Webformyself создание собственного фреймворка торрент
Для начинающих «велосипедистов» иль просто любопытствующих…
Данная статья не призыв к действию, а лишь небольшая зарисовка на тему «Как бы я это сделал». На данный момент у меня в отделе активно используется Zend Framework, и именно с ним я лучше всего знаком, поэтому не пугайтесь параллелей, это не реклама, ведь большинство фреймворков в равной степени сочетают в себе плюсы и минусы, а нам нужны лишь преимущества…
Правила
- Стандарты кодирования — лучше воспользоваться существующими, советую стандарты Zend Framework'а
- Процесс добавления кода в репозиторий (даже если вы сами в проекте — это будет хорошо дисциплинировать), только не перегибайте палку, иначе это замедлит развитие проекта
Архитектура
Надеюсь большинство читателей уже знакома с патерном MVC (Model-View-Controller) — так давайте на нем и базировать наш фреймворк, использования чего-то иного, боюсь, будет отпугивать пользователей (тут я подразумеваю программистов :) ).
Model
В типовом проекте модель завязывается на одну таблицу в базе данных, но исключений хватает, поэтому не следует принимать данное утверждение за аксиому. Наша модель должна с легкостью работать с различными хранилищами данных, будь то БД, файлы, или память.
Давайте представим как может выглядеть модель:
// модель User использует в качестве хранилища БД
class Model_User extends Framework_Model_Database
<
$_table = "users" ;
$_pkey = "id" ;
function getByLogin ( $login ) < /*. */ >
function getByEmail ( $email ) < /*. */ >
>
// модель MainConfig использует в качестве хранилища ini файл
class Model_MainConfig extends Framework_Model_Ini
<
protected $_file = "application.ini" ;
function setOption ( $key ) < /*. */ >
function getOption ( $key ) < /*. */ >
>
// модель Registry использует в качестве хранилища память - некая альтернатива глобальным переменным
class Model_Registry extends Framework_Model_Memory
<
function setOption ( $key ) < /*. */ >
function getOption ( $key ) < /*. */ >
>
// модель Session использует в качестве хранилища файлы сессии
class Model_Session extends Framework_Model_Session
<
protected $_namespace = "global" ;
function setOption ( $key ) < /*. */ >
function getOption ( $key ) < /*. */ >
>
В действительности такими примерами я сильно коверкаю представление о MVC — ведь зачастую под моделью подразумевают некую бизнес модель, но никак не сессию или конфигурационный файл.
Каковы нынче требования к шаблонизатору? Лично для меня нативный PHP синтаксис, поддержка различного рода хелперов и фильтров. Так же должен быть реализован паттерн «двухэтапного представления» (Two Step View pattern), в ZF для этого служат два компонента — Zend_View и Zend_Layout.
Приведу пример такого представления:
<?php if ( $this -> books ) : ?>
<!-- Таблица из нескольких книг. -->
<table>
<tr>
<th>Author</th>
<th>Title</th>
</tr>
<?php foreach ( $this -> books as $key => $val ) : ?>
<tr>
<td> <?php echo $this -> escape ( $val [ 'author' ] ) ?> </td>
<td> <?php echo $this -> escape ( $val [ 'title' ] ) ?> </td>
</tr>
<?php endforeach ; ?>
</table>
<?php else : ?>
<p>Нет книг для отображения.</p>
<?php endif ; ?>
Пример использование layout'ов (взят из документации по Zend_Layout):
О да, в Zend Framework'е удачная реализация представления, она мне нравится, конечно, не без мелких нареканий, но в целом — это пять.
Controller
Контроллер должен выполнять свои обязанности — обрабатывать запрос, пинать модель и представление — дабы пользователь получил желаемый результат.
Так, проведем разбор — у нас просят показать профайл пользователя с Соответственно напрашивается существование контроллера users с методом profile, который бы смог получить в качестве параметра некий id:
// название контроллера должно содержать префикс - дабы чего не напутать
class Controller_Users extends Framework_Controller_Action
<
public function actionProfile ( )
<
// получаем данные из запроса
$id = $this -> request -> get ( 'id' ) ;
// пинаем модель
$user = new Model_User ( ) ;
$user -> getById ( $id ) ;
// закидываем данные в представление
$this -> view -> user = $user ;
>
>
Естественно, на плечи контроллера так же ложится обязанность изменять формат представление, т.е. если нам надо вернуть данные в JSON формате, то никакого иного вывода быть не должно (это и так подразумевается самим MVC, но стоит лишний раз напомнить).
Кто повнимательней увидит в данном примере появление некого Request'a — это объект который занимается разбором входящего запроса. Зачем он нужен — об этом чуть далее.
Routers
Теперь немного о требованиях со стороны конечных пользователей — в частности о ЧПУ. Сравните следующие варианты ссылок:
Для генерации/разбора подобного входящего запроса в ZF используются роутеры — по факту — это правила построения URL'ов, нам так же придется их реализовать — и с этим сложно поспорить.
Вы наверное захотите сразу засунуть данный функционал непосредственно в класс Request, но не спешите, ведь нам еще потребуется генерировать правильные URL во View — а вызывать там объект Request — немного не логично, давайте таки оставим это на совести отдельного класса, к которому может обращаться как Request так и View
Request & Response
- обработка входящих параметров всеми правилами из Router'а
- отдавать параметры в контроллер по требованию
- формировать заголовок ответа
- формировать ответ — т.е. брать view, оборачивать в некий layout и на выход
Мне не очень нравится реализация Response в ZF — слишком много лишнего в нем
Modules
Фреймворк должен быть модульным, т.е. написав какой-то модуль (блог, форум, и т.д.) вы сможете с легкостью использовать данный код в других приложениях. Для этого нам понадобится лишь отделить MVC каждого модуля в свою директорию, при этом какой-то модуль останется за главного.
Теперь стоит перейти к самому вкусному — непосредственно к ядру системы, его функционал мы практически уже описали, стоит лишь подвести черту:
- При инициализации входящий запрос должен быть обработан всеми правилами Router'ов, дабы объект Request мог вернуть нам запрашиваемое значение по ключу
- Объект Request так же должен знать, какой модуль/контроллер/экшен запрашивается
- Ядро должно подгрузить необходимый контроллер и вызвать запрашиваемый экшен (метод контроллера)
- После отработки контроллера вызывается Response и ставит точку
Вспомогательный классы
Если вы захотите потренироваться в написании «велосипедов», то можете начать отсюда:
- Работа с БД — необходима поддержка MySQL, SQLite, PostgreSQL (это минимум), а в целом стоит уделить этому пункту много внимания, т.к. он один может привлечь множество пользователей
- Валидаторы — необходимая вещь, для экономии времени при написании форм (см. Zend_Validate)
- Транслятор — для реализации мультиязычности в системе, возможно хватит и gettext'a, но не стоит на это надеяться
- Почта — можно обойтись лишь функцией mail, но это как-то не по-взрослому
- Пагинатор — для решения тривиальной задачи — разбиение по страницам (см. Zend_Paginator)
- Навигатор — построение меню, карты сайта и «хлебных крошек» (см. Zend_Navigation)
- Кэширование — без него никуда (см. Zend_Cache)
- Конфигурационные файлы — Zend_Config слишком большой для того, чтобы обрабатывать лишь один ini файл, тут можете попрактиковаться, но все же посматривайте на Zend_Config_Ini
- Автозагрузчик — очень полезная вещь, и главное удобное — Zend_Loader
- ACL — возможно потребуется — по крайней мере, распределение прав по запросу модуль/контроллер/экшен лучше пусть будет зашит в системе
Я не случайно привожу ссылки на пакеты Zend Framewrok'а — они вполне адекватны и самостоятельны, могут быть использованы сами по себе, т.е. никто ведь не машает вам построить свой фреймворк из кубиков Zend'a (и вот тому пример: ZYM)
Тривиальные задачи
В фреймворке должен быть заложен функционал для решения следующих тривиальных задач (мелких и не очень):
Еще лучше, если с фреймворком будет поставляться готовая к использованию CMS система — она позволит популяризировать ваше детище, и возможно привлечет сторонних разработчиков.
Структура каталога
И так, что у нас получается, если взглянуть на файловую систему (в document_root должна лежать лишь папка public):
Это лишь мое пожелание, какой же она будет у вас — решать вам…
Вывод
To Be Or Not To Be — решать вам, как по мне — можно смириться с недостатками какого-то одного фреймворка, и наслаждаться его преимуществами. Возможно, вы попытаетесь написать свое решение или скрестить существующие, но не забываете — написание такого рода приложения влечет за собой ответственность по его поддержке.
Читайте также: