私のサイトがSEOに対応できるように、ZendFrameworkでURLベースの翻訳を実装しようとしています。これは、デフォルトルートに加えて、以下のようなURLが必要であることを意味します。
zend.local/en/module
zend.local/en/controller
zend.local/en/module/controller
zend.local/en/controller/action
上記は私が今問題を抱えているものです。残りは大丈夫です。lang
メソッドにロケールと変換オブジェクトを設定できるように、パラメーターをフェッチするコントローラープラグインを追加しましたpreDispatch
。これが私のルートの一部です(.iniファイルに保存されています):
; Language + module
; Language + controller
resources.router.routes.lang1.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.lang1.route = "(^[a-zA-Z]{2})/(\w+$)"
resources.router.routes.lang1.defaults.controller = index
resources.router.routes.lang1.defaults.action = index
resources.router.routes.lang1.map.1 = "lang"
resources.router.routes.lang1.map.2 = "module"
; Language + module + controller
; Language + controller + action
resources.router.routes.lang2.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.lang2.route = "(^[a-zA-Z]{2})/(\w+)/(\w+$)"
resources.router.routes.lang2.defaults.module = default
resources.router.routes.lang2.defaults.action = index
resources.router.routes.lang2.map.1 = "lang"
resources.router.routes.lang2.map.2 = "controller"
resources.router.routes.lang2.map.3 = "action"
コメントが示すように、いくつかのURL構造が同じルートに一致するため、アプリケーションがフォーマットを誤って解釈します。たとえば、次の2つのURLがlang1
ルートによって照合されます。
zend.local/en/mymodule
zend.local/en/mycontroller
最初のURLでは、「mymodule」がモジュール名として使用されていますが、これは正しいです。ただし、2番目のURLでは、モジュール名として「mycontroller」が使用されていますが、これは私が望むものではありません。ここでは、「default」モジュールと「mycontroller」をコントローラーとして使用する必要があります。lang2
同じことが前のルートにも当てはまります。/en/module
そのため、URLが構造体であるか。であるかを区別する方法がわかりません/en/controller
。
これを修正するために、コントローラープラグインで以下のコードを試してみました。
// Get module names as array
$dirs = Zend_Controller_Front::getInstance()->getControllerDirectory();
$modules = array_keys($dirs);
// Module variable contains a module that does not exist
if (!in_array($request->getModuleName(), $modules)) {
// Try to use it as controller name instead
$request->setControllerName($request->getModuleName());
$request->setModuleName('default');
}
これは私がテストしたシナリオでは正常に機能しますが、lang2
ルートを機能させるために同様のことを行う必要があります(これには、コントローラーのリストを取得するためにディレクトリをスキャンすることが含まれる可能性があります)。これは貧弱な解決策のように思われるので、可能であれば、ルートのみ(またはそれほど「ハッキー」ではない単純なコード)でこれらすべてを達成したいと思います。たとえば、必要なときに毎回ルートを作成することもできます/en/controller
が、それは妥協案であり、行きたくありません。したがって、誰かがこれを解決する方法を知っているか、同じことを達成するための別のアプローチを知っているなら、私はすべての耳です!