Пишем блог на Zend Framework и Smarty: часть 1 — подготовка
by Вредный • 17.03.2010 • php, Zend Framework, программирование • Комментарии [7]
Сегодня мы начнем создавать свой полноценный блог с комментариями; писать в него могут сразу несколько человек по своими именами.
Мы будем использовать последнюю на сегодняшний день версию Zend Framework’а. Еще один плюс этого блога в том, что мы сделаем его таким, чтобы он смог запускаться легко на локальном компьютере и на выделенном хостинге, что не просто сделать, следую инструкции разработчиков.
Что нам для этого понадобится.
1) Конечно же веб-сервер (как установить его вы можете прочесть здесь). Хотя с лихвой хватит XAMPP установленного в корень какого-нибудь диска.
2) Zend Framework последней версии, на момент написания последней версией был 1.10.2, скачать вы можете с официального сайта.
3) Среда разработки, я использую для этих целей бесплатную NetBeans, но вы можете писать весь код и в блокноте, это не возбраняется.
4) Немного терпения, потому как с первого раза может что-то не получиться.
Начнем с организации каталога с проектом. У меня установлен XAMPP на диск D, исходя из этого и будут организовываться пути, будьте внимательнее.
Сначала перенаправляем все запросы в файл index.php, находящемуся в корне нашего проекта.
.htaccess
1 2 3 4 | RewriteEngine on RewriteCond %{SCRIPT_FILENAME} -f RewriteCond %{SCRIPT_FILENAME} -d RewriteRule ^(.*)$ index.php/$1 |
Вторая строка включает перенаправление, если ссылка не на реальный файл, находящийся на сервере, третья строка — для каталогов.
Теперь самый важный файл в нашем проекте
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/application')); defined('APPLICATION_ENV') || define('APPLICATION_ENV', 'development'); set_include_path(implode(PATH_SEPARATOR, array( realpath(APPLICATION_PATH . '/../library'), get_include_path(), ))); require_once 'Zend/Application.php'; require_once 'Zend/Loader/Autoloader.php'; Zend_Loader_Autoloader::getInstance(); |
В этом участке мы определяем константы, если они не установлены, первая это путь к /application, вторая — переменная среды. Дальше мы включаем в путь папку library, в которой находится Zend Framework (скопируйте туда папку Zend, если вы не сделали этого раньше, у вас должно получиться что-то вроде ./library/Zend).
В последующих 2х строчках подключаем 2 класса, один главный, который и запускает приложение, второй для того, чтобы не подключать нужные классы во время разработки. Zend_Loader_Autoloader — позоволяет это делать автоматически.
Пока оторвемся от главного файла и напишем файл конфига, из которого мы и будем по мере надобности брать данные (подключение к базе данных, пути и прочее).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | [development] database.type = pdo_mysql database.username = blog database.password = blog database.dbname = blog paths.base = D:\xampp\htdocs\blog paths.templates = D:\xampp\htdocs\blog\templates paths.data = D:\xampp\htdocs\blog\data logging.file = D:\xampp\htdocs\blog\debug.log phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" |
Т.к. только разрабатываем свое приложение, мы используем раздел ‘development’, следующие 4 строчки задают как подключаться с базе данных, рекомендую вам тоже создать базу данных blog на localhost, пользователь и пароль blog.
Следующие строчки paths.* задают абсолютные пути к папке с данными, о которой мы поговорим позже, базовый путь, где находится наш проект и путь к шаблонам Smarty, о которых тоже позже.
Строки bootstrap.* указывают расположения класса инициализации, которым мы воспользуемся чуть позже.
Последняя строка указывает местонахождения контроллеров.
Давайте теперь создадим класс, которым будем расширять все наши контроллеры, т.е. вмето того, чтобы писать
1 | class IndexController extends Zend_Controller_Action |
будем писать
1 | class IndexController extends CustomControllerAction |
, чтобы иметь доступ ко многим конфигурационным данным.
Класс ./library/CustomControllerAction
1 2 3 4 5 6 7 8 | <?php class CustomControllerAction extends Zend_Controller_Action { public $db; public function init() { $this->db = Zend_Registry::get('db'); } } |
Как вы помнить из Hello world на Zend Framework в конце мы закрывающийся тег php не ставим.
Класс ./application/Bootstrap.php пока пуст
1 2 3 4 | <?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { } |
Вернемся к ./index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | require_once 'CustomControllerAction.php'; $config = new Zend_Config_Ini('/application/configs/application.ini', 'development'); Zend_Registry::set('config', $config); $params = array('host' => $config->database->hostname, 'username' => $config->database->username, 'password' => $config->database->password, 'dbname' => $config->database->database); $db = Zend_Db::factory($config->database->type, $params); Zend_Registry::set('db', $db); $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); |
Здесь мы подключаем класс, которым и расширяем Zend_Controller_Action, дальше мы создаем конфиг из нашего конфигурационного файла, указывая вторым параметром имя секции, в нашем случаем [development]
И сохраняем этот конфиг в реестре Zend Framework, чтобы иметь доступ к нему из любого места нашего приложения.
Массив $params содержит данные для подключения к базе данных, в данном случае MySQL, но мы с легкостью сможем заменить ее на что-нибудь другое.
В переменной $db идентификатор соединения, который мы тоже сохраняем в реестр.
Дальше мы передаем параметры нашему приложению и запускаем
1 2 | $application->bootstrap() ->run(); |
Если вам захочется запустить приложение, то вас ждет неудача, наберитесь терпения, все будет работать, я вам обещаю =)
Т.к. мы вместо встроенного шаблонизатора в Zend Framework, будем использовать Smarty, который вы можете на официальном сайте smarty.net, оттуда нам лишь понадобится лишь папка libs, из который мы копируем все в папку с нашими библиотеками ./library/Smarty.
Теперь мы напишем свой класс Templater, расширяющий Zend_View_Abstract, который будет отвечать за отображение информации на нашем блоге.
Файл ./library/Templater.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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <?php class Templater extends Zend_View_Abstract { protected $_path; protected $_engine; public function __construct() { $config = Zend_Registry::get('config'); require_once 'Smarty/Smarty.class.php'; $this->_engine = new Smarty(); $this->_engine->template_dir = $config->paths->templates; $this->_engine->compile_dir = sprintf('%s/tmp/template_c', $config->paths->data); $this->_engine->plugins_dir = array($config->paths->base . '/include/Templater/plugins', 'plugins'); } public function getEngine() { return $this->_engine; } public function __set($key, $value) { $this->_engine->assign($name, $value); } public function __get($key) { return $this->_engine->get_template_vars($key); } public function __isset($key) { return $this->_engine->get_template_vars($key) !== null; } public function __unset($key) { $this->_engine->clear_assign($key); } public function assign($spec, $value = null) { if (is_array($spec)) { $this->_engine->assign($spec); return; } $this->_engine->assign($spec, $value); } public function clearVars() { $this->_engine->clear_all_assign(); } public function render($name) { return $this->_engine->fetch(strtolower($name)); } public function _run() { } } |
getEngine() — возвращает экземпляр класса Smarty. Т.к. этот метод может вызывать несколько раз, нам необходимо кэшировать объект Smarty, чтобы он не создавался более одного раза. Это происходит в конструкторе этого класса.
__set() — присваиваем переменную шаблону. Кто знаком со Smarty $smarty->assign(‘key’, ‘val’);
_get() — ранее присвоенную переменную возвращаем.
render() визиализируем шаблон, вызывая метод fetch().
Теперь наш класс нужно прикрутить к нашему приложению. Для этого в файле ./index.php перед
$application->bootstrap()->run();
допишем
1 2 3 4 5 | require_once 'Templater.php'; $vr = new Zend_Controller_Action_Helper_ViewRenderer(); $vr->setView(new Templater()); $vr->setViewSuffix('tpl'); Zend_Controller_Action_HelperBroker::addHelper($vr); |
Создадим шаблон для вывода информации ./templates/index/index.tpl
1 2 3 | {include file='header.tpl'} Мой первый блог {include file='footer.tpl'} |
Шаблоны для шапки и футера соответственно:
./templates/header.tpl
1 2 3 4 5 6 7 8 9 10 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//RU" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ru" xml:lang="en"> <head> <title>Title</title> <meta http-equiv="Content-Type" content="text/html; charset="utf-8" /> </head> <body> <div> |
./templates/footer.tpl
1 2 3 | </div> </body> </html> |
Все, что сейчас умеет делать наше приложение, это выводить фразу «Мой первый блог», но на самом деле мы сделали очень много, дальше будет еще интереснее, подписывайтесь на rss, чтобы не пропустить создание блога на Zend Framework и Smarty, вопросы, пожелания и дополнения приветствуются.

Совершенно, извиняюсь, мудацкий способ задания архитектуры приложения.
Bootstrap как будто бы не существует. Вы просто создали файл и задали наследование от базового бутстрапа. Было бы неплохо прочитать, что такое Bootstrap и зачем он нужен.
Тем не менее, вы используете Zend_Application, начисто игнорируя уже упомянутый Bootstrap. Прочитайте тоже, что такое Zend_Application.
Инциализировать БД в index.php — бред. А вдруг в каком-то контроллере БД вообще не нужна?
Про наследование базового контроллера вообще молчу. Базовый контроллер зенда _почти_ полноценен и самодостаточен, 99.9% дополнительных нужд решаются помощниками действий, плагинами. Прочитайте и про них.
В общем, ваша статья — хороший пример из разряда «пишу, лишь бы работало». Новичкам эта статья хорошего не принесет ровным счетом ничего, а вот мозг запудрит капительно. За такой подход к проектированию надо расстреливать на месте.
P.S. Думал, может какой-то древний материал попался. Ан-нет, «was posted by admin on 17.03.2010″. Так что мои претензии законны.
спасибо за информативный комментарий, постараюсь исправить это в следующих заметках
Вообще то неплохо было бы упомянуть что код скопирован из книги Квентина Зерваса «Web 2.0 Создание приложений на PHP». Даже переменные не переименованы.
вы правы, каюсь, это был не очень удачный опыт начала по не актуальной на сей день книге
нужно лишь было взять ее как отправную точку
Да все ок, чего ты оправдываешься?.
Спасибо sadreamer что так подробно разяснил, Я чувствовал что что-то не так слишком уж все в тупик заходит в этом методе.Сейчас доки читаю разбираюсь…Действительно не помешал бы пример блога на Zend только новой ветки 1.11.X Для новичков.
Давайте попробуем своими силами написать блог, есть опыт разработки комментируемых штук. Если есть желание можно раализовать.