Автор: Rob Allen, www.akrabat.com
Также доступна устаревшая версия руководства, ориентированная на старые версии Zend Framework.
Это руководство предназначено для введения в использование Zend Framework для создания простых приложений с использованием БД с использованием парадигмы Model-View-Controller. Оно было переписано для версии фреймворка 1.8 и использует все преимущества скриптов командной строки Zend_Tool и Zend_Application для бутстраппинга. Используются другие компоненты, включая Zend_Controller, Zend_View, Zend_Db_Table и Zend_Form.
Замечание: Это руководство было тестировано на Zend Framework версии 1.10. Есть хорошие шансы, что оно будет работать с более поздними версиями ветки 1.*, но оно гарантированно не будет работать с версиями ранее 1.10.
Если вы получаете ошибки 404 когда открываете любую страницу, кроме главной, убедитесь, что директива AllowOverride в конфигурационном файле Apache установлена в значение All и включено расширение mod_rewrite.
Если вы развёртываете “пользовательский” сайт (например, http://localhost/~rob), вам необходимо использовать строку RewriteBase в файле .htaccess, например: RewriteBase /~rob/zf-tutorial/public/.
Исходный код
Исходный код руководства доступен в виде zip-архива.
Требования
Zend Framework имеет следующие требования:
- PHP 5.2.4 (или выше)
- Веб-сервер с поддержкой mod_rewrite или аналогичного функционала.
Условности
Предполагается, что у вас запущен PHP 5.2.4 с веб-сервером Apache. Ваш Apache должен иметь установленное и настроенное расширение mod_rewrite.
Также вы должны быть уверены, что Apache настроен для поддержки файлов .htaccess. Обычно для этого достаточно изменить параметр:
AllowOverride None
на
AllowOverride All
в вашем файле httpd.conf. За деталями обратитесь к документации веб-сервера. Вам не будет доступна ни одна страница на вашем сайте, кроме главной, если mod_rewrite и .htaccess не будут корректно настроены.
Получение Zend Framework
Загрузить Zend Framework вы можете с официального сайта в виде архивов .zip и .tar.gz.
Настройка Zend_Tool
Zend_Tool для Windows
- Создайте новую директорию в Program Files и назовите её ZendFrameworkCli
- Откройте скачанный архив.
- Скопируйте папки bin и library из архива в папку C:\Program Files\ZendFrameworkCli. Папка должна иметь две подпапки: bin и library.
- Добавьте директорию bin в переменную окружения “Path”:
- Откройте окно “Система” в панели управления
- Выберите вкладку дополнительно нажмите на кнопку “Переменные среды”
- В списке “Системные переменные” найдите переменную “Path” и дважды кликните по ней.
- Добавьте “;C:\Program Files\ZendFrameworkCli\bin” в конец поля воода и нажмите “OK”. (точка с запятой обязательны!)
- Перезагрузитесь
Zend_Tool для OS X (Аналогично для Linux)
- Распакуйте скачанный архив,, ZendFramework-1.8.0-minimal.zip в вашу папку загрузок и откройте его.
- Скопируйте содержимое в /usr/local/ZendFrameworkCli, выполнив в консоли команду:
sudo cp -r ~/Downloads/ZendFramework-1.8.0-minimal /usr/local/ZendFrameworkCli - Отредактируйте ваш bash-профиль для создания alias’а
- В консоли наберите: open ~/.bash_profile
- В конец файла добавьте: alias zf=/usr/local/ZendFrameworkCli/bin/zf.sh
- Сохраните и закройте текстовый редактор
- Закройте терминал
Тестирование Zend_Tool
Вы можете проверить, корректно ли установлен Zend_Tool, набрав в консоли (командной строке) следующее:
1 | zf show version |
Если всё работает, вы увидите следующее:
1 | Zend Framework Version: 1.8.0 |
Если нет, проверьте, верно ли вы указали путь и существует ли директория bin в каталоге ZendFrameworkCli. Если Zend_Tool работает, вы можете увидеть все доступные команды при помощи “zf –help”
Что мы будем делать?
Мы создадим очень простую систему для отображения нашей коллекции CD. Главная страница будет отображать нашу коллекцию в виде списка, и позволит нам добавлять, редактировать и удалять CD-диски.
Нам потребуются следующие страницы:
| Главная страница | Будет выводить список альбомов и ссылки для редактирования и удаления их. Также будет доступна ссылка для добавления нового альбома |
|---|---|
| Добавление нового альбома | На странице будет отображаться форма для добавления нового альбома |
| Редактирование альбома | Форма для редактирования альбома |
| Удаление альбома | Страница будет запрашивать подтверждение на удаление альбома, с последующим удалением |
Также нам понадобится хранилище наших данных в БД. Создадим таблицу со следующими полями:
| Название поля | Тип | Null? | Дополнительно |
|---|---|---|---|
| id | integer | No | Primary key, auto increment |
| artist | varchar(100) | No | |
| title | varchar(100) | No |
Начинаем наше приложение
Пришло время начать разработку. Где возможно, мы будем использовать утилиту командной строки ZF, т.к. это значительно экономит наше время и силы. Первая задача – создать скелет проекта, состоящий из файлов и каталогов.
Откройте консоль или командную строку и измените каталог на корневой вашего веб-сервера, используя команду cd. Убедитесь, что у вас достаточно прав для создания файлов в этом каталоге. Введите:
1 | zf create project zf-tutorial |
Утилита ZF создаст директорию с именем zf-tutorial и наполнит её рекомендуемой структурой директорий. Эта структура предполагает, что конфигурация Apache позволяет вам хранить многие файлы вне публичного каталога сервера. Вы должны увидеть следующие файлы и каталоги:

(здесь не отображён скрытый файл .htaccess в каталоге public)
В каталоге /application расположен исходный код вашего веб-сайта. Как вы можете наблюдать, мы имеем раздельные каталоги для файлов моделей, вида и контроллеров вашего приложения. Каталог /public является публично-доступным корневым каталогом сайта, который будет открываться по URL http://localhost/zf-tutorial/public/. Таким образом, большая часть файлов вашего приложения не будет доступна напрямую через Apache, что обеспечивает большую безопасность.
Замечание: Для живого веб-сайта вам надо будет создать VirtualHost и направить DocumentRoot напрямую на каталог /public. Например, вы можете создать VirtualHost с именем zf-tutorial.localhost, и он будет выглядеть похоже на это:
1 2 3 4 5 6 7 | <VirtualHost *:80> ServerName zf-tutorial.localhost DocumentRoot /var/www/html/z-ftutorial/public <Directory "/var/www/html/zf-tutorial/public"> AllowOverride All </Directory> </VirtualHost> |
Сайт будет доступен по URL http://zf-tutorial.localhost/ (для этого вам следует обновить файл /etc/hosts или c:\windows\system32\drivers\etc\hosts, направив zf-tutorial.localhost на 127.0.0.1). Мы не делаем этого в нашем руководстве потому, что это так же просто, как и использование подкаталога для тестирования.
Изображения, JavaScript и CSS-файлы храните в раздельных директориях внутри /public. Скачанный Zend Framework будет расположен в директории /library. Если вам понадобится использовать другие библиотеки, вы можете также разместить их там.
Скопируйте директорию /library/Zend из скачанного архива в ваш zf-tutorial/library/ таким образом, чтобы ваш zf-tutorial/library/ имел подкаталог Zend/.
Теперь вы можете проверить, всё ли в порядке, открыв URL http://localhost/zftutorial/public. Вы должны увидеть что-то вроде этого:

Бутстраппинг
Контроллер Zend Framework’а использует паттерн проектирования Front Controller и направляет все запросы через один файл – index.php. Это гарантирует, что окружение корректно настроено для запуска приложения (процесстакже известен как бутстраппинг). Мы используем файл .htaccess в каталоге /zf-tutorial/public, который был сгенерирован при помощи Zend_Tool. Он направляет все запросы на файл index.php, который, в свою очередь, тоже сгенерирован Zend_Tool.
Файл index.php является стартовым пунктом в нашем приложении и используется для создания экземпляра Zend_Application, который, в свою очередь, инициализирует наше приложение и запускает его. Файл также определяет две константы: APPLICATION_PATH и APPLICATION_ENV, которые определяют путь к директории application/ и режим работы приложения соответственно. Режим указывается в .htaccess и по умолчанию имеет значение development.
Компонент Zend_Application используется для запуска приложения и настраивается при помощи конфигурационного файла: application/config/application.ini. Этот файл также генерируется автоматически.
Класс бутстраппинга наследует Zend_Application_Bootstrap_Bootstrap и расположен в application/Bootstrap.php. Он может использоваться для выполнения любого специфичного кода при запуске приложения.
Файл application.ini, который хранится в каталоге application/configs, загружается с помощью компонента Zend_Config_Ini. В этом файле допустимо использование наследования секций:
1 | [staging : production] |
Это значит, что секция staging наследует все параметры секции production. Константа APPLICATION_ENV определяет, какая секция будет загружена. Во время разработки лучше всего использовать секцию development, а для уже запущенного приложения – секцию production.
Редактирование файла application.ini
Несмотря на то, что Zend_Tool создаёт работоспособный конфигурационный файл, мы можем добавить в наше приложение специфичные настройки. Отредактируйте application/configs/application.ini и добавьте:
1 | phpSettings.date.timezone = "Europe/Moscow" |
Добавить это надо после всех значений phpSettings в секцию [production]. Здесь вам следует написать свой часовой пояс. Теперь мы готовы к написанию специфичного кода нашего приложения.
Специфичный код приложения
Прежде чем мы будем настраивать наши файлы, важно понять, как в Zend Framework организованы страницы. Каждая страница приложения является Действием (action), и действия сгруппированы в Контроллеры (controllers). Для URL формата http://localhost/zf-tutorial/public/news/view будет использоваться контроллер News и действие view. Это позволяет группировать схожие действия по смыслу. Например, контроллер news имеет действия list, archived и view. MVC в Zend Framework поддерживает модули для группировки контроллеров вместе, но это приложение не настолько большое, чтобы беспокоиться об этом.
Также следует заметить, что если имя контроллера или действия не указано, используется имя index. Таким образом, URL http://localhost/zf-tutorial/public/ выполнит действие index контроллера index.
Так как это базовое руководство, мы не будем осваивать “продвинутые” вещи, наподобие аутентификации. Об этом написано отдельное руководство (или читайте об этом в книге Zend Framework in Action).
Мы имеем четыре страницы для управления альбомами, мы сгруппируем их в один контроллер и четыре действия. Мы будем использовать контроллер по умолчанию и четыре действия:
| Страница | Controller | Action |
|---|---|---|
| Главная страница | index | index |
| Добавление нового альбома | index | add |
| Редактирование альбома | index | edit |
| Удаление альбома | index | delete |
Если сайт становится сложным, вы можете группировать контроллеры в модули.
Настройка контроллера
Теперь мы готовы к настройке нашего контроллера. В Zend Framework контроллер это класс, который должен называться {Controller name}Controller. Заметьте, что {Controller name} должен начинаться с заглавной буквы. Файл, который будет содержать этот класс, должен быть назван {Controller name}Controller.php и распологаться в директории application/controllers. Каждое действие – это публичный метод в классе контроллера с именем {action name}Action. В этом случае {action name} должен начинаться с маленькой буквы, и все последующие буквы тоже должны мыть в нижнем регистре. Смешанный регистр символов в именах контроллеров и действий разрешён, но он обрабатывается по специальным правилам, которые вам следует понять, прежде чем их использовать. В первую очередь, просмотрите документацию.
Наш класс контроллера называется IndexController, который определён в application/controllers/IndexController.php и был автоматически сгенерирован при помощи Zend_Tool. Нам надо лишь добавить дополнительные действия.
Добавление дополнительных действий контроллера производится при помощи утилиты командной строки zf. Откройте командную строку и измените директорию на ваш каталог zf-tutorial/. После выполните следующие команды:
1 2 3 | zf create action add index zf create action edit index zf create action delete index |
Эти команды создают три метода: addAction, editAction, deleteAction в IndexController и соответствующие им скрипты вида, которые нам понадобятся позже. Сейчас мы имеем четыре настроеных и готовых к использованию действия.
URL’ы действий следующие:
| URL | Класс и метод |
|---|---|
| http://localhost/zf-tutorial/public | IndexController::indexAction() |
| http://localhost/zf-tutorial/public/index/add | IndexController::addAction() |
| http://localhost/zf-tutorial/public/index/edit | IndexController::editAction() |
| http://localhost/zf-tutorial/public/index/delete | IndexController::deleteAction() |
Вы можете протестировать их и должны увидеть следующую надпись:
1 | View script for controller index and script/action name add |
Замечание: Если вы получаете ошибку 404, значит ваш Apache или модуль mod_rewrite не настроен должным образом, или параметр AllowOverride в вашем Apache не позволяет использовать .htaccess в каталоге public/.
База данных
Сейчас мы имеем скелет приложения с методами действий контроллера и файлы вида, самое время взглянуть на секцию “модель” нашего приложения. Запомните, что модель содержит код ядра нашего приложения и, в нашем случае, код взаимодействия с БД. Мы будем использовать класс Zend_Db_Table, который используется для поиска, вставки, обновления и удаления строк из БД.
Конфигурирование БД
Для использования Zend_Db_Table нам необходимо сообщить с какой БД мы будем работать, имя пользователя и пароль. Чтобы не прописывать это жёстко в нашем приложении мы будем использовать файл конфигурации для хранения этой информации. Компонент Zend_Application имеет ресурс для работы с БД, поэтому нам достаточно лишь указать данные в файле configs/application.ini.
Откройте файл configs/application.ini и добавить следующие строки в конец секции [production] (т.е. перед секцией [staging]):
1 2 3 4 5 | resources.db.adapter = PDO_MYSQL resources.db.params.host = localhost resources.db.params.username = rob resources.db.params.password = 123456 resources.db.params.dbname = zf-tutorial |
Разумеется, вы должны использовать свои имя пользователя, пароль и имя БД. Теперь для нас будет создано соединение с БД и автоматически настраиваемый Zend_Db_Table. Вы можете узнать больше о доступных плагинах ресурсов здесь: http://framework.zend.com/manual/en/zend.application.available-resources.html
Создание таблицы БД
Как мы изначально планировали, будем использовать БД для хранения данных о наших альбомах. Я использую MySQL и соответствующее SQL-выражение для создания таблицы:
1 2 3 4 5 6 | CREATE TABLE albums ( id int(11) NOT NULL AUTO_INCREMENT, artist varchar(100) NOT NULL, title varchar(100) NOT NULL, PRIMARY KEY (id) ); |
Запустите это выражение в MySQL-клиенте (например, phpMyAdmin) или стандартной командной строке MySQL.
Вставка тестовых альбомов
Сейчас нам нужно вставить несколько строк в таблицу, чтобы мы могли видеть функциональность нашего приложения.
Я возьму несколько топовых CD из магазина Amazon UK. Запустите следующий код в вашем MySQL-клиенте:
1 2 3 4 5 6 7 | INSERT INTO albums (artist, title) VALUES ('Paolo Nutine', 'Sunny Side Up'), ('Florence + The Machine', 'Lungs'), ('Massive Attack', 'Heligoland'), ('Andre Rieu', 'Forever Vienna'), ('Sade', 'Soldier of Love'); |
Теперь у нас есть некоторые данные в БД и мы можем писать очень простые модели для них.
Модель
позволяет вам самим решить, как она должна работать. Есть много компонентов, которые вы можете использовать для этого по мере необходимости. Один подход заключается в том, чтобы представить каждую сущность в вашем приложении и использовать объекты-мапперы, чтобы извлечь или сохранить данные в БД. Этот подход описан в Zend Framework QuickStart здесь: http://framework.zend.com/manual/en/learning.quickstart.create-model.html
В этом руководстве мы будем создавать модели, наследующие Zend_Db_Table и использующие Zend_Db_Table_Row. Zend Framework предоставляет компонент Zend_Db_Table, который реализует паттерн проектирования Table Data Gateway для взаимодействия с данными в таблице БД. Имейте в виду, что паттерн Table Data Gateway может начать ограничивать вас при разработке больших систем. Также возникает соблазн оставить код доступа к БД в методах действий (action) контроллера как голый Zend_Db_Table.
Zend_Db_Table_Abstract – это абстрактный класс, на базе которого мы создаём наш класс для управления альбомами. Не имеет значения, как мы назовём наш класс, но разумно будет назвать его именем таблицы БД. Наш проект имеет загрузчик по умолчанию, который создаётся при помощи Zend_Application, который находит классы ресурсов модуля внутри указанного каталога. Для основных каталогов application/ мы используем префикс Application_.
Автозагрузчик ищет ресурсы в каталогах согласно следующей таблице:
| Префикс | Каталог |
|---|---|
| Form | forms |
| Model | models |
| Model_DbTable | models/DbTable |
| Model_Mapper | models/mappers |
| Plugin | plugins |
| Service | services |
| View_Filter | view/filters |
| View_Helper | view/helpers |
Для работы с нашими альбомами мы создаём класс, наследующий Zend_Db_Table_Abstract с именем Application_Model_DbTable_Albums, размещаться он будет по следующему пути: applications/models/DbTable/Albums.php
Чтобы указать, какую таблицу БД следует использовать, используйте protected-свойство класса $_name, в котором должно храниться имя таблицы. Также Zend_Db_Table преполагает, что ваша таблица имеет auto-increment первичный ключ с именем id. Имя поля может быть изменено при необходимости.
Создайте файл и введите следующий код:
zf-tutorial/application/models/DbTable/Albums.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <?php class Application_Model_DbTable_Albums extends Zend_Db_Table_Abstract { protected $_name = 'albums'; public function getAlbum($id) { $id = (int)$id; $row = $this->fetchRow('id = ' . $id); if (!$row) { throw new Exception("Count not find row $id"); } return $row->toArray(); } public function addAlbum($artist, $title) { $data = array( 'artist' => $artist, 'title' => $title, ); $this->insert($data); } public function updateAlbum($id, $artist, $title) { $data = array( 'artist' => $artist, 'title' => $title, ); $this->update($data, 'id = '. (int)$id); } public function deleteAlbum($id) { $this->delete('id =' . (int)$id); } } |
Мы создаём четыре метода-помощника, которые будут использоваться как в нашем приложении как интерфейс к таблице БД. getAlbum() достаёт из БД одну запись в виде массива, addAlbum создаёт новую запись в БД, updateAlbum() обновляет запись альбома и deleteAlbum() удалён запись совсем. Код каждого из этих методов сам отлично объясняет себя. Также возможны связи таблиц и выбора связанных данных из БД, но в этом руководстве мы об этом говорить не будет.
Нам необходимо получить в контроллерах данные из моделей и получить скрипты вида для отображения их. Но, прежде чем мы это сделаем, нам необходимо понять как работает система отображения в Zend Framework.
Макеты и виды
Компонент вида Zend Framework, как и следовало ожидать, называется Zend_View. Он позволит нам отделить код отображения страницы от кода действий.
Базовое использование Zend_View такое:
1 2 3 | $view = new Zend_View(); $view->setScriptPath('/path/to/scripts'); echo $view->render('script.php'); |
Очень легко писать этот код в каждом нашем действии, но повторение кода – не лучший подход. Мы будем инициализировать отображение по-другому и предоставлять доступ к объекту вида в каждом методе действия. Zend Framework предоставляет для этой цели помощник вида (Action Helper) под названием ViewRenderer. Он берёт на себя задачу инициализации вида, записывает его в свойство класса контроллера ($this->view) для использования его и выводит скрипт вида после выполнения действия.
Для вывода скриптов вида ViewRenderer настраивает Zend_View для поиска скриптов вида в каталоге “views/scripts/{controller name}” с расширением phtml. Таким образом, скрипт вида имеет путь “views/scripts/{controller name}/{action name}.phtml”, содержимое его передаётся в объект ответа для вывода на экран. Объект ответа (Response) используется для объединения вместе HTTP-загловков, тела ответа и исключений, сгенерированных MVC-системой. Front Controller автоматически отправляет заголовки и тело ответа по завершении процесса диспатчинга.
Всё это настраивает для нас Zend_Tool, когда мы создаём проект и добавляем контроллеры и действия с использованием команд “zf create controller” и “zf create action”.
Общий HTML-код: Макеты
Очень быстро становится ясно, что некоторые части HTML-кода дублируются. Например, “шапка” и “подвал”, “сайдбар” или даже два. Это не новая проблема, и для её решения предназначен компонент Zend_Layout. Мы перемещаем “шапку”, “подвал” и другой код в скрипт вида макета (layout), и уже туда подключаем скрипт вида выполняемого действия.
По умолчанию наши макеты хранятся в каталоге application/layouts/. Также доступен ресурс для Zend_Application, который настраивает Zend_Layout. Мы используем Zend_Tool, чтобы создать скрипт вида макета и обновить application.ini для его применения. Откройте терминал или командную строку и введите следующую команду, находясь в корневом каталоге вашего проекта:
1 | zf enable layout |
Zend_Tool создал каталог application/layouts/scripts и поместил в него скрипт вида layout.phtml. Также был обновлён application.ini, в секцию [production] добавлена следующая строка:
1 | resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/" |
В конце цикла диспатчинга, после выполнения действий контроллера, Zend_Layout выведет наш макет (layout). Zend_Tool создал очень простой файл макета, который только выводит нам содержимое скрипта вида выполняемого действия. Дополним его необходимым вебсайту HTML-кодом. Откройте layout.phtml и замените его код на следующий:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php $this->headMeta()->appendHttpEquiv('Content-Type', 'text/html;charset=utf-8'); $this->headTitle()->setSeparator(' - '); $this->headTitle('Zend Framework Tutorial'); echo $this->doctype(); ?> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <?php echo $this->headMeta(); ?> <?php echo $this->headTitle(); ?> </head> <body> <div id="content"> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->layout()->content; ?> </div> </body> </html> |
Файл макета содержит “внешний” HTML-код, который соответствует HTML-стандарту. Так как это нормальный PHP-файл, мы можем использовать в нём PHP, доступна переменная $this, которая содержит экземпляр объекта вида, который был создан во время бутстраппинга. Мы можем использовать его для передачи данных в скрипт вида и вызывать методы. Методы, известные как помощники вида (view helpers), возвращают строку, которую мы можем вывести.
В первую очередь, мы настраиваем некоторые помощники вида для head-секции веб-страницы и также для вывода корректного doctype. Внутри секции
1 |
Это значит, что скрипт вида действия выполняется раньше, чем скрипт вида макета.
Нам необходимо указать doctype для веб-страницы прежде, чем мы выведем любой скрипт вида. Скрипт вида действия выполняется раньше и может возникнуть необходимость узнать, какой doctype используется. В особенности, это может понадобится для Zend_Form. Чтобы указать doctype, мы добавляем следующую строку в application.ini, секция [production]:
1 | resources.view.doctype = "XHTML1_STRICT" |
Помощник вида doctype() выведет корректное определение doctype, и компоненты вроде Zend_Form будут генерировать совместимый HTML-код.
Стилизация
Даже несмотря на то, что это “всего лишь” руководство, нам понадобится CSS-файл для того, чтобы сделать приложение более приятным глазу!
Сложность в том, что мы не знаем полный путь к CSS-файлам, т.к. наше приложение может находится не в корневом каталоге сайта, а в подкаталоге. К счастью, доступен помощник вида baseUrl(), который получает необходимую нам информацию из объекта запроса (Zend_Controller_Request) и передаёт нам URL, который мы не знали.
Теперь мы можем добавить CSS-файл в секцию
1 2 3 4 5 6 7 |
Используя метод appendStylesheet() помощника headLink(), мы можем добавить дополнительные, более специфичные CSS-файлы в скриптах вида контроллера, которые будут выведены в секции
после site.css.И, наконец, мы добавим некоторые необходимые CSS-стили. Создайте подкаталог css в каталоге public/ и добавьте туда site.css, содержащий следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | body,html { margin: 0 5px; font-family: Verdana,sans-serif; } h1 { font-size: 1.4em; color: #008000; } a { color: #008000; } /* Table */ th { text-align: left; } td, th { padding-right: 5px; } /* style form */ form dt { width: 100px; display: block; float: left; clear: left; } form dd { margin-left: 0; float: left; } form #submitbutton { margin-left: 100px; } |
Это должно сделать наше приложение более приятным, но, как вы могли заметить, что я не дизайнер!
Мы имеем четыре скрипта действия, которые были автоматически сгенерированы и готовы к наполнению. Перейдём к пустым файлам index.phtml, add.phtml, edit.phtml, delete.phtml, которые, как вы помните, расположены в каталоге application/views/scripts/index.
Вывод альбомов
Теперь, когда мы закончили с конфигурацией, настройкой БД и скелетом вида, мы можем перейти к основной части нашего приложения и сделать вывод альбомов. Мы реализуем это в IndexController indexAction при помощи следующего кода:
1 2 3 4 5 6 7 8 9 10 | ... function indexAction() { $this->view->title = "My Albums"; $this->view->headTitle($this->view->title); $albums = new Application_Model_DbTable_Albums(); $this->view->albums = $albums->fetchAll(); } ... |
Прежде всего, мы указываем заголовок (title) страницы, который будет выведен в секции
и отображён в заголовке браузера. Метод fetchAll() возвращает zend_Db_Table_Rowset, который позволит нам обойти все полученные строки в скрипте вида.Теперь наполним скрипт вида, application/views/scripts/index/index.phtml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <p><a href="<?php echo $this->url(array('controller' => 'index', 'action' => 'add')) ?>">Добавить новый альбом</a></p> <table> <tr> <th>Title</th> <th>Artist</th> <th> </th> </tr> <?php foreach($this->albums as $album) : ?> <tr> <td><?php echo $this->escape($album->title) ?></td> <td><?php echo $this->escape($album->artist) ?></td> <td> <a href="<?php echo $this->url(array('controller' => 'index', 'action' => 'edit', 'id' => $album->id)) ?>">Редактировать</a> <a href="<?php echo $this->url(array('controller' => 'index', 'action' => 'delete', 'id' => $album->id)) ?>">Удалить</a> </td> </tr> <?php endforeach; ?> </table> |
Первое, на что обратим внимание, это создание ссылки для добавления альбома. Помощник вида (view helper) url() предоставлен фреймворком и помогает создавать ссылки. Мы просто передаём необходимые параметры в виде массива.
Также мы создали HTML-таблицу для вывода заголовка и автора каждого альбома, со ссылками на редактирование и удаление записи. Стандартный цикл foreach используется для вывода альбомов, в данном случае мы используем его альтернативный синтаксис, включающий двоеточие и endforeach – он проще для восприятия в скриптах вида. Опять же, сылки на редактирование и удаление записи мы формируем при помощи помощника вида url().
Если вы откроете страницу http://localhost/zf-tutorial/public/ (или другую, если вы расположили приложение в другом месте), вы увидите список альбомов, как здесь:

Добавление новых альбомов
Теперь мы можем создать функционал для добавления новых альбомов. Он состоит из двух частей:
- Вывод формы ввода для пользователя
- Процесс отправки формы и запись данных в БД
Для этого мы будем использовать Zend_Form. Этот компонент позволяет нам создать форму и провести валидацию данных. Мы создаём новый класс Form_Album, который расширяит Zend_Form определяет нашу форму. Так как форма – ресурс нашего приложения, мы расположим класс в файле Album.php в директории форм. Для создания формы воспользуйтесь командной строкой:
1 | zf create form Album |
Эта команда создаст файл Album.php в application/forms. В версии ZF 1.10.0 и ниже, имя класса будет некорректное. Замените содержимое файла следующим кодом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?php class Application_Form_Album extends Zend_Form { public function __construct($options = null) { parent::__construct($options); $this->setName('album'); $id = new Zend_Form_Element_Hidden('id'); $id->addFilter('Int'); $artist = new Zend_Form_Element_Text('artist'); $artist->setLabel('Музыкант') ->setRequired(true) ->addFilter('StripTags') ->addFilter('StringTrim') ->addValidator('NotEmpty'); $title = new Zend_Form_Element_Text('title'); $title->setLabel('Название') ->setRequired(true) ->addFilter('StripTags') ->addFilter('StringTrim') ->addValidator('NotEmpty'); $submit = new Zend_Form_Element_Submit('submit'); $submit->setAttrib('id', 'submitbutton'); $this->addElements(array($id, $artist, $title, $submit)); } } |
В конструкторе Application_Form_Album мы создаём четыре элемента формы для ID, музыканта, названия альбома и кнопки submit. Для каждого из них мы указываем атрибуты, в том числе label для заголовка поля. В случае с ID мы уверены, что он может быть только integer, для предотвращения потенциальных SQL-инъекций мы используем фильтр Int.
Для текстовых элементов мы добавляем два фильтра, StripTags и StringTrim для удаления нежелательного HTML-кода и лишних пробелов. Также мы добавили валидатор NotEmpty чтобы быть уверенными, что пользователь ввёл необходимые данные.
Теперь нам нужно получить форму для вывода и подготовить её отправку. Делается это при помощи следующего кода в IndexController addAction():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ... function addAction() { $this->view->title = "Add new album"; $this->view->headTitle($this->view->title); $form = new Application_Form_Album(); $form->submit->setLabel('Добавить'); $this->view->form = $form; if ($this->getRequest()->isPost()) { $formData = $this->getRequest()->getPost(); if ($form->isValid($formData)) { $artist = $form->getValue('artist'); $title = $form->getValue('title'); $albums = new Application_Model_DbTable_Albums(); $albums->addAlbum($artist, $title); $this->_helper->redirector('index'); } else { $form->populate($formData); } } } ... |
Немного пояснений по коду.
1 2 3 | $form = new Application_Form_Album(); $form->submit->setLabel('Добавить'); $this->view->form = $form; |
При помощи этого кода мы инстанцируем форму, указываем label для кнопки отправки, после чего передаём форму в скрипт вида для вывода.
1 2 3 | if ($this->getRequest()->isPost()) { $formData = $this->getRequest()->getPost(); if ($form->isValid($formData)) { |
Если метод isPost() объекта запроса (request) возвращает true, значит форма была отправлена. В таком случае, мы получаем данные при помощи метода getPost() и проверяем их валидность при помощи метода isValid().
1 2 3 4 | $artist = $form->getValue('artist'); $title = $form->getValue('title'); $albums = new Application_Model_DbTable_Albums(); $albums->addAlbum($artist, $title); |
Если форма валидна, мы инстанцируем класс модели Application_Model_DbTable_Albums и используем созданный ранее метод addAlbum() для создания новой записи в БД.
1 | $this->_helper->redirector('index'); |
После того, как данные были сохранены, мы используем помощник действия (action helper) Redirector для возвращения обратно к действию index (т.е. на главную страницу).
1 2 3 | } else { $form->populate($formData); } |
Если форма не валидна, мы заполняем элементы формы введёнными пользователем значениями и повторно её выводим.
Теперь нам надо сделать вывод формы в скрипте вида add.phtml
1 |
Как видите, вывод формы очень прост благодаря тому, что форма знает, как выводить саму себя. Теперь вы можете использовать ссылку “Добавить новый альбом” на главной странице приложения для добавления нового альбома.
Редактирование альбома
Редактирование альбома очень похоже на добавление:
zf-tutorial/application/controllers/IndexController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ... function editAction() { $this->view->title = "Edit album"; $this->view->headTitle($this->view->title); $form = new Application_Form_Album(); $form->submit->setLabel('Save'); $this->view->form = $form; if ($this->getRequest()->isPost()) { $formData = $this->getRequest()->getPost(); if ($form->isValid($formData)) { $id = (int)$form->getValue('id'); $artist = $form->getValue('artist'); $title = $form->getValue('title'); $albums = new Application_Model_DbTable_Albums(); $albums->updateAlbum($id, $artist, $title); $this->_helper->redirector('index'); } else { $form->populate($formData); } } else { $id = $this->_getParam('id', 0); if ($id > 0) { $albums = new Application_Model_DbTable_Albums(); $form->populate($albums->getAlbum($id)); } } } ... |
Разберём различия с добавлением альбома. Во-первых, перед выводом формы нам необходимо извлечь текущие значения полей “Музыкант” и “Название альбома” из БД и наполнить ими элементы формы. Делается это следующим образом:
1 2 3 4 5 | $id = $this->_getParam('id', 0); if ($id > 0) { $albums = new Application_Model_DbTable_Albums(); $form->populate($albums->getAlbum($id)); } |
Заметьте, что это происходит в случае, если POST-данные не были отправлены. Мы получаем id из объекта запроса используя метод _getParam(). Далее мы при помощи модели извлекаем запись из БД с соответствующим ID и наполняем форму полученными значениями (как вы уже знаете, что метод модели getAlbum() возвращает массив).
После валидации формы, нам необходимо сохранить изменённые данные в БД. Для этого мы используем метод модели updateAlbum():
1 2 3 4 5 | $id = $form->getValue('id'); $artist = $form->getValue('artist'); $title = $form->getValue('title'); $albums = new Application_Model_DbTable_Albums(); $albums->updateAlbum($id, $artist, $title); |
Скрипт вида выглядит так же:
zf-tutorial/application/views/scripts/index/edit.phtml
1 |
Теперь вы можете редактировать альбомы.
Удаление альбома
Чтобы функционал приложения был полным, нам необходимо добавить удаление. У нас уже есть ссылка “Удалить” для каждого альбома. Чтобы избежать случайного удаления, мы будем отображать форму подтверждения и удалять альбом только когда пользователь нажмёт кнопку “Да”. Так как это тривиальная форма, мы напишем её код напрямую в скрипте вида (можете использовать Zend_Form, если хотите).
Начнём с кода действия IndexController::deleteAction():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ... public function deleteAction() { $this->view->title = "Delete album"; $this->view->headTitle($this->view->title); if ($this->getRequest()->isPost()) { $del = $this->getRequest()->getPost('del'); if ($del == 'Да') { $id = $this->getRequest()->getPost('id'); $albums = new Application_Model_DbTable_Albums(); $albums->deleteAlbum($id); } $this->_helper->redirector('index'); } else { $id = $this->_getParam('id', 0); $albums = new Application_Model_DbTable_Albums(); $this->view->album = $albums->getAlbum($id); } } ... |
Как и в добавлении и редактировании, мы используем метод isPost() объекта запроса для определения, следует ли выводить форму подтверждения, или надо удалить альбом. Мы используем модель Application_Model_DbTable_Albums для удаления записи, используя метод deleteAlbum(). Если POST-запрос не был отправлен, мы получаем ID альбома, достаём соответствующую запись из БД и передаём её в скрипт вида.
Скрипт вида представляет собой простую форму:
zf-tutorial/application/views/scripts/index/delete.phtml
1 2 3 4 5 6 7 8 9 10 11 | <p>Are you sure that you want to delete '<?php echo $this->escape($this->album['title']); ?>' by '<?php echo $this->escape($this->album['artist']); ?>'? </p> <form action="<?php echo $this->url(array('action'=>'delete')); ?>" method="post"> <div> <input type="hidden" name="id" value="<?php echo $this->album['id']; ?>" /> <input type="submit" name="del" value="Да" /> <input type="submit" name="del" value="Нет" /> </div> </form> |
В этом скрипте мы выводим сообщение для подтверждения удаления с кнопками “Да” и “Нет”. В случае, если пользователь нажимает кнопку “Да”, мы удаляем запись из БД.
Вот и всё. Теперь мы имеем полностью работающее приложение.
Заключение
Мы научились собирать простое, но функциональное MVC-приложение с использованием Zend Framework. Я надеюсь, это руководство было интересным и информативным. Если вы обнаружите ошибку, пожалуйста, пишите на e-mail автора rob@akrabat.com (или переводчика sergeymitr@gmail.com).
Это руководство охватывает лишь базовое использование фреймворка, существует множество других компонентов для изучения. Сайт автора http://akrabat.com содержит много статей о Zend Framework, также рекомендую прочесть руководство http://framework.zend.com/manual. Если вы предпочитаете печатный текст, Rob Allen написал книгу под названием “Zend Framework in Action”, которая доступна для заказа на сайте http://www.zendframeworkinaction.com.
Всего доброго!
Anton says:
Zend Framework in Action выпущена в 2007-м. Она не сильно устарела с момента выпуска?
1 апреля 2010, 3:23Anton says:
Вопрос по существу:
1 апреля 2010, 10:29Попробовал под WinXP запустить
zf configure db-adapter
, как написано здесь
http://framework.zend.com/manual/en/learning.quickstart.create-model.html
Получил ошибку. Про эту ошибку что-то говориться в комментариях той статьи, но мне это не помогло. Вот я подумал может вместо того, что бы мучиться с Виндой, не проще ли будет запустить эту команду через какой-нибудь интерпретатор линуксовских команд?
Сергей Митрошин says:
ZF in Action слегка устарела, но ещё актуальна.
1 апреля 2010, 10:41Что за ошибку вы получили?
Anton says:
An Error Has Occurred The config already has a db resource configured in section production.
1 апреля 2010, 11:43Сергей Митрошин says:
Дело не в системе (windows/linux), в вашем application.ini уже настроен db-адаптер. Возможно, вы сделали это вручную.
1 апреля 2010, 11:48Anton says:
Спасибо. Я уже и забыл об этом. А что утилита просто вставляет строки в application.ini? Одна строка содержит ссылку на файл guestbook.db. Я ни где не нашел этого файла. Это нормально?
1 апреля 2010, 12:03Сергей Митрошин says:
Приведите, пожалуйста, полный текст ссылки на guestbook.db
1 апреля 2010, 14:10Да, утилита просто вставляет строки в application.ini. Можно сделать это вручную.
Anton says:
Это я разбирал этот туториал: http://framework.zend.com/manual/en/learning.quickstart.create-model.html
4 апреля 2010, 9:12Там используется php_pdo_sqlite, поэтому dbname у них выглядит так:
resources.db.params.dbname = “APPLICATION_PATH /../data/db/guestbook.db”
Сергей Митрошин says:
Изначально файл этот, насколько я помню, не нужен, но следует создать в нём таблицы.
4 апреля 2010, 11:42darkasha says:
public function deleteAction()
на 11 строчке баг —–> $albums = new Model_DbTable_Albums();
$albums = new Application_Model_DbTable_Albums();
4 апреля 2010, 19:57Сергей Митрошин says:
darkasha: спасибо, исправлено
5 апреля 2010, 3:51Ирина says:
Все сделала, перезагрузилась, ввожу zf show version
7 апреля 2010, 6:23Получаю: “”php.exe”" не является внутренней или внешней командой,исполняемой программой или командным файлом.
h3kir says:
Ирина, чтобы такого не было исправте путь в Zf.bat с php.exe
7 апреля 2010, 8:25на C:\WebServers\usr\local\php5\php.exe разумеется WebService это название моей папки куда установен апатч.у вас это наверняка другая.
Ирина says:
Вот здесь: SET PHP_DIR=C:\Server\PHP\ ?
7 апреля 2010, 8:45Если там, то исправила, правда это ничего не изменило. Или опять перезагружаться надо?
Ирина says:
О! Сработало! Спасибо!!! надо было изменить
7 апреля 2010, 8:48SET PHP_BIN=C:\Server\PHP\php.exe
Ирина says:
Теперь вы можете проверить, всё ли в порядке, открыв URL http://localhost/zftutorial/public.
7 апреля 2010, 10:16У меня: Fatal error: Call to a member function getDefaultModule() on a non-object in D:\www\zf-tutorial\library\Zend\Application\Bootstrap\Bootstrap.php on line 69
Anton says:
localhost
7 апреля 2010, 10:18Гы-гы
Ирина says:
Че гы-гы, это цитата
7 апреля 2010, 10:28Anton says:
localhost – это локальное имя вашей системы. В интернете такого имени не существует.
7 апреля 2010, 10:33Ирина says:
Я в курсе! Я не говорю про то, что не знаю, куда заходить, а говорю про то, что у меня ошибка, вместо красивой картинки. Если у кого была такая же, расскажите, как решили проблему!
7 апреля 2010, 10:45Сергей Митрошин says:
Ирина, похоже на баг ZF. Никогда не получал такую ошибку.
7 апреля 2010, 12:31Попробуйте обновить ZF до последней версии.
Ирина says:
Баг ZF, но версия у меня 1.9.6.
7 апреля 2010, 12:57Ирина says:
Думаю, что все-таки что-то в настройках апача…
7 апреля 2010, 13:01Anton says:
как сохранить переменную, сгенерированную в одной функции, что бы потом можно было использовать её в другой?
Я конечно понимаю что глобальные переменные давно не используются, но все же?
чем можно в Zend это сделать?
Пробовал Zend_Registry, но то-ли у меня руки кривые и я не понял, или там задать значение перемененной можно только в Bootstap?… ну да, для хранения переменных базы и конфиг файла супер… но а как быть с теми переменными которые создаются в самом контроллере, и нужны фактически только на некоторое время, но разных функциях.
плиз, подскажите тугодуму…
9 апреля 2010, 1:44Сергей Митрошин says:
Если это ваши пользовательские функции, передавайте значения через аргументы функции.
9 апреля 2010, 11:57Anton says:
Это мои пользовательские функции, но они вызываются не последовательно, и к тому же вызываются через AJAX
примерно так
1 функция: форма -> сохранение в базу, в результате получаем ID
2 функция: обработка данных
3 функция: обработка данных
вот во второй и в третей функциях, мне нужны эти переменные.
9 апреля 2010, 16:45Сергей Митрошин says:
Почему не получается передать их как аргументы функции?
9 апреля 2010, 17:45Anton says:
Потому, что функция в которой генерируется переменная, вызывается через jquery.form
а jquery.form возвращает только или ошибку или код 200.
и я бы передел легко, переменную, если бы она мне вернулась после отправки формы…
а так как не возвращает, потому я думал сохранить переменную во время обработки формы, и потом использовать её.
ну сохранять видимо нужно или в сессию или в базу… а хотелось бы просто в виде переменной.
9 апреля 2010, 19:11Сергей Митрошин says:
Разумеется, в таком случае не будет работать Zend_Registry.
9 апреля 2010, 21:00Но при помощи jquery.form можно получить данные с сервера при помощи параметра success.
Anton says:
да, данные из формы, но не результат работы функции, по крайней мере я не нашел как бы это сделать.
9 апреля 2010, 21:19Zyava says:
Храните в сессии свою переменную, ее туда так же легко поместить, как и в Zend_Registry: http://framework.zend.com/manual/1.10/en/zend.session.basic_usage.html
10 апреля 2010, 22:51chitozzz says:
начал осваивать zf по вашей статье…все сделал, вроде работает, но не работает удаление и редактирование… в чем дело не пойму… из базы читает а изменять и удалять не хочет…
25 апреля 2010, 12:32chitozzz says:
все разобрался… спасибо за знокомство с zf
25 апреля 2010, 16:23Dmitry says:
Здравствуйте, у меня в пункте “Вывод альбомов”, вместо списка альбомов появляется следующее:
My Albums
An error occurred
Application error
Подскажите пожауйста, где может быть ошибка?
28 апреля 2010, 11:24Сергей Митрошин says:
Вам надо добавить следующую строку в нужную секцию файла application.ini:
28 апреля 2010, 11:30resources.frontController.throwExceptions = 1
После этого вы увидите сам текст ошибки.
Dmitry says:
Добавил в секцию [production], и к сожалению ничего не изменилось.. Может что-то с Apache?
28 апреля 2010, 11:40Сергей Митрошин says:
В .htaccess у вас какой прописан APPLICATION_ENV?
28 апреля 2010, 11:47А сайт недвижимости больше не прописывайте, я его всё равно удаляю.
Dmitry says:
в public/index.php:
// Define application environment
defined(‘APPLICATION_ENV’)
|| define(‘APPLICATION_ENV’, (getenv(‘APPLICATION_ENV’) ? getenv(‘APPLICATION_ENV’) : ‘production’));
a .htaccess только:
RewriteEngine On
28 апреля 2010, 11:57RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ – [NC,L]
RewriteRule ^.*$ index.php [NC,L]
Dmitry says:
Установил в .htaccess
SetEnv APPLICATION_ENV production, результат не изменился
28 апреля 2010, 12:03kapals says:
Dmitry, пробуй так:
defined(‘APPLICATION_ENV’)
|| define(‘APPLICATION_ENV’, (getenv(‘APPLICATION_ENV’) ? getenv(‘APPLICATION_ENV’) : ‘development’));
и
resources.frontController.throwExceptions = 1
ставим в application.ini ниже
28 апреля 2010, 16:52[development : production]
kapals says:
Или скорее всего откоменти в php.ini строку
28 апреля 2010, 16:54extension=php_pdo_mysql.dll
Dmitry says:
Да, действительно extension=php_pdo_mysql.dll был закоментрован в php.ini, теперь все работает,
28 апреля 2010, 17:30Большое спасибо!
kapals says:
Рад помочь:)
28 апреля 2010, 17:50chitozzz says:
подскажите пожалуйста как подключить к этому сайту авторизацию? … все почитал что смог найти по этой теме но все решения как я понимаю для старых версий zf…
28 апреля 2010, 19:22Сергей Митрошин says:
Копайте в сторону Zend_Auth – статьи должны быть актуальны, основные части этого модуля давно не обновлялись.
28 апреля 2010, 20:12Elena says:
Здравствуйте
Помогите, пожалуйста,разобраться!
Создала в корневом каталоге C:\WebServers\home новый проект :
zf create project pages
Перешла в каталог проекта:
1 мая 2010, 16:22C:\Users\lenko>cd c:\webservers\home\pages
При попытке создать новые действия контроллера, получаю ошибку:
c:\WebServers\home\pages>zf create action add index
“zf” не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.
Dark Smoke says:
Скажите мне, от куда берется albums?
$albums = new Application_Model_DbTable_Albums();
3 мая 2010, 20:08$this->view->albums ( fetchAll();
Dark Smoke says:
Elena
3 мая 2010, 20:09В самом начале статьи есть тема Настройка Zend Tools прочти ее еще раз и сделай как там написано.
Oldman says:
Бьюсь вторую неделю
Элементарно не могу все установить.
Ставлю под винду, denwer.
Подскажите что делать с этим?
Warning: require_once(Zend/Application.php) [function.require-once]: failed to open stream: No such file or directory in Z:\home\localhost\public\index.php on line 18
Fatal error: require_once() [function.require]: Failed opening required ‘Zend/Application.php’ (include_path=’Z:\home\localhost\library;.;/usr/local/php5/PEAR’) in Z:\home\localhost\public\index.php on line 18
4 мая 2010, 22:22chitozzz says:
я тоже парился не получается… на семерке… я поставил zend server (почто тоже что и денвер), и там сразу заработала эта тулза…
5 мая 2010, 19:33wr120 says:
подскажите что делать ошибка такая
6 мая 2010, 10:49Fatal error: Uncaught exception ‘Zend_Config_Exception’ with message ‘Section ‘APPLICATION_ENV’ cannot be found in Z:\home\localhost\www\zf-tutorial\application/configs/application.ini’ in Z:\home\localhost\www\zf-tutorial\library\Zend\Config\Ini.php:150 Stack trace: #0 Z:\home\localhost\www\zf-tutorial\library\Zend\Application.php(383): Zend_Config_Ini->__construct(‘Z:\home\localho…’, ‘APPLICATION_ENV’) #1 Z:\home\localhost\www\zf-tutorial\library\Zend\Application.php(85): Zend_Application->_loadConfig(‘Z:\home\localho…’) #2 Z:\home\localhost\www\zf-tutorial\public\index.php(24): Zend_Application->__construct(‘APPLICATION_ENV’, ‘Z:\home\localho…’) #3 {main} thrown in Z:\home\localhost\www\zf-tutorial\library\Zend\Config\Ini.php on line 150
JHT says:
при наборе в консоле: zf show version – выдает – “”php.exe”" Не является внутренней или внешней командой.
7 мая 2010, 16:25как наладить?
Oldman says:
с настройками таки разобрался, автору спасибо за урок.
9 мая 2010, 0:46будет ли продолжение?
что-нибудь посложнее, например, урок по созданию реального приложения.
(как вариант блога или простенького “сообщества по интересам”)
Oldman says:
Ошибка в коде
function indexAction()
{
$this->view->title = “My Albums”;
$this->view->headTitle($this->view->title);
$albums = new Application_Model_DbTable_Albums();
$this->view->albums = $albums->fetchAll();
}
…
Fatal error: Class ‘Application_Model_DbTable_Albums’ not found in Z:\home\zf-tutorial\application\controllers\IndexController.php on line 16
10 мая 2010, 1:42Сергей Митрошин says:
to wr120:
Видимо, в .htaccess пропущена строка “SetEnv APPLICATION_ENV development”
to JHT:
Необходимо добавить php.exe в переменные окружения системы, в гугле есть подробные описания.
to Oldman:
10 мая 2010, 19:38Автору, действительно, спасибо. Я лишь перевёл.
Продолжение действительно стоит написать. Буду заниматься.
По поводу ошибки – в статье всё правильно и класс должен быть определён. Возможно, вы используете старую версию ZF? Если дело не в этом – отпишите, пожалуйста, буду фиксить.
Oldman says:
у меня ZendFramework-1.10.2.
не могу понять почему не находит этот класс.
Пробовал разные варианты переименовывал файлы и менял путь
10 мая 2010, 19:55Application_Model_DbTable_Albums – не работает
Application_Models_DbTable_Albums – не работает
Model_DbTable_Albums – не работает
Models_DbTable_Albums – не работает
Oldman says:
Еще с формами тоже не порядок
http://s003.radikal.ru/i201/1005/a7/3c941c124c89.jpg
Отсутствуют лейблы и надпись на кнопке
10 мая 2010, 20:57kapals says:
Сохрани скрипт в утф-8
10 мая 2010, 22:33Shadow_Of_iRBIS says:
После добавления
11 мая 2010, 11:53resources.view.doctype = “XHTML1_STRICT”
пропадает хидер “My Albums” почему-то. т.е. в layout.phtml $this->title пустой. В чем может быть проблема?
oleg hodil says:
я идиот
25 мая 2010, 15:48Tirei says:
Warning: require_once(Zend/Application.php) [function.require-once]: failed to open stream: No such file or directory in Z:\home\localhost\www\zf-tutorial\public\index.php on line 18
Fatal error: require_once() [function.require]: Failed opening required ‘Zend/Application.php’ (include_path=’Z:\home\localhost\www\zf-tutorial\library;.;/usr/local/php5/PEAR’) in Z:\home\localhost\www\zf-tutorial\public\index.php on line 18
То же самя ошибка, как ее исправить не могу понять
27 мая 2010, 11:49Tirei says:
блин я идиот, все там рассписано!
27 мая 2010, 13:10lavren says:
Спасибо за статью! Испытал с помощью zend server & Zend framework 1.10.5, проблем не было!
После прочтения статьи многое стало понятно!
Кому интерсно … мой выбор данной системы (zf), обусловлен выбором CMS на ZF,
27 мая 2010, 21:44PimCore (pimcore.org)
Anton says:
PimCore интересно, да. Только по нему на русском вообще ни чего нет…
28 мая 2010, 6:26lavren says:
Молодой ещё … (PimCore)! Сейчас основы zend fr.. изучу, то и займусь PimCore поплотнее…
28 мая 2010, 10:09Anton says:
lavren, если захотите поделиться опытом по PimCore, кидайте ссылку…
1 июня 2010, 10:48Oldman says:
PimCore я поставил ради интереса. Тормозная какая-то она. Страницы долго грузятся (и в админки и в самом тестовом сайте). В админке при беглом просмотре не обнаружил нормальной системы назначения ролей пользователям. Зато много (на мой взгляд) лишнего и непонятного в админке.
1 июня 2010, 19:54lavren says:
У меня на домашнем сервере (windows-zendserver), летает! Но вы правы – работы ещё непочатый край…
1 июня 2010, 21:10Oldman says:
Если у кого-то были проблемы с кодировкой (Denwer).
2 июня 2010, 22:03Замените строчку в AddDefaultCharset windows-1251 на AddDefaultCharset utf-8
и перезапустите Аpache
Oldman says:
мне нужно чтоб в адресной строке в конце стояло .html как быстро а главное правильно реализовать ?
2 июня 2010, 22:10(localhost/controller/metod.html)
Denis says:
Добрый день, подскажите, пожалуйста, ответы на два вопроса.
5 июня 2010, 1:301. Как сделать свой дизайн для форм создания и редактирования записи в альбоме? Хочется, чтобы и возможности предоставляемые Zend_Form, Zend_Form_Element_Hidden, Zend_Form_Element_Text… остались, но при этом дизайн был свой.
2. Как можно на одной странице сделать несколько логических, независимых друг от друга блоков? Например, на каждой странице должен выводиться блок последний новостей, независимо от основного функционала страницы.
Denis says:
P.S. О декораторах я почитал. Но, ИМХО, их использование далеко, от удобного. Получается что уже имеющуюся верстку надо перелопатить в команды формирования (методы декораторов). Все это будет плохо читаемо, сложно к исправлению ошибок и еще более сложно к изменению, если таковое потребуется. Интересуют более наглядные методы задания своего дизайна для форм.
5 июня 2010, 1:57ZA says:
Здравствуйте!
8 июня 2010, 21:58Скажите, пожалуйста, почему может отрабатывать ветка Default контроллера ErrorController (на странице появляется сообщение Application Error) при выполнении команды
$this->view->users = $users->fetchAll();
контроллера IndexController?
users практически ничем не отличается от Albums. логин/пароль, записанные в application.ini соответствуют существующему в БД пользователю.
ZA says:
вопрос снят. Прочитала самые первые комментарии про установку
8 июня 2010, 22:23resources.frontController.params.displayExceptions = 1
в application.ini
Roman says:
Статья хорошая, но обнаружил следующий глюк. При использовании команд типа
16 июня 2010, 14:23zf create action имя_метода index
зачем-то переформатируется весь файл, причем последовательность из нескольких фигурных скобок заменяется одной. То есть вместо }}} получаем } со всеми вытекающими последствиями. Если вместо }}} в файле стоит };};} то все нормально, но все равно зачем то меняются отступы по непонятной логике.
Вопрос такой если не пользоваться командной строкой, а все добавлять вручную возникнут ли впоследствии проблемы ?
1111111 says:
Здравствуйте.
24 июня 2010, 21:15Пробую написать свой маршрутизатор и не могу пока понять почему при перенаправлении на файл не загружает стили()”обычным” способом. И вообще это довольно актуальная тема для отдельного поста: “Как написать свой framework”? Только этот вопрос приведет пачку новых посетителей не говоря уже о большем.
1111111 says:
таким вот способом:
24 июня 2010, 21:17link href=”image/style.css” rel=”stylesheet” type=”text/css”
kolorimage says:
У меня XAMPP. И при попытке посетить http://localhost/zftutorial/public
“Access forbidden!
You don’t have permission to access the requested directory. There is either no index document or the directory is read-protected.
If you think this is a server error, please contact the webmaster.”
27 июня 2010, 17:20Zabi says:
Подскажите плс, встал на шаге после создания экшенов, неработают ссылки типа
http://localhost/zf-tutorial/public/index/add
но заходит с необходимым результатом на ссылки типа
http://localhost/zf-tutorial/public/index.php/index/add
теперь на шаге создания динамичных ссылок echo $this->url(array(‘controller’ => ‘index’, ‘action’ => ‘add’)) немогу сгенерировать необходимые ссылки, перерыл кучу инфы но не могу найти ответ на вопрос: как сделать так чтобы не нужно было писать в адресе index.php, или написать функцию для создания правильных ссылок.
в httpd.conf AllowOverride All прописано и LoadModule rewrite_module modules/mod_rewrite.so раскомментировано
29 июня 2010, 17:54Feo says:
При установке лучше не копировать library/Zend в наш проект, а сделать символьную ссылку, к основному пакету /usr/local/ZendFrameworkCli/library/Zend
2 июля 2010, 18:01Sunnesoft says:
Возникла проблема как у Oldman’a. Только решил ее редактированием файла View\Abstract: $_encoding=’нужная кодировка’.
8 июля 2010, 23:24neman says:
У меня возникла такая проблем, когда я передаю значение на русском языке в метод setLable класса Zend_Form_Element_Text(‘artist’), то ничего в браузере не отображается, а на английском – все нормально. И такая же проблема с headTitle. Что делать?)))
11 июля 2010, 13:20Oldman says:
neman: проблема с кодировкой, читай коментарии
11 июля 2010, 13:24neman says:
Изменил в httpd.conf строчку AddDefaultCharset windows-1251 на AddDefaultCharset utf-8 и все равно не отображается кириллица хотя и в layout.phtml прописана кодировка utf-8
15 июля 2010, 15:38Oldman says:
а перезагружал сервак? )
15 июля 2010, 20:05пора форума создавать, однако
Anton says:
Oldman. Поддерживаю. Много вопросов, в одну ветку все не укладывается…
15 июля 2010, 20:32Фам says:
Обнаружил интересный баг, но поскольку только недавно начал учиться работать в Zend Framework’е, не знаю, как его исправить…
16 июля 2010, 13:45Собственно, его описаниние:
Когда неправильно заполняешь какой-нибудь input в форме и валидатор начинает ругаться, становится невозможно обновить страницу браузера до тех пор, пока не заполнишь правильно – выскакивает окно с надписью: “Чтобы отобразить эту страницу, Firefox должен отправить информацию, которая повторит любое ранее произведённое действие (например, запрос на поиск или онлайн-покупка).” и кнопками “Отправить” и “Отмена”, причем последняя не помогает… Не могли бы вы подсказать, в чем дело?
Фам says:
ыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыы
16 июля 2010, 16:44Фам says:
Простите за предыдущее сообщение!.. Хотел посмотреть кое-что))
16 июля 2010, 16:46Anton says:
А почему “ы” ?
16 июля 2010, 19:37Сергей Митрошин says:
Попытка дефейса?
16 июля 2010, 19:37Сергей Митрошин says:
По поводу “Firefox должен отправить информацию…” – так и должно быть, он хочет повторно послать POST-данные.
16 июля 2010, 19:38Anton says:
Стандартное поведение браузеров. Когда жмешь F5, он повторно отсылает запрос, вызвавший обновляемую страницу.
16 июля 2010, 20:08Фам says:
А нельзя никак этого избежать?
19 июля 2010, 11:42Anton says:
Используй другие способы обновить страницу. Уверен они есть…
19 июля 2010, 12:17Фам says:
Просто я на основе этого руководства делаю гостевую книгу (просто так в качестве тренировки) и, мне кажется, что если бы это было реально приложение, то его пользователям не сильно хотелось бы искать другой способ обновить страницу…
19 июля 2010, 13:36Anton says:
Такую возможность обычно предусматривают заранее и реализуют в виде специальной кнопочки, что бы у пользователя не возникало желания жать на F5.
19 июля 2010, 13:45kroosnik says:
Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\zf-tutorial\application\views\scripts\index\index.phtml on line 8
подскажите пожалуйста, что я сделал не так?
28 июля 2010, 13:22Сергей Митрошин says:
Пытаетесь сделать foreach не по массиву.
28 июля 2010, 13:34kroosnik says:
я делал все по статье
<a href="url(array(‘controller’ => ‘index’, ‘action’ => ‘add’)) ?>”>Добавить новый альбом</
…
albums as $album) : ?>
…
но почему-то именно на этой строке все остановилось и не работает (
28 июля 2010, 13:48kroosnik says:
albums as $album) : ?>
28 июля 2010, 13:48dnka says:
Народ, подскажите плиз такое дело: я хочу развернуть приложение на хостинге. Но там все лежит в папке www\имя_сайта . Как мне прописывать настройки, чтобы автоматически корневой дирикторией была \имя_сайта\public\
Спасибо большое
28 июля 2010, 21:12Сергей Митрошин says:
Описание процесса: http://www.alberton.info/zend_framework_mod_rewrite_shared_hosting.html
28 июля 2010, 21:38dnka says:
Огромное спасибо, Сергей Митрошин !!! 2 минуты – и все работает
28 июля 2010, 21:48Сергей Митрошин says:
Пожалуйста
28 июля 2010, 22:14skyder says:
Такая проблема: если в БД данные записаны кириллицей, на странице они отображаются вопросиками… как поменять кодировку?
3 августа 2010, 10:28skyder says:
С кодировкой разобрался… При создании БД нужно сравнение ставить utf-8…
3 августа 2010, 13:00Иван says:
У меня не отображается русские буквы!!! Все файлы поменял на utf-8: результата никого!!!
11 августа 2010, 20:59DendyFan says:
Тоже проблема с кодировками…
Все файлы в UTF8
meta в layout тоже utf8
Все сравнения в таблице utf8_unicode_ci, сопоставление соединения mysql Тоже utf8_unicode_ci
В конфиге resources.db.charset = “utf8″
И все равно ???? вместо русских букв…
14 августа 2010, 20:08Rostislav says:
Ребята, подскжите пожалуйста по такому вопросу
15 августа 2010, 0:37можно ли как то задать ошибку общюю для формы
не связанную с конкретным полем.
ну скажем чтоб например если не прошёл логин выдавало какое-то общее сообщение над списком полей
и чтоб это всё отобразилось просто при echo $form;
Rostislav says:
Это был вопрос по Zend_Form
15 августа 2010, 0:39CoDy says:
Спасибо за статью.
16 августа 2010, 13:26Собрал у себя на локальном сервере вышеописанное приложение.
Хоть приложение и очень простое, но сервер нагружает довольно сильно.
Есть ли методы ускорить работу приложений на базе ZF? В частности хотелось бы узнать о таком расширении ка Zend Optimizer – это просто дешифратор или в нем есть задатки php акселератора???
Kinko says:
Не могли бы Вы осветить использование Dojo.
22 августа 2010, 15:11Constantine says:
спасибо за статью! у меня есть вопрос
я сделал все, как написано до пункта, где мы создаем обьект $albums нашего класса для альбомов.
на строчке $albums = new Application_Model_DbTable_Albums();
мне выдается ошибка
Fatal error: Class ‘Application_Model_DbTable_Albums’ not found in (путь к папке сайта)\application\controllers\IndexController.php on line 16
хотя сам класс лежит именно там, где должен, тоесть в (путь к папке сайта)\application\models\DbTable\Albums.php
27 августа 2010, 19:34не могли бы вы помочь?
Constantine says:
проблему решил! вот ответ из офф мануала (инетерсно будет всем, у кого не работает ZF Tool на сервере с xampp):
To all those who couldn’t make ‘zf’ commands work (eg: zf enable layout).
The path to the Zend framework installation should be registered with the system.
Eg: In Windows a path variable should be set in the Environment Variables in the Advanced tab of System Properties in Control Panel. (eg: Control Panel->System->Advanced->Environment Variables in XP).
I’m using XAMPP. There is a small caveat in there which I’ll share with my fellow XAMPP users. XAMPP has already has some logic by which all the folders inside it knows the existence of others. So If you go look inside it you can see there is already a Zend folder in the PEAR directory inside php folder. So all we need to add as a path variable is up to the php folder (eg: C:\xampp\php) and all will be well.
Check by typing “zf show version”. It will print out the version of the Zend libraries inside the PEAR folder. (Whenever there is a new version of ZF is available I change the content inside this folder and everything is up to date).
28 августа 2010, 20:10Oldman says:
! C:\Documents and Settings\fuckoff\Рабочий стол\zf-tutorial-160.zip: Архив повреждён или имеет неизвестный формат
30 августа 2010, 23:18Сергей Митрошин says:
Oldman, спасибо. Заменил ссылку на архив.
30 августа 2010, 23:25Oldman says:
Режим указывается в .htaccess и по умолчанию имеет значение development.
30 августа 2010, 23:38вроде в application.ini
foreach says:
Кто нибудь может объяснить на пальцах по поводу ошибки:
1 сентября 2010, 14:27FataError:Class ‘Application_Model_DbTable_Albums’ not found in ‘Z:\localhost\zfapp\www\application\controllers\IndexController.php’ on line 18
Почему не найден класс?Все же делал по статье.
phpstarter says:
Остановился на шаге там где через zf tool добавляют дополнительные действия в контроллер
Так вот в командной строке захожу в папку zf-tutorial
и ввожу как написано в статье следующюю команду.
zf create action add index
в ответ получаю такую ошибку….
“Fatal error: Cannot redeclare class Zend_Loader in E:\xampp\htdocs\zf-tutorial\library\Zend\Loader.php on line 31
подскажите что делать ?
1 сентября 2010, 20:18Сергей Митрошин says:
Надо закомментировать в application.ini следующую строку: includePaths.library = APPLICATION_PATH “/../library”
1 сентября 2010, 20:32Комментарий обозначается символом “;”
phpstarter says:
спасибо ! сработало
а после всего наверно потом надо будет раскоментировать ту строчку обратно ?
1 сентября 2010, 20:55Сергей Митрошин says:
Не обязательно, и без неё работает.
1 сентября 2010, 21:20phpstarter says:
большое спасибо
я пока новичек, как я понял если делать свой серьезный проэкт то лучше делать его на ZF чем самому писать. Пролистал кучу сайтов по ZF но везде както через одно место было написано, а тут все вроде идеально получается ! Большое спасибо за проделанную работу ! А также за внимание к коментариям
1 сентября 2010, 21:27Сергей Митрошин says:
Пожалуйста
1 сентября 2010, 22:25Пишите, если что.
phpstarter says:
Внимание для тех у кого возникнут следующие проблемы.
Если вы используете веб сервер xampp, и вы начали на его базе делать этот проэкт и у вас произошло следующее…
1. При вводе в командной строке команды zf show version и вам выводится “Zend Framework Version: 1.9.6″ , хотя вы знаете что скачали более свежую версию.
2. При вводе в командной строке команды zf enable layout вы получаете “An Error Has Occured”
“Action ‘enable’ is not a valid action
Итак если у вас произошло читаем ниже
Объяснение…..
Дело в том что у xampp тоже есть встроенная Zend библиотека и она подключается к работе , а так как она стара отсюда и старая версия при запросе а также откза подключать layout.
Действия……..
2 сентября 2010, 18:11заходим в /xampp/php/PEAR там есть папка Zend. Берем из архива скачанного фрейморка туже папку и перезаписываем туда куда я указал. После этого тутже можно проверять. Описанные выше проблемы изчезнут.
phpstarter says:
Сергей выручайте пожалуйста
Дошел до вывода албомов.
Проделав шаги указанные там
смотрю http://localhost/zf-tutorial/public/. у меня все точно также построенно но вместо того что должно выйти пишет “Fatal error: Class ‘Application_Model_DbTable_Albums’ not found in E:\xampp\htdocs\zf-tutorial\application\controllers\IndexController.php on line 17″
Я так понимаю IndexController без понятия кто такой класс Application_Model_DbTable_Albums. Если не ошибаюсь , объявляли мы его в Albums.php . Я пока все пытаюсь вслепую сделать, так что мало соображаю, но наверно IndexController Должен был както получить доступ к содержимому Album.php но сюдя по всему он не брал от туда инфу и потому не знает что такой класс создан. Пожалуйста помогите советом
2 сентября 2010, 19:36Сергей Митрошин says:
Попробуйте заменить имя класса в обоих случаях на Model_DbTable_Albums.
2 сентября 2010, 19:41phpstarter says:
После изменения Application_Model_DbTable_Albums на Model_DbTable_Albums в указанных ниже строчках
albums.php
class Model_DbTable_Albums extends Zend_Db_Table_Abstract
IndexController.php
$albums = new Model_DbTable_Albums();
ответ тотже
2 сентября 2010, 19:44Fatal error: Class ‘Model_DbTable_Albums’ not found in E:\xampp\htdocs\zf-tutorial\application\controllers\IndexController.php on line 17
phpstarter says:
Сергей. покопавшись тут http://akrabat.com/zend-framework-tutorial/ я нашел ответ в 43ем коментарии…
человек по имени Sensi решил эту проблему добавив следующий код в Bootstrap.php
protected function _initFoo()
{
$loader = new Zend_Loader_Autoloader_Resource (array (
‘basePath’ => APPLICATION_PATH,
‘namespace’ => ‘Application’,
));
$loader->addResourceType( ‘model’, ‘models’, ‘Model’);
}
Проделав это у меня вышло но только после того как я переименовал класс в исходных вариант тоесть с заглавием Application.
Теперь у меня все работает. Но может быть вы сможете пробежавшись по этому добавочному коду , както его упрощенно объяснить чтоли… описать что он делает и зачем он именно в бутсреп файле.
заранее спасибо
2 сентября 2010, 20:06phpstarter says:
новая проблема
команда zf create form Album
отказывается работать.
Fatal error: Call to a member function search() on a non-object in E:\xampp\php\PEAR\Zend\Tool\Project\Provider\Form.php on line 70
Заранее говорю что по этому пути как и в program files установлена последняя версия zf. 1.10.8
Как решить данную проблему ?
2 сентября 2010, 20:42Сергей Митрошин says:
В указанном коде происходит добавление моделей в список ресурсов для автозагрузки. По какой-то причине это не произошло автоматически. Надо разбираться.
2 сентября 2010, 21:15По поводу zf create form – вы всё делаете правильно, видимо, баг в ZF. Попробуйте откатиться до прежних версий.
phpstarter says:
не стал откатываться так как тогда не работали бы другие функции..
сделал формы ручками, благо не настолько кривые
вобщем спасибо за перевод, даннйо статьи. Все собрал. Все работает
Теперь хочу это дело нормально переварить и на базе этого сварганить чтонить свое
Еще раз спасибо за проделаную работу
2 сентября 2010, 23:30Сергей Митрошин says:
Пожалуйста.
2 сентября 2010, 23:39Удачи с изучением
Oldman says:
автор, сделай рассылку не больше одного письма в день, при новых камментах
2 сентября 2010, 23:43а то заипался удалять
спасибо