e2 По мнению Яндекса, самый лучший движок для создания блогов. Разработан относительно недавно Ильей Бирманом на PHP. Главное отличие этого движка от других – отсутствие отдельной админки, все управление проходит в пользовательском интерфейсе, на котором владельцу блога доступны дополнительные функции, которых достаточно много.
Приложение 2
Программный код, использовавшийся в практической части
Листинг 1.1 Перенаправление запросов к веб-сайту через файл index.php
(файл .htaccess)
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
Листинг 1.2 Обработка пользовательских запросов методами класса Zend-Controller(файл index.php)
<?php
require_once('Zend/Loader.php');
Zend_Loader::registerAutoload();
$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory($config->paths->base .
'/include/Controllers');
$controller->dispatch();
?>
Листинг 1.3 Контроллер index, используемый на главной странице веб-приложения (файл IndexController.php)
<?php
require_once('CustomControllerAction.php');
class IndexController extends CustomControllerAction
{
public function indexAction()
{
Echo’Будущий школьный сайт’;
}
}
?>
Листинг 1.4 Начальные настройки приложения (файл settings.ini)
[development]
database.type = pdo_mysql
database.hostname = localhost
database.username = phpweb20
database.password = myPassword
database.database = phpweb20
paths.base = /var/www/phpweb20
paths.data = /var/www/phpweb20/data
paths.templates = /var/www/phpweb20/templates
logging.file = /var/www/phpweb20/data/logs/debug.log
Листинг 1.5 Загрузка рабочих настроек приложения с использованием класса Zend_Config_Ini(файл index.php)
$config = new Zend_Config_Ini('../settings.ini', 'development');
Zend_Registry::set('config', $config);
$controller->setControllerDirectory($config->paths->base .
'/include/Controllers');
Листинг 1.6 Расширение Smarty для использования в веб-приложении
(файл Templater.php)
<?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/templates_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, $val)
{
$this->_engine->assign($key, $val);
}
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()
{ }
}
?>
Листинг 1.7 Новыйконтроллер, выводящийфайл index.tpl
(файл IndexController.php)
<?
class IndexController extends CustomControllerAction
{
public function indexAction()
{
}
}
?>
Листинг 1.8 Шаблондляоперации index контроллера index
(файл index.tpl)
{include file='header.tpl'}
Будущийспортивныйсайтшколы
{include file='footer.tpl'}
Листинг 1.9 ФайлзаголовкаHTML-страницы
(файл header.tpl)
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251 " />
</head>
<body>
<div>
Листинг 1.10 Файл конца страницы, в котором закрываются тэги, открытые в заголовке(файл footer.tpl)
</div>
</body>
</html>
Листинг 2.1 Загрузочный файл приложения с использованием компонента Zend_Auth(файл index.php)
// настройка утентификации пользователей
$auth = Zend_Auth::getInstance();
$auth->setStorage(new Zend_Auth_Storage_Session());
$controller->registerPlugin(new CustomControllerAclManager($auth));
Листинг 2.2 Подключаемый модуль CustomControllerAclManager, проверяющий допуски перед отправкой запроса на обработку
(файлCustomControllerAclManager.php)
<?php
class CustomControllerAclManager extends Zend_Controller_Plugin_Abstract
{
// роль по умолчанию, если не вошел (или роль не определена)
private $_defaultRole = 'guest';
// выполнить операцию, если у пользователя не хватает привилегий
private $_authController = array('controller' => 'account',
'action' => 'login');
public function __construct(Zend_Auth $auth)
{
$this->auth = $auth;
$this->acl = new Zend_Acl();
// добаляемновыероли
$this->acl->addRole(new Zend_Acl_Role($this->_defaultRole));
$this->acl->addRole(new Zend_Acl_Role('member'));
$this->acl->addRole(new Zend_Acl_Role('administrator'), 'member');
// добавляемконтролируемыересурсы
$this->acl->add(new Zend_Acl_Resource('account'));
$this->acl->add(new Zend_Acl_Resource('admin'));
// по умолчанию даем всемпользователям доступ ко всему
// кроме управления учетными записями и администрированием
$this->acl->allow();
$this->acl->deny(null, 'account');
$this->acl->deny(null, 'admin');
// добавляем исключение. чтобы гости могли войти или
// зарегистрироваться, если нет привилегий
$this->acl->allow('guest', 'account', array('login',
'fetchpassword',
'register',
'registercomplete'));
// позволяем зарегистрированным пользователям доступ к управлению учетными записями
$this->acl->allow('member', 'account');
// даем администраторам доступ в область администрирования
$this->acl->allow('administrator', 'admin');
}
/**
* preDispatch
*
* Прежде, чем отправлять запрос на обработку, проверяет есть ли у пользователя
* нужные привелегии. Если нет, инициирует операцию по умолчанию
*
*
* @param Zend_Controller_Request_Abstract $request
*/
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
// проверка, вошел ли пользователь и имеет ли нужную роль
// если нет, то назначается роль по умолчанию (гость)
if ($this->auth->hasIdentity())
$role = $this->auth->getIdentity()->user_type;
else
$role = $this->_defaultRole;
if (!$this->acl->hasRole($role))
$role = $this->_defaultRole;
// контролируемый ресурс - имя запрашиваемого контроллера
$resource = $request->controller;
// привилегия - имя запрашиваемой операции
$privilege = $request->action;
// если ресурс не определен явно. проверить
// глобальныедопускипоумолчанию
if (!$this->acl->has($resource))
$resource = null;
// в допуске отказано. Выполняется операция по умолчанию
if (!$this->acl->isAllowed($role, $resource, $privilege)) {
$request->setControllerName($this->_authController['controller']);
$request->setActionName($this->_authController['action']);
}
}
}
?>
Листинг 2.3 Первоначальная версия класса DatabaseObject_User
(файлuser.php)
<?
class DatabaseObject_User extends DatabaseObject
{
static $userTypes = array('member' => 'Member',
'administrator' => 'Administrator');
public $profile = null;
public $_newPassword = null;
public function __construct($db)
{
parent::__construct($db, 'users', 'user_id');
$this->add('username');
$this->add('password');
$this->add('user_type', 'member');
$this->add('ts_created', time(), self::TYPE_TIMESTAMP);
$this->add('ts_last_login', null, self::TYPE_TIMESTAMP);
}
}
?>
Листинг 2.4 Полныйтексткласса FormProcessor_UserRegistration
(файлUserRegistration.php)
<?php
class FormProcessor_UserRegistration extends FormProcessor
{
protected $db = null;
public $user = null;
public function __construct($db)
{
parent::__construct();
$this->db = $db;
$this->user = new DatabaseObject_User($db);
$this->user->type = 'member';
}
public function process(Zend_Controller_Request_Abstract $request)
{
// проверкаправильностиимени
$this->username = trim($request->getPost('username'));
if (strlen($this->username) == 0)
$this->addError('username', 'Please enter a username');
else if (!DatabaseObject_User::IsValidUsername($this->username))
$this->addError('username', 'Please enter a valid username');
else if ($this->user->usernameExists($this->username))
$this->addError('username', 'The selected username already exists');
else
$this->user->username = $this->username;
// проверкаимениифамилии
$this->first_name = $this->sanitize($request->getPost('first_name'));
if (strlen($this->first_name) == 0)
$this->addError('first_name', 'Please enter your first name');
else
$this->user->profile->first_name = $this->first_name;
$this->last_name = $this->sanitize($request->getPost('last_name'));
if (strlen($this->last_name) == 0)
$this->addError('last_name', 'Please enter your last name');
else
$this->user->profile->last_name = $this->last_name;
// проверкаадресаэлектроннойпочты
$this->email = $this->sanitize($request->getPost('email'));
$validator = new Zend_Validate_EmailAddress();
if (strlen($this->email) == 0)
$this->addError('email', 'Please enter your e-mail address');
else if (!$validator->isValid($this->email))
$this->addError('email', 'Please enter a valid e-mail address');
else
$this->user->profile->email = $this->email;
$session = new Zend_Session_Namespace('captcha');
$this->captcha = $this->sanitize($request->getPost('captcha'));
if ($this->captcha != $session->phrase)
$this->addError('captcha', 'Please enter the correct phrase');
// если ошибок нет, сохранить данные пользоваетля
if (!$this->hasError()) {
$this->user->save();
unset($session->phrase);
}
// возвратtrue, еслинетошибок
return !$this->hasError();
}
}
Листинг 2.5 Шаблон HTML для формы регистрации пользователей
(файл register.tpl)
{include file='header.tpl'}
<form method="post" action="/account/register">
<fieldset>
<legend>Создание аккаунта</legend>
<div class="error"{if !$fp->hasError()} style="display: none"{/if}>
Заполните поля
</div>
<div class="row" id="form_username_container">
<label for="form_username">Логин:</label>
<input type="text" id="form_username"
name="username" value="{$fp->username|escape}" />
{include file='lib/error.tpl' error=$fp->getError('username')}
</div>
<div class="row" id="form_email_container">
<label for="form_email">E-mail:</label>
<input type="text" id="form_email"
name="email" value="{$fp->email|escape}" />
{include file='lib/error.tpl' error=$fp->getError('email')}
</div>
<div class="row" id="form_first_name_container">
<label for="form_first_name">Имя:</label>
<input type="text" id="form_first_name"
name="first_name" value="{$fp->first_name|escape}" />
{include file='lib/error.tpl' error=$fp->getError('first_name')}
</div>
<div class="row" id="form_last_name_container">
<label for="form_last_name">Фамилия:</label>
<input type="text" id="form_last_name"
name="last_name" value="{$fp->last_name|escape}" />
{include file='lib/error.tpl' error=$fp->getError('last_name')}