
良い一日! 私たちがYii2で作成するプロジェクトのほとんどは、クールであり、大好きだからです。
ただし、改善すべき点が常にあります(この利点はYiiアーキテクチャによって妨げられません)。 Yii2のアプリケーションでのナビゲーションの処方を簡素化するソリューションを共有したいと思います。
問題
アプリケーションにページを追加するとき、(コントローラーとビューを作成した後に)次のことを規定する必要があります。
- ページタイトル(
$this->title = ...
); -
$this->params['breadcrumbs'][] = ...
($this->params['breadcrumbs'][] = ...
); - コントローラー内のアクションの権利(コントローラーの動作における
\yii\base\ActionFilter
); - このページへのリンクがあるすべてのメニューのアクセス制御で表示されます。
- ルールを
\yii\web\UrlManager::rules
素敵なリンクのルールに追加します。 - sitemap.xmlにページを追加します。

「別のページ」では太字ではありませんか? 最悪の部分は、これらすべての点を忘れずに念頭に置いておく必要があるということです。 そして、プロジェクトのナビゲーションが変化し始めた場合、何かを壊すのがさらに簡単になります。ほとんどの場合、パン粉を忘れてしまい、機能しなくなります。
解決策
アプリケーションのどのページも一般的なサイトマップに含める必要があると想定しました。 そのため、ページに関する包括的な情報(「問題」セクションの段落を参照)を使用してそのようなサイトマップを(マルチレベルツリーの形式で)作成すると、ページの追加はサイトマップで1か所で説明することになります! そこに見出し、リンクの権利と規則を登録できます。また、サイトマップを使用すると、パンくずやsitemap.xmlを簡単に取得できます。
したがって、コンポーネント[MegaMenu]()が取得されました。これはhabrasocietyを表しています。
設置
コンポーネントはComposerを介してインストールされます。
$ composer require ExtPoint/yii2-megamenu
次に、アプリケーション構成にコンポーネントを追加する必要があります。
アプリケーションコンポーネントとして:
'components' => [ 'megaMenu'=> [ 'class' => '\extpoint\megamenu\MegaMenu', 'items' => [ // You sitemap [ 'label' => '', 'url' => ['/site/index'], 'urlRule' => '/', ], ... ], ], ... ],
アプリケーションを起動する前にロードします(ルールをUrlManager
に追加するUrlManager
):
... 'bootstrap' => ['log', 'megamenu'], ...
API
APIコンポーネントはYii2に可能な限り近い場所で作成され、多くの場合、1対1で繰り返されます。
ページ記述形式(パラメーター\extpoint\megamenu\MegaMenu::items
)
ほとんどの\yii\bootstrap\Nav::items
、各アイテムは\yii\bootstrap\Nav::items
のナビゲーションジョブの形式に対応します。各アイテムには、 label
、 url
、 visible
、 active
、 encode
、 items
、 options
、 linkOptions
ます。 各アイテムは配列として定義され、そこから\extpoint\megamenu\MegaMenuItem
クラスのインスタンスが作成されます。
以下に、 \yii\bootstrap\Nav::items
ない新しく導入されたパラメーターをリストし\yii\bootstrap\Nav::items
。
-
urlRule
(文字列、配列、またはインスタンス\yii\rest\UrlRule
)。 この形式は、\yii\web\UrlManager::rules
対応してい\yii\web\UrlManager::rules
。 -
roles
(文字列または文字列の配列)。 形式は、\yii\filters\AccessRule::roles
と同じです。 サポートされている値は"?"
、"@"
および文字列としての役割。 -
order
(数値)各メニューレベルは、このパラメーターに従ってソートされます。 デフォルト値は0です。
コンポーネントメソッド\extpoint\megamenu\MegaMenu
-
setItems(array $items)
リストの最後にメニューアイテムを追加します。 -
addItems()
メニュー項目を追加します。 -
getItems()
メニュー項目を返します。 -
getActiveItem()
\Yii::$app->requestedRoute
に似ていますが、解析されたパラメーターを使用して、現在のルートを返します。 -
getMenu(array $item, $custom)
ネストされたメニュー項目(null
=ルート)を検索し、子を持つネストされたメニューを返します。 カスタムパラメータでは、配列として設定した場合、メニュー構成をオーバーライドできます。 数値で設定した場合、これは返されたメニューのネストを示します。 たとえば、\Yii::$app->megaMenu->getMenu(null, 2)
は、メニュー自体に多数のネストがある場合でも、2レベルのメニューを返します。 -
getTitle($url = null)
指定されたurl
(デフォルトは現在のページ)のアイテムを検索し、そのタイトルを返します -
getFullTitle($url = null, $separator = ' — ')
前のものと同様ですが、すべての親アイテム名も追加します -
getBreadcrumbs($url = null)
ウィジェットのパンくずを返します\yii\widgets\Breadcrumbs::links
-
getItem($item, &$parents = [])
URL /ルートでアイテムを検索します。親では、見つかったアイテムのすべての親のアイテムを追加します -
getItemUrl($item)
アイテムを検索し、そのURLを返します
アイテム検索ロジック
2つのアイテムを比較するためのロジックは、 \extpoint\megamenu\MegaMenu::isUrlEquals
実装されています。 2つの文字列を比較してリンクを比較します。
ルートはもう少し複雑に比較されます。最初に正規化され(モジュール、コントローラー、アクションを示す完全なルートが取得されます)、次にルートのみが比較されます。 ルートが一致する場合、パラメーターが比較されます。
パラメータがnullと異なる場合、そのキーと値の両方が比較されます。 値がnullとして指定されている場合、これは任意の値が存在できることを意味し、キーの存在のみが比較されます。
例:
- isUrlEquals( ' http://ya.ru '、 ' http://ya.ru ')// true
- isUrlEquals(['qq / ww / ee']、['aa / bb / cc'])// false
- isUrlEquals(['aa / bb / cc'、 'foo' => null]、['aa / bb / cc'])// false
- isUrlEquals(['aa / bb / cc'、 'foo' => null]、['aa / bb / cc'、 'foo' => null])// true
- isUrlEquals(['aa / bb / cc'、 'foo' => 'qwe']、['aa / bb / cc'、 'foo' => null])// true
- isUrlEquals(['aa / bb / cc'、 'foo' => 'qwe']、['aa / bb / cc'、 'foo' => '555'])// false
例
MegaMenuがインストールされた小さなWebアプリケーションの例は、テストフォルダーにあります。
さて、これは実際のプロジェクトでは機能しません!

ただし、あります。 MegaMenuはすでにいくつかの大規模プロジェクトで使用されています。 私たちのプロジェクトでは、機能を常にモジュールに分割し、MegaMenuはこれに抵抗しません。
このような内訳の例とより現実的な例は、 定型文で見ることができます。 ピースのメニューは、 モジュールまたはコントローラーから組み立てられます 。
藤堂
コンポーネントはまだ開発中です。近い将来に期待されるいくつかの機能を次に示します。
- コントローラーのアクセス制御(アクセス制御のためにサイトマップを分析する動作);
- sitemap.xmlのサイトマップを取得します。
- データベースへの変更を保存しながらサイトマップをカスタマイズするためのUI。
終了
最後まで読んだ/葉っぱをくれたすべての人に感謝します。 提案や要望はaffka@affka.ruに書いてください
GitHubにスターを付ける-ExtPoint / yii2-megamenu
みなさん、良い一日を!