問題文
システムの1つの層でコントローラアドレスの知識を決定する必要があります。 これにより、コントローラーとそのアドレスをすばやく検索し、簡単にリファクタリングできます。
UPD:問題をより明確に示すために、コントローラーのアドレスがシステムのどこか、コントローラー、ビュー、場合によってはクライアントスクリプトでも設定され、このプロセスが制御不能になる場合、次の例を挙げることができます。アドレスを構築するためのパラメーターの十分性のチェックを実装します。 これは、アドレスのパラメーターがシステムの別のレイヤー(ビューやクライアントスクリプトなど)で設定されている場合に必要です。
解決策
すべてのアドレスは、コントローラーで定義する必要があります。 必要に応じて、ビューレイヤーまたはクライアントスクリプトで不足しているパラメーターを入力できます。
便利な作業のために、アシスタント-アドレスビルダーを定義できます。

アドレスビルダーのソースコードuse CUrlManager; class UrlBuilder { const PARAMETER_NAME_HASH = '#'; private $urlManager; private $route; private $params = array(); private $required = array(); public static function className() { return get_called_class(); } public function __construct(CUrlManager $urlManager) { $this->urlManager = $urlManager; } public function getUrlManager() { return $this->urlManager; } public function getRoute() { return $this->route; } public function setRoute($route) { $this->route = $route; return $this; } public function getParams() { return $this->params; } public function setParams($params) { $this->params = $params; return $this; } public function getParam($name) { if (!array_key_exists($name, $this->params)) { throw new Exception(sprintf('This param `%s` not exists')); } return $this->params[$name]; } public function setParam($name, $value) { $this->params[$name] = $value; return $this; } public function getHash() { return $this->getParam(self::PARAMETER_NAME_HASH); } public function setHash($value) { $this->setParam(self::PARAMETER_NAME_HASH, $value); return $this; } public function getRequired() { return $this->required; } public function setRequired($required) { $this->required = $required; return $this; } 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); } public function toArray() { return array( 'route' => $this->route, 'params' => $this->params, 'required' => $this->required, ); } 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(),
製品カタログの出力のプレゼンテーション(catalog.php)
$productUrlBuilder = $this->getParam('urls.product'); foreach ($this->getParam('products') as $product) { $productUrl = $productUrlBuilder ->copy() ->setParam('id', $product->id) ->getUrl(); print($productUrl);
ソリューションを使用するために、
https://github.com/petrgrishin/yii-url-builderおよび
https://packagist.org/packages/petrgrishin/yii-url-builderに投稿されたコード