PHP NameSpace — как же все-таки его готовить?

от автора

PHP, начиная с версии 5.3, подарил нам пространство имен. С тех пор идет где-то вялое, а где-то бурное обсуждение, как же это пространство имен использовать?
Некоторые фреймворки, такие как Symphony, Laravel, и, конечно же Zend взяли эту технологию на вооружение.
Все это более или менее вписалось в схему MVC. Осталась одна, наверное вечная, дискуссия, какой же должна быть главная брачная пара приложения — Модель и Контроллер?
Одни нам говорят, что Модель должна быть дородной и толстой и при ней стройный и тонкий Контроллер. Одним словом — матриархат.
Другие, наоборот, считают, что Контроллер должен всем управлять и повелевать, поэтому он получается основательный, упитанный. И при нем худенькая, стройненькая Модель, задача которой сводится к подай-принеси. Такой вот патриархат.
Так что же лучше в схеме MVC? Патриархат или матриархат?
Давайте посмотрим на это с точки зрения построения семейной ячейки на основе демократии. И пусть Namespace нам в этом поможет.

Нам не нравятся толстые, неуклюжие Контроллеры, которые, как слон в посудной лавке, по неосторожности могут раздавить все приложение.
Нам не нравятся также толстые Модели. Ну а кому они нравятся? Они должны быть достойны подиума!
Давайте попробуем с помощью Namespace, как с хорошей сватьей, создать гармоничную семью.

Сначала создадим каркас приложения. Как это ни банально, но пусть это будет блог.

image

Мы создали основну структуру, где:

  • Blog — это хранилище нашего приложения;
  • Views и Templates — хранилище представлений и шаблонов;
  • Utility — хранилище общих библиотек;
  • index.php — bootstrap скрипт;
  • Post — вот здесь и должна состояться семейная идиллия Контроллера и Модели.

С index.php все просто:

<?php use Blog\Blog 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  */ 

Определяем нужные пути и создаем автозагрузчик.
Автозагрузчик загружает необходимые классы, которые расположены в иерархии папок согласно пространству имен класса. Например, класс Blog\Post\Services\View будет разыскиваться в Blog/Post/Services.
А вот и первая встреча с Namespace.
При старте index.php мы создаем экземпляр приложения Blog, класс которого загружается из Blog/Blog.php.
Посмотрим на него.

<?php namespace Blog; use Blog\Post\Post 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 Blog\Post и автозагрузчик загружает его из Blog/Post/Post.php.
Наверное, этот класс и можно назвать Контроллером,

<?php namespace Blog\Post; use Blog\Post\Services\View as View;  class Post   {      public $view;       public function __construct()       {          $this->view = new View();       } }//end class Post 

Сущность Post включает в себя:
— структуру самой записи данных — Blog\Post\Entities\PostEntity.php

<?php namespace Blog\Post\Entities;  class PostEntity {      public $id;      public $title;      public $body; }//end class 

— службы, обслуживающие запросы Контроллера — Blog\Post\Services\View.php (одна из служб, для примера)

<?php namespace Blog\Post\Services; use Blog\Utility\Contemplate as Contemplate; use Blog\Post\Repositories\Db 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 

— систему взаимодействия с базой данных — Blog\Post\Repositories\DB.php — вот она, наша тонкая, изящная Модель,
Только подай-принеси, и ничего больше!

<?php namespace Blog\Post\Repositories; 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, "Blog\Post\Entities\PostEntity");   }//end survey  }//end class Db 

В результате нам удалось создать структуру приложения, где все компоненты хорошо связаны, при этом мы добились четкого разделения классов, где каждый класс выполняет свою задачу. Контроллер у нас тонкий и в то же время мощный. Модель под стать ему. Идеальная семья!
И все багодаря Namespace.

Не спорю, во многих случаях удобен фреймворк. Но, посмотрите, Namespace вам ничего не напоминает?
Четкое разделение на классы, строгая, и в тоже время гибкая, полностью подчиненная разработчику иерархия каталогов и классов.
Отсутствие порою такого весомого довеска в виде сотен файлов и классов в виде фреймворка.
Отсутствие прокрустова ложа правил взаимодействия классов и компонентов.

Статья навеяна размышлениями на эту тему Taylor Otwell, автора фреймворка Laravel, за что ему огромное спасибо.
Адрес исходников примера на GitHub: https://github.com/oleg578/PHPNamespaceModel

ссылка на оригинал статьи http://habrahabr.ru/post/178859/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *