Zend framework что это
Zend framework что это
В этом разделе помещены уроки по PHP скриптам, которые Вы сможете использовать на своих ресурсах.
Фильтрация данных с помощью zend-filter
Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.
Контекстное экранирование с помощью zend-escaper
Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.
Подключение Zend модулей к Expressive
Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.
Совет: отправка информации в Google Analytics через API
Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.
Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.
Совет: активация отображения всех ошибок в PHP
При поднятии PHP проекта на новом рабочем окружении могут возникнуть ошибки отображение которых изначально скрыто базовыми настройками. Это можно исправить, прописав несколько команд.
Агент
PHP парсер юзер агента с поддержкой Laravel, работающий на базе библиотеки Mobile Detect.
Zend Framework, субъективные впечатления
Недавно мне было поручено разработать некое веб-приложение. Не буду вдаваться в подробности, а лишь скажу, что приложение связанно с планированием перевозок. Есть общедоступная часть, воспользоваться которой может любой посетитель сайта. Есть внутренние интерфейсы для операторов системы. Есть информеры для размещения на сторонних сайтах. С технической точки зрения это несколько десятков экранов, множество различных форм, табличек. Часть экранов используют ajax, кастомные компоненты, написанные на javascript, и всякие красивости типа drag-and-drop. Данные, как обычно, хранятся в реляционной БД в виде полутора десятков таблиц. В общем не совсем примитивное приложение, но и очень сложным назвать его тоже не могу.
По работе мне, мне достаточно часто приходится проектировать или лично кодить подобные приложения. Однако в данном проекте было одно важное требование. Приложение должно быть разработано на базе серьезной и проверенной платформе, а именно на Zend Framework. Использование самописных “велосипедов” — недопустимо. Скажу честно, опыта реальной работы с Zend Framework у меня до сих пор не было. Но платформа известная и за ней стоит известный разработчик. Многими разработчиками Zend Framework вообще рассматривается как стандарт веб разработки. Так что, тем более, есть повод освоить что то новое и солидное. Поэтому я с энтузиазмом взялся за этот проект.
Далее пойдет описание моих личных эмоций и впечатлений, поэтому, возможно, не стоит их воспринимать слишком близко. Это именно некий эмоциональный остаток, оставшийся после завершения работы над проектом. Zend Framework в коммерческом проекте был использован мной впервые.
Zend Framework позиционируется как отличная, продуманная и удобная платформа для разработки веб-приложений. Что же такое типичное веб приложения по моему личному мнению? Ну, это много разнообразных экранов, много форм, много табличек. Все это активно работает с базой данных, обычно с реляционной базой данных. Ладно, буду конкретнее, в 95% случаев именно с MySQL. Итак, от платформы для разработки веб приложений я как минимум ожидаю хороших возможностей по созданию форм, разных экранов и удобную работу с реляционной базой данных. И вот я приступил к освоению.
Первым делом мне потребовалось изучить основы самого Zend Framework. Мною была прочитана книжка посвященная этой платформе “Zend Framework. Разработка веб-приложений на PHP. Автор: Викрам Васвани”. Похоже что на данный момент это чуть ли не единственная русскоязычная книжка в печатном виде посвященная подобным фреймворкам. В принципе книжка вполне неплохая. После прочтения у меня появилось общее понимание как работать с фреймворком. Дальше я приступил к изучению официальной документации, чтобы заполнить пробелы и вообще понять, что еще может предоставить мне это фреймворк. Ведь книга рассматривает далеко не все возможности движка. Исчерпывающая и доходчиво написанная официальная документация находится здесь framework.zend.com/manual/ru Примерно через неделю я решил что можно приступать к разработке приложения.
Мое мировоззрение на кодинг
Пару слов о моем персональном мнении, как должны писаться продукты. Упомяну здесь и те вещи, за которые меня иногда критикуют.
Я уважаю ООП и применение ООП-патернов. Но применение должно быть обоснованным и реально упрощаться читабельность кода или его дальнейшее совершенствование. Патерны ради патернов — это плохо.
Хороший код — это понятный код. Понятный код — это лаконичный код. Если можно написать код короче, то как правило он будет понятнее. Чем больше логически связанных кусков кода помещается на одном экране монитора — тем лучше.
Если меня что то не устраивает в уже существующих решениях и подходах, я задумываюсь над созданием собственного решения, которое будет меня удовлетворять больше. Да, многие называют это “изобретением велосипеда”. Но я предпочитаю создать удобный велосипед, вместо того, чтобы долго и печально допиливать напильником чужое, не очень подходящее решение.
MVC это замечательно, но не в каждом конкретном случае упрощает и ускоряет процесс разработки. В некоторых случаях от него можно отступить, особенно, когда речь идет о простейших действиях, но этих действий очень много. (Но я тут ни в коем случае не хочу сказать, что MVC не нужна вообще.) Вот пример:
Да, я здесь смешал Модель, Контроллер, Раутер и Представление. Вполне похоже на фрагмент говнокода. Однако, в некоторых, осознанных случаях, я напишу именно так, если это будет оправданно с точки зрения временных затрат, объема кода и возможности дальнейшей поддержки. В общем, я против ярого mvc-фанатизма, и я за здравый смысл и обдуманность подходов.
В проекте о котором идет речь в статье, разумеется, такого кода нет. Я не считаю что у меня уже достаточно опыта, чтобы осознанно отступить от подхода диктуемого в Zend Framwork, поэтому я старался полностью следовать его концепции.
Теперь немного о шаблонах в веб-проектах. Я не понимаю когда используются шаблонные языки типа Smarty. Ну зачем выдумывать новый и в общем то ограниченный язык, когда есть полноценный язык PHP? Неужели верстальщика тяжело научить использовать PHP-шные if(. ) и foreach(. )? Это не сложнее чем в Smarty, но зато мы не добавляем в проект новый экзотический язык.
Кстати, бывает что шаблоны (или Представления) настолько сложные, что в них приходится использовать не только if и foreach, а и весьма сложные конструкции, включая классы и объекты которые наследуются друг от друга. Хотя при этом, задача преставления остается прежней — сформировать HTML кода по сухим данным.
В общем, для шаблонов я всегда предпочитаю обычный PHP, и обещание разработчика не запихивать в шаблон никакой логики. Для обработки шаблона можно использовать простейшую функцию типа
Плюс конечно простейшая обвязка для экранирования, для кэширования. Вроде больше ничего и не надо для счастья.
Пожалуй я еще ничего не имею против XSLT в качестве шаблонного языка. Но только для случаев когда вариантов представления информации не очень много и они относительно простые. Ну не сделаете вы легко на голом XSLT шаблон для какой-нибудь адской формы структура и геометрия который полностью зависит от поступивших данных. Здесь потребуются и циклы и объекты и полиморфизм и наследование.
Установка Zend Framework
Фрейморк, как оказалось весит около 25МБ и содержит почти 3000 файлов. Неслабо, подумал я! Видимо там реализовано все, о чем только можно мечтать!
Для начала меня немного расстроила структура директорий приложения на базе Zend Framework. Она предполагает весьма большое количество директорий. При работе над проектом я постоянно терялся в этой структуре. Также немного перемудерными мне показались правила названия создаваемых классов, правил для именования файлов и путей их размещения. Логика в них есть, но честно говоря, можно было все это сделать более интуитивно понятным. И особо сильно утомляет путешествия по директориям скриптов представления. Хотя, видимо если долго работать с этим фреймворком, то привыкнешь.
Но меня сильно утомил ритуал создания новых разделов приложения: Директории создай, файл назови, класс назови, контроллер назови. Сначала с проделай это с контроллером, потом со вьюшкой. Да, там есть консольная утилита, которая в некоторых случаях позволяет это сделать автоматически. Но в ряде случаев она недееспособная.
Оказалось, что Zend Framework не рассчитан на работу с shared хостингом, т.к. для запуска требует прописать в VirtualHost директорию отличную от корня вашего проекта. Так что у вас должен быть как минимум VDS сервер. Ну да, я слышал мнение, что если вы разрабатываете что то, что работает на shared хостинге, то вы не крут, и вам не место среди профессионалов. Хотя я всегда считал что 95% все веб проектов крутятся именно на shared хостингах. Ладно, в любом случае после нескольких взмахов напильника, я все же заставил проект подняться на shard хотинге.
Работа с базами данных
Сначала мне потребовалось создать модели данных (в рамках концепции MVC). Как выяснилось, Zend Framework не предоставляет ничего готового для создания моделей. По сути надо просто написать собственный класс, методы которого будут выполнять ту или иную операцию по работе с БД. Т.е. в ряде случаев, класс модели, это всего лишь обертка над SQL запросом, а иногда SQL запросы с некой дополнительной обвязкой на PHP.
Для работы с БД во фреймворке используется компоненты Zend_Db. Он позволяет работать с большинством распространенных СУБД через SQL.
Он также позволяет делать запросы без использования SQL, а конструируя некий хитрый объект, который внутри фреймворка все таки превратиться в SQL. Вот только мне кажется что для написание более-менее сложного запроса, все равно удобнее и понятнее написать SQL запрос, чем конструировать эту обертку, которая, как выясняется, позволяет создать далеко не любой сложный запрос. В общем я считаю что лучше хорошо изучить сам SQL, чем пытаться заставить его сформировать фреймворк, и надеяться, что он это сделает оптимальным образом. Нативный SQL намного лучше читается, понятен всем программистам и позволяет использовать все возможности конкретной СУБД. Вы скажете, что использование объектного конструктора запросов позволяет абстрагироваться от диалекта конкретной БД? При сложных запросах — далеко не всегда удается абстрагироваться, даже имея крутой конструктор. Ну и еще один аргумент — я не помню ни одного проекта, где бы потребовалось сменить СУБД, и при этом не предполагалось глобальной переделки всего проекта, бизнес логики и модели данных, т.е. написание полностью нового проекта по мотивам предыдущего. Сохранение кусочка класса модели данных от предыдущей версии на общем фоне не сильно облегчит жизнь.
Есть еще несколько удобных методов, которые извлекают результаты SQL запросов:
fetchCol() — извлекает одну колонку. Удобно когда надо получить список ID-шек
fetchRow() — извлекает первую строку. Удобно когда надо выбрать одну запись по первичному ключу.
fetchOne() — Извлекает только одно значение. Тоже удобно, когда реально надо получить одно значение и не хочется писать код для выковыривания одного элемента его из массива.
fetchPairs() — извлекает пары значений в виде ассоциативного массива. Создает хэш типа ключ-значение. Очень полезно создания разных словариков.
Все эти методы позволяют по мелочи уменьшить число строк кода. Убрать всякие дополнительные циклы, извлечения элементов и.т.п. В итоге, объщий объем кода в моделях заметно уменьшается.
Метод fetchPairs() это хорошо. А теперь, как на получить чуть более интересный и нужный словарь, где в качестве ключа идет первичный ключ БД, а в качестве значения массив-запись БД? Очень распространенная задача. Ответ — а никак! Делай руками, вызывай fetchAssoc(), потом крути цикл и генерируй новый массив-словарь. Обидно!
Ладно, идем дальше. Надо извлечь из таблицы данные и построить из них древовидный массив. Оказывается эта распространенная операция тоже никак не реализована. Т.е. нет ничего типа:
$hierarhy = db->fetch_tree(“SELECT id, parent_id, title FROM tree‘, ‘id’, ‘parent_id’);
Идем дальше. В SQL надо передавать параметры. Ну да, на первый взгляд все просто. Делается это так:
Можно даже несколько плейсходлеров поставить.
Только вот когда программа становиться сложной, то и сложность запросов растет, и параметров могут быть уже десятки. Нужны именованные плейсхолдеры. Считать плейсхолдеры по их порядковому номеру — далеко не располагает к понятности кода. Как выяснилось, Zend Framework их не реализует! Они работает, но только если выбранная БД их поддерживает. Например если вы выбрали MySQLi то с именованными плейсходерами вы работать не сможете. Неужели было так сложно было сделать эмуляцию именованных параметров?! Ладно, эта вещь оказалось решаемой. Оказывается если в качестве адаптера выбрать Pdo_Mysql вместо Mysqli, то именованные параметры начнут работать, т.к. они эмулируются внутри самого PDO. Признаться, я дошел до этого не сразу. Обида стихла, но неприятный осадок остался.
Частенько в SQL запросах приходится использовать код типа такого
SELECT * FROM items WHERE id IN(1,3,5,8,12)
где список id-шек, динамически генерируется из массива.
Я лично не нашел способа сделать это на Zend Framework красиво. Есть некий метод quoteInto(). Использовать можно так
В общем, не сильно мне порнавился Zend_Db. Какой то большой выгоды или сильного удобства от его использования я не заметил. Кстати Zend_Db весит больше 500КБ.
Вообще, для работы с БД я предпочитаю использовать самодельный маленький класс со следующими публичными методами:
Результаты выполнения — обычные ассоциативные массивы логичной для каждого из случаев структуры. Параметры — всегда именованные, можно передавать числа, строки, а также списки. Класс кидается исключениями, если в SQL допущена синтаксическая ошибка. Этот “велосипед” весит в районе 10КБ, и честно говоря мне его всегда хватает. Другим программистам на его изучение требуется 10 минут, а для изучения Zend_Db — часы внимательного штудирования мануалов, и все равно остаются вопросы. Путем расширения класса и переопределения нескольких виртуальных методов, можно добавить поддержку любой другой БД.
Формы
Следующая важнейшая вещь для веб-приложения это формы. Обычно их весьма много. Структура и внешний вид тоже очень разнообразны. Для работы с формами в Zend Framework используется Zend_Form.
Чтобы создать форму надо сконструировать объект формы. В него надо добавить объекты каждого из полей. В полях можно настроить разные параметры. Указать валидаторы и т.п. Вот пример создания поля
Создав все поля — добавляем их к объекту формы
Только вот когда полей становится много мы обязательно какое нибудь из них забудем добавить в форму. Ну не люблю я до ужаса, когда в коде надо чего нибудь перечислить, а потом где нибудь в другом месте опять это все повторно перечислять. Причем здесь надо каждый раз указывать имя переменной объекта поля и его название для вывода
Если бы addElement() возвращал не ссылку на форму, а ссылку на добавленный элемент, то при помощи fluent интерфейса код бы вышел намного лаконичнее и без всяких повторов. Типа того
Как вы заметили, тут можно использовать готовые валидаторы полей. Неплохо. Давайте попробуем сделать поле для ввода e-mail и введем кривой адрес электронной почты. Для этого используем стандартный валидатор EmailAddress.
Попробуем указать кривой емейл “xxx”. Получаем сообщение о некорректности:
‘xxx’ is no valid email address in the basic format local-part@hostname
Нормально. Разумеется надо бы перевести сообщение на русский, но там это можно легко сделать. А теперь давайте попробуем еще более кривой адрес “я@_domain.xx”.
И вот что мы получаем:
‘_domain.xx’ is no valid hostname for email address ‘я@_domain.xx’
‘_domain.xx’ appears to be a DNS hostname but cannot match TLD against known list
‘_domain.xx’ does not appear to be a valid local network name
‘я’ can not be matched against dot-atom format
‘я’ can not be matched against quoted-string format
‘я’ is no valid local part for email address ‘я@_domain.xx’
6 сообщений! Кому это надо? Неужели рядовой пользователь вообще поймет что такое TLD, quoted-string или dot-atom? Рядовому пользователю нужно только одно единственное сообщение — “Некорректный E-mail” и все! Но стандартные средства этого не позволяют. Чтобы избавиться от вывода этой кучи сообщений — предлагается написать свой собственный класс валидатора.
Ну допустим сделали мы форму, настроили все поля, все валидаторы. Теперь выведем ее. По умолчанию HTML код форма будет выглядеть примерно так:
Причем в DD элементы буду заворачиваться даже hidden поля! А потом мы начнем удивляться, что за странные пустоты образовались в форме. В общем интеллекта для особой обработки hidden полей у фреймворка нет.
А что если меня простейший DL список не устраивает? Вдруг мне надо сделать форму со сложной структурой? Тут предлагается использовать классы декораторы. Декораторы, это такие классы которые позволяют заворачивать элементы формы в определенные HTML теги, например можно завернуть элемент не в тег DT, а например в DIV. О ужас! “Правильный” MVC фреймворк вынуждает нас заниматься версткой прямо внутри контроллера, причем самым нечитабельным способом!
На мой взгляд, версткой нестандартных форм должен заниматься исключительно верстальщик. Он должен просто сделать скрипт представления который содержит все верстку формы. А использовать десяток классов декораторов внутри контроллера — это, мягко говоря, криво.
Позвольте привести пример простейшего “велосипеда” для работы с формами, который позволяет лаконично и удобно создавать формы.
Здесь, для уменьшение объема кода делаем возможность позволяем вместо явного создания объектов элементов формы, просто создать конфигурирующий массив. Хотя это и не исключает возможности создания объектов полей и валидаторов вручную. Ну а дальше, используем форму:
Ну а теперь несколько методов, неправильных с точки зрения MVC.
$form->getSqlSet(); // Вернет кусок SQL кода
Можно использовать так
$sql = “UPDATE account SET “.$form->getSqlSet().” WHERE >
Следующие методы используются для тех же целей.
$form->getSqlFieldsList();
$form->getSqlValuesList();
Да, это не совсем канонически правильное решение. Но зато набор полей надо описать только один раз в конструкторе формы. В случае его изменения автоматически изменятся и все SQL запросы.
Админки
Как правило, для любого сложного веб-приложения требуется создание неких админок или панелей управления. Например для установки параметров, или для редактирования справочников и т.п. Т.е. как минимум нужен некий инструмент для создания редакторов списков записей. Как минимум плоских списков, а для сложных проектов эти списки должны быть часто иерархичными.
В общем в этом фреймворке нет ничего готового для этого. Если надо, приходится реализовывать все самому вручную. Т.е. для каждого редактора создавать экран с таблицей, с формой, и практически вручную реализовывать CRUD операции.
Выводы и впечатления
Как вы поняли, этот “правильный” фреймворк произвел на меня не очень хорошее впечатление.
Но пожалуй что Zend Framwork все же можно освоить в следующих случаях:
1. Если у вас недостаточно опыта чтобы сделать сносный каркас для своего приложения.
2. Если вы вообще не умеете работать с MVC, но хотите прочувствовать эту идеологию
3. Если у вас нет хорошего представления об ООП и применении типичных патернов проектирования, то Zend Framwork покажет вам множество примеров. Там они использовали ООП везде где надо и не надо.
4. Так же Zend Framwork вполне сойдет, если вы делаете несложное приложение, работа которого больше сводится к извлечению данных из БД и выводу на экран. Например, какие нибудь новостные порталы или каталоги продукции.
Хотя, может все же лучше обратить свой взор на какой либо другой фреймворк? Zend Framework уже начал терять позиции, и возможно неспроста.
А лично я наткнулся на неудобства практически во всех компонентах фреймворка с которыми пытался работать. Регулярно ворчал себе под нос фразы типа “Это же можно было сделать удобнее!” или “Ну почему этого они не реализовали!”. У меня создалось впечатление, что главная задача разработчиков Zend Framwork была сделать все ООПно. Все что можно, все завернуть в враперы, адаптеры, и не важно, будет ли это удобно или нет. Уровень абстракции в библиотеке крайне высок, настолько высок, что в нем тяжело разбираться. И главное, практически любой компонент надо допиливать под свои потребности. В сыром виде все работает не так как хочется.
Да, я прекрасно осознаю. Наверняка я что то недопонял во фреймворке. Наверняка что-то пропустил в мануалах. И сейчас я получу замечания в стиле RTFM. Но и это тоже показатель. Хорошая платформа должна легко и быстро осваиваться, сразу показывать правильные и удобные решения. Здесь, я этого не почувствовал.
А еще мне вспомнился советский анекдот, когда собирая по чертежам самолет, получался паровоз. А в чертежах было написано — “получившееся изделие — доработайте напильником”. Я не хочу дорабатывать паровоз до самолета напильником. Я хочу чтобы все сносно работало прямо “из коробки”.
Введение в Zend Framework
Update (2014): Это статья 2007 года, которая, к моему удивлению, до сих пор пользуется спросом. По этой причине я обновил её в соответствии с новыми правилами оформления постов на Хабре, и добавил подсветку синтаксиса для примеров кода. Если кому-то захочется что-то добавить или исправить, исходник текста с хабра-разметкой выложен в открытый доступ: gist.github.com/dreikanter/2b4ee996d7a775e707d7
Аннотация от переводчика
PHP — один из самых широко распространенных языков разработки веб-приложений и при этом один из самых спорных. Я очень часто видел негативное отношение к этой технологии, да и недостатки, провоцирующие это отношение — не для кого не являются секретом. Тем не менее, PHP активно эволюционирует и во многих отношениях постепенно становитс лучше. Одним из серьезных шагов его развития, на мой взгляд, является появление MVC-фреймворков, призванных систематизировать процесс разработки веб-приложений и приучить к порядку разработчиков, которым зачастую здорово не хватает силы воли, чтобы при всей предоставляемой языком свободе, сохранить грамотную и красивую инфраструктуру разрабатываемого ПО (сразу уточню, что последнее утверждение субъективно и основано исключительно на виденном мной коде различных программных решений).
В последнее время я активно заинтересовался архитектурой MVC и сделал свою собственную реализацию фреймворка на этой концепции для PHP4. Совсем недавно на глаза попался первый официальный релиз Zend Framework, о котором я давно слышал, но все руки не доходили с ним поиграть. Для PHP существуют и другие подобный библиотеки, но в данном случае привлек бренд.
Вначале я испытал некоторое разочарование в официальной документации, которая оказалась хорошим reference-ом, но просто никаким tutorial-ом и поэтому на роль вводного материала не подошла. Но почти сразу нашлась неплохая статья, в которой автор пошагово разбирает процесс создания веб-приложения. Материала достаточно, чтобы разобравшись в нем можно было начать осмысленно ориентироваться в мане от Zend. Текст ориентирован на программистов, имеющих некоторый опыт в программировании веб-приложений на PHP, но не знакомых с Zend Framework.
Статья довольно объемная, поэтому я решил разделить ее на две части, дабы не перегружать никому мозг. Ниже я привожу первую часть ее перевода, в которой в общих чертах освещена концепция MVC и разобрана структура веб-приложения, реализованного на Zend Framework. Если материал заинтересует хабрачитателей, я опубликую продолжение.
В завершение введения, небольшой дисклаймер. Уважаемые любители Ruby on Rails и Python on Django, я уважаю вашу религию 🙂 Убедительная просьба не развивать в комментариях тему о том, какой фреймворк или язык лучше. Это совсем не относящаяся к топику данного поста тема. Мне и, вероятно, многим сейчас будет гораздо интереснее узнать об опыте реальных разработок ПО на Zend.
Материал рассчитан на то, чтобы дать общее представление об использовании Zend Framework для создания простейших приложений с использованием баз данных. Приведенные примеры были протестированы на Zend Framework версии 1.0.0. Скорее всего, они будут работать и с более поздними версиями, но не с более ранними.
Архитектура Модель-Вид-Контроллер
PHP-приложение, написанное традиционным способом, может представлять собой некое подобие следующего примера:
В ходе жизненного цикла приложений подобного типа, трудоемкость их поддержки становится крайне высока, т. к. меняющиеся требования заказчика приводят к необходимости вносить большое количество изменений («заплаток») в исходный код. Это делает его плохо структурированным и трудно читаемым. Один из методов для повышения гибкости приложения состоит в разделении кода на три категории:
Системные требования
У Zend Framework следующие требования:
Где скачать Zend Framework
Zend Framework доступен для свободного скачивания в виде ZIP или TAR.GZ архивов по адресу framework.zend.com/download/stable.
Структура директорий
На данный момент в Zend Framework жестко не стандартизирована структура директорий приложения, но в официальной документации рекомендуется использовать общепринятую схему. Эта схема основана на том, что пользователь, как предполагается, имеет полный доступ к конфигурированию сервера Apache. Мы же будем использовать немного видоизмененный подход, чтобы смягчить данные требования и сделать Zend Framework более применимым в условиях широко распространенного разделяемого хостинга.
Для начала, создайте директорию zf-tutorial в корневом каталоге вашего тестового веб-сайта. Это будет означать, что URL этой директории примет вид localhost/zf-tutorial (адрес может варьироваться, в зависимости от настроек вашего сервера).
После этого дополнительно создайте следующую структуру каталогов для хранения файлов веб-приложения:
Начальная загрузка
zf-tutorial/application /.htaccess, zf-tutorial/library/.htaccess:
Файл начальной загрузки index.php
Файл начальной загрузки zf-tutorial/index.php содержит следующий код:
Рассмотрим код подробнее.
Данные строки обеспечивают вывод интерпретатором всех сообщений о происходящих ошибках (подразумевается, что в конфигурационном файле php.ini параметру display_errors задано значение on ). Вторая строка кода задает часовой пояс, согласно стандартному требованию PHP 5.1+. Приведенное в примере значение параметра следует заменить на соответствующее вашему географическому положению.
Файл Zend/Loader.php содержит класс Zend_Loader со статическими функциями, позволяющими подключать любой класс из Zend Framework.
Далее нам понадобится сообщить первичному контроллеру о местоположении директории с другими контроллерами:
Учитывая, что наша программа предназначена для образовательных целей и функционирует на тестовой системе, можно разрешить все исключения, которые могут происходить при ее работе. По-умолчанию, первичный контроллер будет перехватывать их все до одного и хранить в свойстве _exceptions своего объекта (данному объекту соответствует англоязычный термин Response object). Этот объект используется для хранения всей информации, возвращаемой при обращении к заданному URL, что включает HTTP-заголовок, содержимое веб-страницы и массив произошедших исключений.
Первичный контроллер автоматически выдает заголовок и контент страницы непосредственно перед окончанием своей работы. Тех, кто ранее не встречался с архитектурой веб-приложений, подобной Zend Framework, может привести в некоторое недоумение тот факт, что для отображения сообщений об исключительных ситуациях, их (исключения) необходимо повторно возбуждать. Эта особенность становится актуальной для серверов, работающих в своем штатном режиме, когда вывод сообщений об ошибках на страницах неуместен.
В итоге, после всех выполненных приготовлений, наше приложение может быть запущено:
Это говорит о том, что мы еще не до конца сформировали наше веб-приложение. и прежде чем приступить к делу, стоит уяснить, в чем конкретно состоит задача.
Веб-сайт
Предположим, что мы хотим создать простую базу данных для хранения информации о компакт-дисках. На главной странице будет отображен список дисков в нашей коллекции, а так же будет предоставлена возможность добавлять новые CD, редактировать и удалять ненужные записи. Для хранения данных, используем базу со схемой, приведенной ниже:
Fieldname | Type | Null? | Notes |
---|---|---|---|
id | Integer | No | Primary key, Autoincrement |
artist | Varchar(100) | No | |
title | Varchar(100) | No |
Необходимые страницы
Для реализации перечисленных выше функций, нам понадобятся следующие страницы:
Организация страниц
Прежде чем приступить к созданию файлов, следует понять, как принято организовывать их в Zend Framework. Согласно принятой терминологии, каждая страница веб-приложения определяется термином «действие».
Примечание переводчика. Небольшое пояснение терминологии. Англоязычным оригиналом используемого в данной статье термина «действие» является слово action. Приведенный перевод на данный момент еще не является устоявшимся понятием, и в некоторых текстах о модели MVC вместо него попадаются иные определения. Например, так же известна прямая (и режущая слух) транслитерация — «экшен».
В Zend Framework так же используются модули для группировки контроллеров, но наше приложение не настолько велико, чтобы имело смысл их применять.
Учитывая, что данная статья ориентирована на первое знакомство с Zend Framework, мы не будем пока касаться таких нюансов работы веб-приложения, как авторизация пользователей. Ограничимся реализацией основной функциональности, а именно — набором перечисленных выше страниц. Учитывая, что все они относятся к работе с альбомами, можно отнести их к одному контроллеру. Мы используем стандартный контроллер, а его действия будут выглядеть следующим образом:
Страница | Контроллер | Действие |
---|---|---|
Начальная страница | Index | Index |
Добавить альбом | Index | Add |
Редактировать альбом | Index | Edit |
Удалить альбом | Index | Delete |
Настройка контроллера
В данном макете контроллера каждое действие будет выводить свое имя. Это можно протестировать, задавая приведенные ниже URL:
URL | Displayed text |
---|---|
localhost/zf-tutorial | in IndexController::indexAction() |
localhost/zf-tutorial/index/add | in IndexController::addAction() |
localhost/zf-tutorial/index/edit | in IndexController::editAction() |
localhost/zf-tutorial/index/delete | in IndexController::deleteAction() |
Теперь у нас имеется работающий класс-роутер с набором действий, соответствующих каждой странице веб-приложения. При возникновении каких-либо проблем в процессе его создания, обратитесь к разделу «Устранение неполадок» в конце статьи.
А теперь пришло время добавить в наше приложение новый вид.
Простейший вариант использования Zend_View выглядит как показано ниже:
Легко можно понять, что если бы мы захотели поместить приведенный код в каждую функцию-действие, это привело бы к его многократному дублированию, что не явилось бы красивым решением. Вместо этого, мы выполним инициализацию вида отдельно, а из функций-действий затем будем только обращаться к нему.
После рендеринга, сгенерированный контент веб-страницы сохраняется в объекте Response, который, как было упомянуто ранее, служит для группировки HTTP заголовков, содержимого страницы и сгенерированных в ходе работы скрипта исключительных ситуаций. в итоге, первичный контроллер автоматически отсылает веб-клиенту заголовок страницы и ее содержательную часть.
Итак, для того, чтобы добавить вид в наше приложение, все, что нам потребуется, — создать несколько файлов с тестовым кодом. Никаких принципиальных изменений внутри контроллера не понадобится, но для большей наглядности мы выполним небольшую корректировку выводимого им текста.
Изменения внутри класса IndexController выделены жирным шрифтом.
Теперь нам понадобится добавить четыре файла для видов нашего веб-приложения.
При тестирование каждого из действий, должны быть отображены выделенные заголовки каждой из страниц.
Общий HTML-код
(Обратите внимание на изменения, добавленный в код.)
Файлы видов так же понадобится откорректировать.
Стилевое оформление
Ссылку на CSS-фалй понадобится добавить в секцию файла header.phtml :
В завершении, понадобится создать, собственно, сам стилевой файл.
Это заставит страницы выглядеть несколько приятнее.