📜 ⬆️ ⬇️

Experience exchange. Where to realize the knowledge of the addresses of the controller?

Formulation of the problem


It is necessary to determine the knowledge of the controller address in one layer of the system. This allows you to quickly search and painlessly refactor controllers and their addresses.

UPD: In order to show the problem more clearly, we can give the following example, when the addresses of the controllers are set in the system anywhere, in controllers, in views, sometimes even in client scripts, and this process becomes uncontrollable.

Implement parameter sufficiency checking for building an address. This is necessary if the parameters for the address are specified in another layer of the system, for example, in a view or client script.
')

Decision


All addresses must be defined in controllers. If necessary, the missing parameters can be filled in the layer of the presentation or client script.

For convenient work, you can define an assistant - address builder.



Address Builder Source Code
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))); } } 



Examples of using


Definition of knowledge about the address in the controller

Basic abstract controller. Implementing the method of creating an address builder object
 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(); } } 




Specific controller. Using the Address Builder
 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('catalog', array( 'products' => Product::model()->findAll(), 'urls' => array( 'product' => $this->createUrlBuilder('site/product') ->setRequired(array('id')), //        , //   ,     ), )); } public function actionProduct($id) { return $this->render('product'); } } 


Presentation of the catalog output (catalog.php)
 /** @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(), ), )); 


For ease of use of the solution, the code is posted on https://github.com/petrgrishin/yii-url-builder and https://packagist.org/packages/petrgrishin/yii-url-builder

Source: https://habr.com/ru/post/226237/


All Articles