経験の交換。 コントローラアドレスの知識を実装する場所

問題文



システムの1つの層でコントローラアドレスの知識を決定する必要があります。 これにより、コントローラーとそのアドレスをすばやく検索し、簡単にリファクタリングできます。



UPD:問題をより明確に示すために、コントローラーのアドレスがシステムのどこか、コントローラー、ビュー、場合によってはクライアントスクリプトでも設定され、このプロセスが制御不能になる場合、次の例を挙げることができます。



アドレスを構築するためのパラメーターの十分性のチェックを実装します。 これは、アドレスのパラメーターがシステムの別のレイヤー(ビューやクライアントスクリプトなど)で設定されている場合に必要です。



解決策



すべてのアドレスは、コントローラーで定義する必要があります。 必要に応じて、ビューレイヤーまたはクライアントスクリプトで不足しているパラメーターを入力できます。



便利な作業のために、アシスタント-アドレスビルダーを定義できます。







アドレスビルダーのソースコード
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('catalog', array( 'products' => Product::model()->findAll(), 'urls' => array( 'product' => $this->createUrlBuilder('site/product') ->setRequired(array('id')), //        , //   ,     ), )); } public function actionProduct($id) { return $this->render('product'); } }
      
      







製品カタログの出力のプレゼンテーション(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(), ), ));
      
      







ソリューションを使用するために、 https://github.com/petrgrishin/yii-url-builderおよびhttps://packagist.org/packages/petrgrishin/yii-url-builderに投稿されたコード



All Articles