2

管理者ユーザーがバックエンドでいくつかの種類のページを選択し、完全にカスタマイズされたURLを使用してメニューに追加できる、優れたコハナフレームワークでCMSを作成しています。

Example of custom URL : "mmmm/about" or "aaa/bbb/release"

各URLに表示される内容を格納するデータベーステーブルがあります。

Example : 
URL : mmm/about     Pagekind : Content page ; (Page) Id : 7
URL : aaa/release   Pagekind : News         ; (News) Id : 1

各ページの種類には独自のコントローラーがあります(したがって、よりクリーンで、管理しやすく、新しいページの種類を追加しやすくなります):

Examples :
>>> In /application/classes/Controller/Pages :
class Controller_Pages() extends Controller_Template { 
    public function action_index(){
        ...
    }
}
>>> In /application/classes/Controller/News :
class Controller_News() extends Controller_Template { 
    public function action_index(){
        ...
    }
}

メニューコントローラーにすべてを送信するこのようなルートがあります:

Route::set( 'menu_path', '(<menupath>)', array('menupath' => '.*?') )
->defaults(
    array(
        'controller' => 'menu',
        'action' => 'dispatch'
    )
);

私のメニューコントローラーはディスパッチを行う必要があります:

>>> In /application/classes/Controller/Menu :
class Controller_Menu() extends Controller_Template 
{ 
    public function action_dispatch()
    {

        // Get the path :
        $menupath = $this->request->param('menupath');

        // Get page info
        $obj = ORM::factory('tablemenu')->where('URL','=',$menupath)->find();

        // Regarding to page kind, call the appropriate controller
        switch ($obj->Pagekind)
        {
           case 'Content page' : 
              // Call controller Page with $obj->Id as page id
              // ???????? 
              // ???????? 
              break;

           case 'News' : 
              // Call controller News with $obj->Id as news id
              // ???????? 
              // ???????? 
              break;

        }

    }
}

だから私はコールコントローラーの部分で立ち往生しています。私の質問は:
-コントローラー内でコントローラーを呼び出す方法はありますか?(SEOのリダイレクトなし)
-はいの場合、それはきれいですか?信頼性のある ?
-そうする別の方法はありますか?Routeクラスを上書きしたいですか?

ありがとう

4

1 に答える 1

6

ここには2つの選択肢があり、どちらもクリーンで信頼できると考えられます。

1.内部リクエスト

コハナは内部呼び出しを行うことができるので、探しているものを達成するためにリダイレクトを行う必要はありません。

class Controller_Menu() extends Controller_Template 
{ 
    public function action_dispatch()
    {
        // Get the path :
        $menupath = $this->request->param('menupath');

        // Get page info
        $obj = ORM::factory('tablemenu')->where('URL','=',$menupath)->find();

        // Regarding to page kind, call the appropriate controller
        switch ($obj->Pagekind)
        {
            case 'Content page' : 
                $url = 'pages/action/' . $obj->Id;
                break;

            case 'News' : 
                $url = 'news/action/' . $obj->Id;
                break;
        }

        // Override current response
        $this->response = Request::factory($url)->execute();
    }
}

これは、これがどのように機能するかを示すための簡単な試みであることに注意してください(そして、それ自体ではおそらく機能しません)。URLの一部に注意してくださいaction。これが機能するためには、ある時点でそれを定義する必要があります。ただし、ここで内部的に行っているリクエストに一致するルートを実際に用意することが重要です。また、これらの内部リクエストが「menu_path」ルートを経由しないようにする方法を考え出す必要があります。しかし、あなたはまだ何も試していませんので、私はあなたにそれで遊んでもらい、あなた自身でそれを理解するならば。:)

2.ルートフィルター(推奨)

ルートフィルターはこのバージョンからのみ使用できるため、ここではプロジェクトにKohana3.3.xを使用していると想定しています。

すべてのリクエストをメニューコントローラにルーティングする代わりに、ルートフィルタ内でリクエストを処理できます。

その場合、ルートは次のようになります。

Route::set('menu_path', '(<menupath>)',
    array(
        'menupath' => '.*?')
    )
    ->filter(function($route, $params, $request)
    {
        $menupath = $params['menupath'];

        // Get page info
        $obj = ORM::factory('tablemenu')->where('URL','=',$menupath)->find();

        if ($obj->loaded())
        {
            // Regarding to page kind, call the appropriate controller
            switch ($obj->Pagekind)
            {
                case 'Content page' : 
                    $params['controller'] = 'Page';
                    $params['id'] = $obj->Id;
                    break;

                case 'News' : 
                    $params['controller'] = 'News';
                    $params['id'] = $obj->Id;
                    break;
            }

            return $params;
        }

        return FALSE;
    })
    ->defaults(array(
        'action'    => 'index',
    ));

ページが見つからない場合に404​​エラーを返したいので、ここでデフォルトのコントローラーを定義する必要はないことに注意してください。ただし、例のどこにも定義されていないので、デフォルトのアクションを定義したいと思います。

Pagekindコントローラ名と一致する値の使用を検討することをお勧めしcaseます。そうすれば、種類ごとにを必要とせず、次の方法で簡単に実行できます。

if ($obj->loaded())
{
    $params['controller'] = $obj->Pagekind;
    $params['id'] = $obj->Id;

    return $params;
}

ルートフィルターのこのタイプの複雑さ(数行以上)では、別のコールバック関数として(以下のコメントで@Daanによって提案されているように)、外部に保持することもお勧めします。例:

Route::set('menu_path', '(<menupath>)',
    array(
        'menupath' => '.*?')
    )
    ->filter('MyRouteHelper::myfilter')
    ->defaults(array(
        'action'    => 'index',
    ));

お役に立てれば :)

于 2013-03-26T14:03:07.877 に答える