3

カスタムフレームワークでコントローラーを切り替える良い方法を理解し、理解しようとしています。次の例は、私が現在考えていることであり、デモンストレーションの目的で簡略化されていますが、より良いアプローチがあれば、専門家のアドバイスをいただければ幸いです。

class BaseController() {
    function __construct() {
        $this->model = new ModelFactory();
        $this->view = new View();

        if(isset($_SERVER['QUERY_STRING'])) {
            list($controller, $action) = explode('=', $_SERVER['QUERY_STRING']);
            self::process($controller);
        }
    }

    public function process($controller) {
        switch($controller) {
            case 'user':
                $user = new UserController($action);
            break;

            case 'forum':
                $forum = new ForumController($action);
            break;

            default:
                // use base controller
                switch($action) {
                    case 'contact':
                        $this->view->load($action);
                    break;
                }
        }
    }
}

// inside UserController.php
switch($action) {
    case 'register':
    break;

    case 'login':
    break;
}

// inside ForumController.php
switch($action) {
    case 'new_thread':
    break;

    case 'edit_post':
    break;
}
4

2 に答える 2

3

これは本当に部分的な答えであり、うまくいけばいくつかの良い指針を与えるでしょう。より良い答えを持った人が来ると確信しています。

  1. あなたBaseControllerの例では、おそらく名前が間違っています。そこにあるものは、他のすべてのコントローラークラスが派生する可能性のあるベースコントローラーよりも、コントローラーファクトリーのように見えます。これは「ルーティング」クラスのように見えるので、そのジョブに適した名前を付けることを検討する必要があります。

  2. フレームワークユーザーがカスタムアクションを使用してカスタムコントローラーを作成するようにする場合:

    a)少なくとも、すべてのコントローラークラスが実装するためのインターフェイスを作成する必要があります。IControllerそれかそのようなものと呼んでください。これは次のステップで使用されます。

    b)文字列をクラス名として使用してオブジェクトを作成することを決心する必要があります。$controllerObject = new $controller();「ルート」ハンドラークラス内のIE 。その理由は、実行するコントローラーとアクションの名前がリクエストURLから直接取得されるためです。この部分をエイリアシングする方法はありますが、それはまったく別の質問です。クライアントから渡されたこれらの「コントローラー」クラス名を検証および/またはホワイトリストに登録することを忘れないでください。検証するには:PHP関数class_exists($controller)を使用し、場合は、コントローラークラスがPHPの組み込みを使用してtrue実装されていることを確認します。その場合にのみ実際にコントローラーオブジェクトを作成する必要があります。IControllerclass_implements($controller)$controllerObject = new $controller();

    「Route」processメソッドは、次のようになります(これは、非常に単純化された例であることに注意してください)。

    public function process($controller, $action) {
        if (!class_exists($controller)) {
            throw new Exception('Controller class does not exist.');
        }
        if (!in_array("IController", class_implements($controller))) {
            throw new Exception('Route is not a valid controller.');
        }
        if (!method_exists($controller, $action)) {
            throw new Exception('No such action for requested controller.');
        }
        $ctrl = new $controller();
        return $ctrl->$action();
    }
    

    $actionc)上記のデザインパターンを使用してクライアントに直接実行させたくないメソッド(つまり、任意の値で名前を付けたもの)をコントローラーに宣言させないでください。うまくいけば、フレームワークユーザーもこれを理解しています。フレームワークユーザーに気付かせるために、これが内部でどのように機能するかを適切に文書化してください。

もちろんそれ以上の方法がありますが、それはあなた次第です-フレームワークデザイナー。また、アクションには、使用する「ビュー」の最終決定権が必要です。ただし、アクションで使用するビューが明示的に記述されていない場合は、デフォルトを設定する方法があります。しかし、繰り返しになりますが、それは別の質問になります。

于 2013-01-13T01:20:30.423 に答える
0

あなたは本当にMVCが実際に何であるかを読むことから始めるべきです。FowlerのGUIアーキテクチャから始めることをお勧めします。一つ確かなことがあるからです-あなたが持っているものはそうではありません。

あなたが名前を付けたものBaseControllerは、実際にはルーティングを扱っているようです。これはユーザーのリクエストURLであり、そのURLから取得したものに基づいたファイルが含まれています。これはOOPでも手続き型プログラミングでもありません。あなたが持っているものは非構造化プログラミングとして知られています。

この狂気の代わりに、アプリケーションのルーティングメカニズムを実装する別のクラスを作成する必要があります。そして、上記の構造で抽出したデータに基づいて、特定のコントローラーインスタンスを開始し、そのインスタンスでメソッドを呼び出す必要があります。

何かのようなもの:

$request = new Request('QUERY_STRING');

$router = new Router;
$router->import('/path/to/routing/config.file');
$router->route( $request );

$klass = $request->getParameter('controller');

if (class_exists( $controller ))
{
    $command = $request->getMethod() . $request->getParameter('action');
} 
else 
{
    $klass = 'Error';
    $command = 'getMessage';
}

$controller = new $klass;
$controller->{$command}( $request );

もちろん、これは非常に単純化されたバージョンです。MVCパターンは、大規模なプロジェクトに何らかの秩序をもたらすことを目的としています。単純なブログ/名刺のWebサイトのようなものを作成するためにそれを使用する場合、それはやり過ぎのように見えます(ページが成長しないと仮定すると)。

PSあなたはあなたの研究に役立つ次のリンクを見つけるかもしれません:thisthisthisそしてthis

于 2013-01-14T15:44:00.010 に答える