Архив рубрики: PHP

Zend Framework: идеальное веб-приложение (ч. 1 из 2)

Часть вторая

Задача: написать веб-приложение с помощью Zend Framework 1.10.x, которое идеально использовало бы возможности фреймворка для определенного функционала.

Лирическое отступление: конечно, по определению невозможно создать что-то идеальное, поскольку идеальное – это совокупность субъективных образов объективной реальности, а раз программистов много и у всех свои мнения по разным вопросам, то и договориться до идеального видиния веб-приложения не получится. Однако, ведь, всё-равно хочется сделать что-то по-настоящему хорошее и масимально близко к идеалу, правда?) И в действительности к стандартизации, идеализации кода приложений всё дело и идет. Яркий пример тому относительно недавно появившиеся тенденции к использованию паттернов и фреймворков.

Так к чему это всё? В n-ый раз перечитывая нередко меняющийся Zend Framework Quickstart, я заметил, что у них постепенно получается четкая и абсолютно прозрачная схема разработки веб-приложения. Для каждого случая, будь-то работа с формами или выемка данных из БД, есть свой паттерн, общепринятое решение (ну ладно, не всеобщее, а принятое умными дядьками из Zend). Значит, теоретически вполне возможно привести культуру написания кода к такому уровню, что программисты будут писать одинаковый, абсолютно правильный и понятный каждому код, свободный от уязвимостей и ошибок. Увидев постановку задачи, два абсолютно разных программиста в уме уже разметят будущую архитектуру веб-приложения, наборы классов и интерфейсов, и эти архитектуры будут абсолютно идентичны. Вроде Java Beans именно для этого и придумали, да? Для мира php я пока такого не встречал.

Скажете, это будет слишком грустно и неинтересно? Достигнув определенного уровня знания, программирование превратиться в рутину, однообразное складывание одних и тех же кирпичиков, в банальное ремесло? Как знать! Из простых каменных блоков строят и пирамиды в Египте, и великие китайские стены. В конце концов, важнее всего качественный и надежный результат. Впрочем, хватит лирики.)

Что же будет в этой статье? В ней приводится пример веб-приложения, в котором я попробую максимально верно использовать ZF и небольшой набор паттернов для решения простых и рутинных проблем, типа выемки данных из БД, запихивания их в формы, отображения списков и прочее. Конечно, это только моё видиние решения, и чувствуется, что некоторые паттерны я использую не совсем так, и вообще, логика обработки запросов должна быть не в том маппере, а вот в той модели и пр. пр. пр…)

Что будет в приложении:

  • Формы добавления и редактирования записей о научных статья, в том числе с возможностью загрузки статей в различных форматах;
  • Страница со списком всех размещенных статей.

Что будет «под капотом»:

  • Модели и мапперы для основных сущностей (статей и авторов);
  • Отдельные классы-шлюзы для работы с таблицами в БД;
  • Связка классов-шлюзов для выполнения агрегирующих запросов (в случае связей один-ко-многим, многие-ко-многим).

Ну поехали.)

Читать далее

Zend Framework: включение профайлера для FirePHP

Задача: включить профилирование всех запросов к БД.

Решение: в основном файле загрузчика приложения (типа «/application/Bootstrap.php»)  добавить следующий код:

    /**
     * FirePHP profiler enable
     */
    protected function _initProfiler() {
    	$this->bootstrap('db');
        $db = $this->getPluginResource('db');
    	$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
		$profiler->setEnabled(true);
		$db->getDbAdapter()->setProfiler($profiler);
    }

Up!

В комментариях Roman подсказал еще более удобный способ включения профайлера через конфигурационный файл («/application/configs/application.ini»):

resources.db.params.profiler.enabled = "true"
resources.db.params.profiler.class = "Zend_Db_Profiler_Firebug"

Ссылки по теме

  • FirePHP — дополнение к FireBug, которое позволяет писать в консоль FireBug.

PS: по секрету скажу, что скоро будет добрая статья про один из самых удобнейших способов работы с БД с помощью Zend_Db. Приглашенные звезды: паттерны data mapper и model, класс Zend_Form. Мы разберемся, как делать запросы типа $row->getAuthorsByPaper()  в действительном отсутствии такого метода!)

Мой диплом о разработке и вводе в эксплуатацию веб-приложения

Буквально месяц назад в славном Московском Техническом Университете Связи и Информатики я защищал диплом «Разработка и ввод в эксплуатацию веб-приложения „Сурдосервер“».

Веб-приложение я начинал разрабатывать еще с августа 2009 года в рамках своей работы в лаборатории вместе со своими коллегами, за мной была инженерная часть и проектирование взаимодействия. Самые интересные моменты в плане разработки я апериодически выкладывал в этом блоге. Настала пора опубликовать и сам диплом. Самим приложением можно воспользоваться на сайте http://surdoserver.ru/.

Самые нетерпеливые могут сразу перейти к разделу со ссылками для скачивания всего этого добра.

О дипломе

Что внутри: в дипломе описан весь цикл разработки современного веб-приложения. Что он включает в себя:

  1. Исследование вопроса;
  2. Определение целей, достигать которые поможет веб-приложение;
  3. Экономический расчет;
  4. Проектирование пользовательского взаимодействия (проектирование интерфейса);
  5. Проектирование БД;
  6. Проектирование программной архитектуры;
  7. Разработка;
  8. Тестирование (в том числе нагрузочное тестирование);
  9. Ввод в эксплуатацию.

В этом дипломе в силу правил составления, расчет экономического эффекта (или т.н. технико-экономического обоснования) находится практически в самом конце, и, откровенно говоря, советую особо не вчитываться в полученные цифры, т.к. сделаны довольно… оптимистичные прогнозы =). Также отсутствует описание процесса тестирования кода, однако есть нагрузочное тестирование.

Что использовалось при разработке и какие результаты:

  • Создано полноценное приложение, которое содержит в себе свыше 400 страниц программного кода;
  • Использовались технологий: PHP, Zend Framework, JavaScript, HTML, Adobe Flex, ActionScript 3;
  • Приобретен и настроен «с нуля» удаленный сервер на основе «облачных» вычислений для обеспечения бесперебойной работы приложения в сети Интернет;
  • Приложение размещено на сервере, получены первые положительные отзывы пользователей на форуме глухих, в социальной группе глухих в сети «вКонтакте», а также посредством встроенной системы обратной связи;
  • В период с 1 февраля по 1 июня 2010 года сайт посетило более 4 100 уникальных пользователей, которые совершили более 88 000 переходов по сайту.

Содержание дипломной работы

  • ВВЕДЕНИЕ
  • Глава 1 Проектирование приложения
    • 1.1 Исследование предметной области
      • 1.1.1  Язык жестов
      • 1.1.2  Современные методы обучения языку жестов
      • 1.1.3  Актуальность проблемы интерактивного веб-приложения для изучения русского языка жестов
    • 1.2   Назначение и основные возможности проектируемого приложения
    • 1.3   Общая архитектура приложения
    • 1.4  Проектирование серверной части
    • 1.5    Проектирование базы данных
      • 1.5.1  Системный анализ предметной области
      • 1.5.2  Инфологическое проектирование
      • 1.5.3  Даталогическое проектирование
      • 1.5.4  Физическое проектирование
    • 1.6  Проектирование клиентской части
  • Глава 2 Технологическая платформа приложения
    • 2.1  Требования к серверной части приложения
      • 2.1.1  Операционная система
        • 2.1.1.1  Обзор современных сетевых ОС
        • 2.1.1.2  Выбор ОС в соответствии с предъявленными требованиями
      • 2.1.2  Система управления базами данных
        • 2.1.2.1 Обзор современных СУБД
        • 2.1.2.2 Выбор СУБД в соответствии с предъявленными   требованиями
      • 2.1.3  Языки программирования
      • 2.1.4  Веб-сервер
        • 2.1.4.1  Обзор современных веб-серверов
        • 2.1.4.2 Выбор веб-сервера в соответствии с предъявленными  требованиями
    • 2.2  Требования к клиентской части приложения
  • Глава 3 Техническая платформа
    • 3.1 Серверное аппаратное оснащение
    • 3.2 Клиентское аппаратное оснащение
  • Глава 4 Описание разработанных компонентов
    • 4.1  Архитектура приложения
      • 4.1.1  Теория
      • 4.1.2  Используемая архитектура
      • 4.1.3  Файловая структура
    • 4.2  Разработанные модули
      • 4.2.1  Сурдо
      • 4.2.2  Дактильная азбука
      • 4.2.3  Страницы
      • 4.2.4  Обратная связь
      • 4.2.5  Поиск
      • 4.2.6  Административная панель
  • Глава 5 Введение приложения в эксплуатацию
    • 5.1  Размещение в сети Интернет
      • 5.1.1 Обзор и выбор способов размещения приложения в сети Интернет
      • 5.1.2  Настройка серверов, подключение доменов
      • 5.2.2  Размещение приложения
      • 5.1.4  Настройка резервного копирования
    • 5.2  Нагрузочное тестирование
      • 5.2.1  Методология тестирования
      • 5.2.2  Результаты тестирования
        • 5.2.1.1  Loadimpact.com
        • 5.2.2.2  Apache JMeter
  • Глава 6 Разработка вопросов по экологии и безопасности жизнедеятельности
    • 6.1  Характеристика условий труда программиста
    • 6.2 Анализ опасных вредных факторов и возможных чрезвычайных ситуаций, возникающих во время работы программиста
      • 6.2.1  Уровень шума на рабочем месте
      • 6.2.2  Электромагнитное и ионизирующее излучения
      • 6.2.3  Статические нагрузки и монотонность труда
      • 6.2.4  Недостаточная освещенность
    • 6.3  Разработка мер безопасности
      • 6.3.1  Снижение уровня шума
        • 6.3.1.1  Теория
        • 6.3.1.1  Расчетная часть
      • 6.3.2  Приобретение оборудования, отвечающего стандартам  безопасности
      • 6.3.3  Устранение статических нагрузок и монотонности труда
      • 6.3.4  Расчет освещенности рабочего места программиста
    • 6.4  Выводы
  • Глава 7 Технико-экономического обоснование проекта
    • 7.1  Постановка задачи
    • 7.2  Стоимость разработки приложения
      • 7.2.1  Определение реальных сроков и количества участников разработки и внедрения приложения
      • 7.2.2  Расчет заработной платы персонала
      • 7.2.3  Расчет затрат на приобретение необходимых аппаратных и программных средств для разработки приложения
      • 7.2.4  Расчет затрат на размещение сайта в сети Интернет
      • 7.2.5 Расчет всех затрат
    • 7.3  Оценка эффективности от внедрения приложения
      • 7.3.1  Косвенная экономия средств
      • 7.3.2  Доход от работы сервиса
  • ЗАКЛЮЧЕНИЕ
  • СПИСОК ЛИТЕРАТУРЫ
  • Приложение А Программные листинги
  • Приложение Б Графические интерфейсы

Плакаты:

Сам диплом в pdf-формате.

При желании в качестве благодарности вы можете купить дипломную работу здесь.

Заметки на полях 2

Включение code hinting с ASDoc для OSMF

Задача: включить в Flash Builder подсказки с кодом с включенными в них описанием классов и их свойств для работы с Open-Source Media Framework (OSMF).

Решение:

  1. Скачиваем исходники OSMF
  2. Разархивируем их на компьютер
  3. В Flash Builder выбираем Import > Existing projects into workspace
  4. Щелкаем «Browse» и находим место, куда распаковали архив с OSMF (например, «C:\osmf_source_v1-0\framework\OSMF»)
  5. Теперь создаем или выбираем существующий проект, в котором нужна поддержка OSMF. Выбираем его свойства (Properties).
  6. Находим вкладку «Library path» (для чисто AS проектов вкладка будет в пункте «ActionScript Build Path»)
  7. Щелкаем «Add project…»
  8. Выбираем «OSMF»

That’s all, folks.)

Сервис по сборке Zend Framework в один файл

Когда неудобно таскать с собой оригинальный Zend Framework с его тысячами файлов, то лучшим решением будет использовать версию ZF, размещенную в одном файле. Для этой цели существует сервис по сборке ZF в один файл — ZF Packer.

Советую полностью исключать из сборки Zend_Test, т.к. он будет требовать установленный PHPUnit.

Еще говорят, что использование такой сборки поднимает производительность, т.к. весь файл перетечет в ОЗУ, но у меня на боевом сервере наблюдался обратный эффект: время отклика увеличилось в два раза.

Zend Framework: объединение кнопок в форме в одну линию в Zend_Form

Задача: объединить, сгенерированные Zend_Form, кнопки «Обновить» и «Удалить», так чтобы они располагались на одной линии.

Решение: использование декораторов и DisplayGroup.

		$this->addElement (new Zend_Form_Element_Submit('submit', array(
            	'label'	=> 'Обновить',
        		'class'	=>	'ui-state-default ui-corner-all ui-button',
				'decorators'	=>	array('ViewHelper')
		  	))
		);

        $this->addElement (new Zend_Form_Element_Button('delete', array(
            	'label'	=> 'Удалить',
        		'id'	=>	'delete-button',
        		'class'	=>	'ui-state-default ui-corner-all ui-button',
        		'decorators'	=>	array('ViewHelper')
        	))
        );

       $this->addDisplayGroup(array('submit', 'delete'), 'submitButtons', array(
	        'decorators' => array(
	            'FormElements',
	            array('HtmlTag', array('tag' => 'div', 'class' => 'form-buttons')),
	        ),
	   ));

Здесь $this — это потомок класса Zend_Form, т.е. class Application_Model_Form_User extends Zend_Form.
Получится что-то типа такого:

Пример интерфейса с кнопками в одну линию в Zend_Form

Пример интерфейса с кнопками в одну линию в Zend_Form

Как это работает

В объявлении каждого элемента мы оставляем только один декоратор, который выводит только сам элемент. Эти элементы без декораторов мы добавляем в одну визуальную группу на основе div и для возможности стилизации в CSS добавляем группе класс «form-buttons».

Zend Framework: пример помощников вида для интеграции ElRTE и ElFinder

Задача: унифицировать и упростить задачу инициализации текстового редактора ElRTE и файлового менеджера ElFinder.

Решение: использование специально для этого придуманных помощников вида (view helpers) в ZF.

Я использую ElRTE и ElFinder в административной панели сайта. Это наиболее удобные инструменты для визуального редактирования html-контента, а также для работы с файлами на серверами. Посему пример будет для модуля admin. Впрочем, сменив название модуля на Application, пример прекрасно подойдет для модуля по умолчанию (тот который в основной папке «/application/»).

Так что же надо сделать, чтобы получить возможность максимально легко включать эти инструменты на сайте, и при этом также легко обновлять их с помощью простой замены файлов на сервере или смены в одном единственном месте пути до редакторов? Поехали:

  1. Создаем модульное приложение на ZF с модулем «admin». Подробнее об этом можете прочитать в одной из предыдущих моих записях.
  2. Скачиваем и сохраняем в «/public/js/» ElRTE и ElFinder
  3. Настраиваем коннектор для ElFinder
  4. Создаем файл «/application/modules/admin/view/helpers/EnableElRTE.php» со следующим содержимым:
    <?php
    /**
     * Class inserts neccery code for initialize rich text editor ElRTE
     */
    class Admin_View_Helper_EnableElRTE extends Zend_View_Helper_Abstract{
    
    	public function enableElRTE() {
    		$elrte_base_uri = "/js/back-end/elrte-1.0rc4/";
    
    		$this->view->headLink()->appendStylesheet("{$elrte_base_uri}css/elrte.full.css");
    		$this->view->headScript()->appendFile("{$elrte_base_uri}js/elrte.min.js");
    		$this->view->headScript()->appendFile("{$elrte_base_uri}js/i18n/elrte.ru.js");
       	}
    }
    
  5. Создаем файл «/application/modules/admin/view/helpers/EnableElFinder.php»:
    <?php
    /**
     * Class inserts neccery code for initialize file manager ElFinder
     *
     * @author Dimitry Dushkin
     *
     */
    class Admin_View_Helper_EnableElFinder extends Zend_View_Helper_Abstract{
    
    	public function enableElFinder() {
    		$elfinder_base_uri = "/js/back-end/elfinder-1.1/";
    
    		$this->view->headLink()->appendStylesheet("{$elfinder_base_uri}css/elfinder.css");
    		$this->view->headScript()->appendFile("{$elfinder_base_uri}js/elfinder.min.js");
    
    		$this->view->headScript()->captureStart() ?>
    			var opts = {
    				lang : 'ru',
    				styleWithCss : false,
    				width	: 800,
    				height  : 200,
    				toolbar : 'normal',
    				fmAllow  : true,
    				fmOpen   : function(callback) {
    					$('<div id="myelfinder" />').elfinder({
    					   	url : '<? echo $elfinder_base_uri?>connectors/php/connector.php',
    						lang : 'ru',
    						dialog : { width : 900, modal : true, title : 'Файлы' }, // открываем в диалоговом окне
    						closeOnEditorCallback : true, // закрываем после выбора файла
    						editorCallback : callback
    		            })
    	       		}
    	        };
           	<?php $this->view->headScript()->captureEnd();
       	}
    }
    
  6. В представлении IndexAction IndexController’a модуля admin (по умолчанию такие штуки располагаются в «/application/modules/admin/view/scripts/index/index.phtml») пишем следующее:
    
    <? echo $this->enableElRTE();?>
    <? echo $this->enableElFinder();?>
    
    <script type="text/javascript">
         $().ready(function() {
              // создаем редактор
              $('.rte_textarea').elrte(opts);
         });
    </script>
    <form method="get">
         <textarea name="content" id="content" class="rte_textarea" rows="5" cols="45"></textarea>
    </form>
    
  7. В основном шаблоне («/application/layouts/scripts/index.phtml») при этом должно быть что-то типа такого (стандартный код для шаблонов ZF):
    <?php echo $this->doctype() ?>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    	<?php echo $this->headTitle() ?>
    	<?php echo $this->headMeta() ?>
    	<?php echo $this->headLink() ?>
    	<?php echo $this->headScript() ?>
    </head>
    <body>
             <?php echo $this->layout()->content ?>
    </body>
    </html>
    
  8. Удостоверяемся, что все работает как надо, пройдя по ссылке типа http://localhost/admin/index/index

Получим что-то типа такого

семейное фото ElRTE и ElFinder

семейное фото ElRTE и ElFinder

Как это работает

Помощники вида необходимы для динамического добавления необходимых элементов в выходной html-код. Как видно, каждый наш помощник является потомком класса Zend_View_Helper_Abstract, который реализует интерфейс, позволяющий получить доступ к глобальному объекту Zend_View, который как раз и отвечает за выходной html-код.

В каждом помощнике мы обращаемся к стандартным помощникам вида (HeadScript Helper для добавления js-файлов и js-кода и HeadStyle Helper для добавления файлов стиля) через глобальный объект Zend_View.

Ссылки в записи

 

UPDATE: по твиттеру товарищ Вредный рассказал о своём усовершенствованном решении этого вопроса. Там предлагается подключать elRte и elFinder в описании формы.

Zend Framework: включение модульной архитектуры

К сожалению, не все рутинные задачи доступны с помощью Zend_Tool. Одна из таких задач — включение механизма модульной архитектуры, что на самом деле немного удивительно, т.к. команда на создание модуля со структурой по умолчанию существует.

Путь создания приложения с нуля с помощью Zend_Tool довольно прост:

  1. Удостоверяемся, что есть доступ к zf.sh (для Linux) или zf.bat (для Windows);
  2. Заходим в директорию, в которой хотим создать приложение, например так
    cd /home/user/data/www/example.ru/
    
  3. Cоздаем проект Zend Framework:
     zf create project example
     
  4. Включаем поддержку шаблонов (layout):
     zf enable layout
     
  5. Создаем, например, модуль video:
     zf create module video
     
  6. Создаем для него Index контроллер с действием IndexAction:
     zf create controller Index index-action-included video
     
  7. В файле /application/config/application.ini включаем поддержку модулей, вписав после тега [production] следующее:

    resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
    resources.modules[] =
  8. Для включения автозагрузки классов модуля (моделей или форм, например) в корне папки модуля (/application/modules/video/) создаем файл Bootstrap.php со следующим содержимым:
    <?php class Video_Bootstrap extends Zend_Application_Module_Bootstrap {}

Вот и всё, все дело в последнем шаге. К сожалению, без него стандартные правила направления запросов к модулю не работают, то есть запрос типа:

example.ru/video/index/index

вызовет ошибку, хотя должен был вызвать IndexAction в IndexController в модуле video.
Строка «resources.modules[] =» включает автозагрузку классов для модулей.

Созданное в записи приложение с моим небольшим изменением для показа времени выполнения скриптов можно скачать по этой ссылке.

Ссылки в записи