1

私の現在のルーター/FrontControllerは、URLを次の形式で分析するようにセットアップされています。

http://localhost/controller/method/arg1/arg2/etc...

ただし、次のように入力できるように、特定のリクエストを IndexController にデフォルト設定する方法がわかりません。

http://localhost/contact
or
http://localhost/about/portfolio

それ以外の:

http://localhost/index/contact
or
http://localhost/index/about/portfolio

これはどのように達成されますか?

<?php

namespace framework;

class FrontController {
    const DEFAULT_CONTROLLER = 'framework\controllers\IndexController';
    const DEFAULT_METHOD     = 'index';

    public $controller       = self::DEFAULT_CONTROLLER;
    public $method           = self::DEFAULT_METHOD;
    public $params           = array();
    public $model;
    public $view;

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

    // route request to the appropriate controller
    public function route() {
        // get request path
        $basePath = trim(substr(PUBLIC_PATH, strlen($_SERVER['DOCUMENT_ROOT'])), '/') . '/';
        $path = trim(parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH), '/');
        if($basePath != '/' && strpos($path, $basePath) === 0) {
            $path = substr($path, strlen($basePath));
        }

        // determine what action to take
        @list($controller, $method, $params) = explode('/', $path, 3);
        if(isset($controller, $method)) {
            $obj = __NAMESPACE__ . '\\controllers\\' . ucfirst(strtolower($controller)) . 'Controller';
            $interface = __NAMESPACE__ . '\\controllers\\' . 'InterfaceController';
            // make sure a properly implemented controller and corresponding method exists
            if(class_exists($obj) && method_exists($obj, $method) && in_array($interface, class_implements($obj))) {
                $this->controller = $obj;
                $this->method = $method;

                if(isset($params)) {
                    $this->params = explode('/', $params);
                }
            }
        }
        // make sure we have the appropriate number of arguments
        $args = new \ReflectionMethod($this->controller, $this->method);
        $totalArgs = count($this->params);
        if($totalArgs >= $args->getNumberOfRequiredParameters() && $totalArgs <= $args->getNumberOfParameters()) {
            call_user_func_array(array(new $this->controller, $this->method), $this->params);
        } else {
            $this->view->load('404');
        }
    }
}
4

4 に答える 4

3

あなたのコードスニペットに基づいて、私はこのようにします(疑似phpコード):

$handler = get_controller($controller);
if(!$handler && ($alias = lookup_alias($path))) {
    list($handler, $method) = $alias;
}
if(!$handler) error_404();

function lookup_alias($path) {
    foreach(ALL_CONTROLLERS as $controller) {
        if(($alias = $controller->get_alias($path))) {
            return $alias;
        }
    }
    return null;
}

したがって、基本的に、特定の場所を処理するコントローラーがない場合は、指定されたパスをエイリアスとして処理するようにコントローラーが構成されているかどうかを確認し、ある場合は、そのコントローラーとマップ先のメソッドを返します。

于 2013-01-22T20:47:53.553 に答える
3

URL は、次の 2 つの方法のいずれかで使用できます。

ルーティングで定義されている方法でコントローラーを確立します

example.com/contact => デフォルトまたはインデックス アクションを備えた「連絡先」コントローラーを用意する

example.com/about/portfolio => 「portfolio」アクションを含む「about」コントローラーを用意する

現在利用可能なルーティングでは、URL は "/controller/method" のように扱われるため、他に方法はありません。

複数の URL を 1 つのコントローラーで処理できるように、動的ルーティングを確立します。

どの URL が有効で、どの URL が汎用コントローラーにリダイレクトされ、どの URL がリダイレクトされるべきでないかを知ることができないため、明らかにこれには少し設定が必要です。これは何らかの形で書き換えまたはリダイレクト ソリューションの代わりとなりますが、PHP レベルで処理されるため、変更の処理が容易になる可能性があります (一部の Web サーバー構成では、パフォーマンス上の理由から .htaccess が提供されず、一般的にはより手間がかかります)。これらを作成します)。

構成入力は次のとおりです。

  1. 処理したいURLと
  2. URL を渡すコントローラーとそのアクション。

次のような配列構造になります。

$specialRoutes = array(
    "/contact" => "IndexController::indexAction",
    "/about/portfolio" => "IndexController::indexAction"
);

欠けているのは、このアクションがパラメーターとして渡された現在の URL を取得する必要があること、またはパス部分が URL スキーマ内の指定されたパラメーターになることです。

全体として、このアプローチはコーディングがはるかに困難です。アイデアを得るために、Symfony や Zend Framework などの一般的な MVC フレームワークのルーティングを調べてみてください。高度に構成可能なルーティングを提供するため、ルーティングは複数のクラスで行われます。メイン ルーターは構成のみを読み取り、一致が検出された場合は、任意の URL のルーティングを構成済みルーターに渡します。

于 2013-01-22T21:34:36.127 に答える
1

次の動的 htaccess 書き換えルールを試してください。

RewriteRule ^(.+)/?$ /index/$1 [QSA]

上記のルールのQSAフラグを使用すると、次のように、必要に応じてクエリ文字列を最後に追加することもできます。

http://localhost/contact?arg1=1&arg2=2

編集:このルールは、次のようなケースも処理し/about/portfolioます。

RewriteRule ^(.+)/?(.+)?$ /index/$1 [QSA]
于 2013-01-22T20:36:52.473 に答える
1

これらの例外については、Web サーバーで書き換えを作成できます。例えば:

RewriteRule ^contact$ /index/contact
RewriteRule ^about/portfolio$ /about/portfolio

これにより、通常の構造にマップする単純化された URL を持つことができます。

/index に何を書き換えるべきかを正確に定義できる場合は、動的ルールを作成できます。例えば:

RewriteRule ^([a-z]+)$ /index/$1
于 2013-01-22T20:31:53.587 に答える