PHP, начиная с версии 5.3, подарил нам пространство имен. С тех пор идет где-то вялое, а где-то бурное обсуждение, как же это пространство имен использовать?
Некоторые фреймворки, такие как Symphony, Laravel, и, конечно же Zend взяли эту технологию на вооружение.
Все это более или менее вписалось в схему MVC. Осталась одна, наверное вечная, дискуссия, какой же должна быть главная брачная пара приложения — Модель и Контроллер?
Одни нам говорят, что Модель должна быть дородной и толстой и при ней стройный и тонкий Контроллер. Одним словом — матриархат.
Другие, наоборот, считают, что Контроллер должен всем управлять и повелевать, поэтому он получается основательный, упитанный. И при нем худенькая, стройненькая Модель, задача которой сводится к подай-принеси. Такой вот патриархат.
Так что же лучше в схеме MVC? Патриархат или матриархат?
Давайте посмотрим на это с точки зрения построения семейной ячейки на основе демократии. И пусть Namespace нам в этом поможет.
Нам не нравятся толстые, неуклюжие Контроллеры, которые, как слон в посудной лавке, по неосторожности могут раздавить все приложение.
Нам не нравятся также толстые Модели. Ну а кому они нравятся? Они должны быть достойны подиума!
Давайте попробуем с помощью Namespace, как с хорошей сватьей, создать гармоничную семью.
Сначала создадим каркас приложения. Как это ни банально, но пусть это будет блог.
Мы создали основну структуру, где:
- Blog — это хранилище нашего приложения;
- Views и Templates — хранилище представлений и шаблонов;
- Utility — хранилище общих библиотек;
- index.php — bootstrap скрипт;
- Post — вот здесь и должна состояться семейная идиллия Контроллера и Модели.
С index.php все просто:
<?php
use BlogBlog as Blog;
/*
* main application
*/
define ("APP_PATH", "/home/oleg/www/viper.dev/");
define ("VIEW_PATH", "/home/oleg/www/viper.dev/Blog/Views/");
spl_autoload_register(function ($class) {
require_once str_replace('\', '/', $class). '.php';
});
$blog = new Blog();
$blog->run();
/*
* end of index.php
*/
Определяем нужные пути и создаем автозагрузчик.
Автозагрузчик загружает необходимые классы, которые расположены в иерархии папок согласно пространству имен класса. Например, класс BlogPostServicesView будет разыскиваться в Blog/Post/Services.
А вот и первая встреча с Namespace.
При старте index.php мы создаем экземпляр приложения Blog, класс которого загружается из Blog/Blog.php.
Посмотрим на него.
<?php namespace Blog;
use BlogPostPost as Post;
class Blog
{
public $post;
public function __construct()
{
$this->post = new Post();
}
public function run()
{
$this->post->view->all();
}
}//end class Blog
При создании класса Blog мы внедряем в него класс Post с Namespace BlogPost и автозагрузчик загружает его из Blog/Post/Post.php.
Наверное, этот класс и можно назвать Контроллером,
<?php namespace BlogPost;
use BlogPostServicesView as View;
class Post
{
public $view;
public function __construct()
{
$this->view = new View();
}
}//end class Post
Сущность Post включает в себя:
— структуру самой записи данных — BlogPostEntitiesPostEntity.php
<?php namespace BlogPostEntities;
class PostEntity
{
public $id;
public $title;
public $body;
}//end class
— службы, обслуживающие запросы Контроллера — BlogPostServicesView.php (одна из служб, для примера)
<?php namespace BlogPostServices;
use BlogUtilityContemplate as Contemplate;
use BlogPostRepositoriesDb as DB;
class View
{
public $db;
public function __construct()
{
$this->db = new DB();
}//end __construct
public function all()
{
$posts = $this->db->survey();
Contemplate::compose(array(
'header' => 'header',
'main' => 'main',
'footer' => 'footer',
),
array(
'posts' => $posts,
'title' => 'Viper site',
));
}
}//end class PostView
— систему взаимодействия с базой данных — BlogPostRepositoriesDB.php — вот она, наша тонкая, изящная Модель,
Только подай-принеси, и ничего больше!
<?php namespace BlogPostRepositories;
use PDO as PDO;
class DB
{
private $dbh;
public function __construct()
{
$user = 'user';
$pass = 'parole';
try
{
$this->dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
PDO::ATTR_PERSISTENT => true ));
} catch (PDOException $e) {
echo "Error!: " . $e->getMessage() . "<br/>";
die();
}
}//end __construct
public function survey()
{
$query_view = $this->dbh->prepare('SELECT * from posts');
$query_view->execute();
return $query_view->fetchAll(PDO::FETCH_CLASS, "BlogPostEntitiesPostEntity");
}//end survey
}//end class Db
В результате нам удалось создать структуру приложения, где все компоненты хорошо связаны, при этом мы добились четкого разделения классов, где каждый класс выполняет свою задачу. Контроллер у нас тонкий и в то же время мощный. Модель под стать ему. Идеальная семья!
И все багодаря Namespace.
Не спорю, во многих случаях удобен фреймворк. Но, посмотрите, Namespace вам ничего не напоминает?
Четкое разделение на классы, строгая, и в тоже время гибкая, полностью подчиненная разработчику иерархия каталогов и классов.
Отсутствие порою такого весомого довеска в виде сотен файлов и классов в виде фреймворка.
Отсутствие прокрустова ложа правил взаимодействия классов и компонентов.
Статья навеяна размышлениями на эту тему Taylor Otwell, автора фреймворка Laravel, за что ему огромное спасибо.
Адрес исходников примера на GitHub: https://github.com/oleg578/PHPNamespaceModel
Автор: olegcorner