Обмен опытом. Где реализовать знание об адресах контроллера?

от автора

Постановка проблемы

Необходимо определить знание об адресе контроллера в одном слое системы. Это позволит быстро осуществлять поиск и безболезненно производить рефакторинг контроллеров и их адресов.

Реализовать проверку достаточности параметров для построения адреса. Это необходимо если параметры для адреса задаются в другом слое системы, например в представлении или клиентском скрипте.

Решение

Все адреса должны быть определены в контроллерах. При необходимости недостающие параметры можно заполнить в слое представления или клиентского скрипта.

Для удобной работы можно определить помощника — построитель адресов.

Исходный код построителя адреса

use CUrlManager;  class UrlBuilder {     const PARAMETER_NAME_HASH = '#';      /** @var CUrlManager */     private $urlManager;     /** @var string */     private $route;     /** @var array */     private $params = array();     /** @var array */     private $required = array();      public static function className() {         return get_called_class();     }      /**      * @param CUrlManager $urlManager      */     public function __construct(CUrlManager $urlManager) {         $this->urlManager = $urlManager;     }      /**      * @return CUrlManager      */     public function getUrlManager() {         return $this->urlManager;     }      /**      * @return string      */     public function getRoute() {         return $this->route;     }      /**      * @param string $route      * @return $this      */     public function setRoute($route) {         $this->route = $route;         return $this;     }      /**      * @return array      */     public function getParams() {         return $this->params;     }      /**      * @param array $params      * @return $this      */     public function setParams($params) {         $this->params = $params;         return $this;     }      /**      * @param string $name      * @return mixed      * @throws Exception      */     public function getParam($name) {         if (!array_key_exists($name, $this->params)) {             throw new Exception(sprintf('This param `%s` not exists'));         }         return $this->params[$name];     }      /**      * @param string $name      * @param mixed $value      * @return $this      */     public function setParam($name, $value) {         $this->params[$name] = $value;         return $this;     }      /**      * @return string      * @throws Exception      */     public function getHash() {         return $this->getParam(self::PARAMETER_NAME_HASH);     }      /**      * @param string $value      * @return $this      */     public function setHash($value) {         $this->setParam(self::PARAMETER_NAME_HASH, $value);         return $this;     }      /**      * @return array      */     public function getRequired() {         return $this->required;     }      /**      * @param array $required      * @return $this      */     public function setRequired($required) {         $this->required = $required;         return $this;     }      /**      * @throws Exception      * @return string      */     public function getUrl() {         if ($this->hasRequiredParams()) {             throw new Exception(sprintf('Required params `%s` not exists', implode(', ', $this->requiredParams())));         }         return $this->getUrlManager()->createUrl($this->route, $this->params);     }      /**      * @return array      */     public function toArray() {         return array(             'route' => $this->route,             'params' => $this->params,             'required' => $this->required,         );     }      /**      * @return UrlBuilder      */     public function copy() {         return clone $this;     }      protected function hasRequiredParams() {         return (boolean)$this->requiredParams();     }      protected function requiredParams() {         return array_diff($this->required, array_keys(array_filter($this->params)));     } } 

Примеры использования

Определение знания об адресе в контроллере

Базовый абстрактный контроллер. Реализация метода создания обектов построителя адреса

class BaseController extends \CController {      public function createUrlBuilder($route, $params = array()) {         $urlBuilder = new UrlBuilder($this->getUrlManager());         $urlBuilder             ->setRoute($route)             ->setParams($params);         return $urlBuilder;     }      public function getUrlManager() {         $urlManager = $this->getApp()->getUrlManager();         return $urlManager;     }      public function getApp() {         return \Yii::app();     } } 

Конкретный контроллер. Использование построителя адреса

class SiteController extends BaseController {      public function actionIndex() {         return $this->render('index', array(             'urls' => array(                 'catalog' => $this->createUrlBuilder('site/catalog')                     ->getUrl(),                 // передана готовая строка адреса ?r=site/catalog             ),         ));     }      public function actionCatalog() {         return $this->render('about', array(             'products' => Product::model()->findAll(),             'urls' => array(                 'product' => $this->createUrlBuilder('site/product')                     ->setRequired(array('id')),                 // передан объект построителя с необходимыми знаниями,                 // требуемые параметры заполняются в представлении             ),         ));     }      public function actionProduct($id) {         return $this->render('product');     } } 

Представление вывода каталога товаров

/** @var UrlBuilder $productUrlBuilder */ $productUrlBuilder = $this->getParam('urls.product');  foreach ($this->getParam('products') as $product) {     $productUrl = $productUrlBuilder         ->copy()         ->setParam('id', $product->id)         ->getUrl();      print($productUrl);     // строка адреса ?r=site/product&id=1 }  // или передать параметры построителя адреса в клиентский скрипт $this->setJsParams(array(     'urls' => array(         'product' => $productUrlBuilder->toArray(),     ), )); 

Для удобства использования решения, код выложил на https://github.com/petrgrishin/yii-url-builder и https://packagist.org/packages/petrgrishin/yii-url-builder

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


Комментарии

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

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