2

フロントコントローラーデザインでMVCを掘り下げようとしています。

index.php のように、1 行を使用してアプリケーション全体を呼び出したいと考えています。

require_once(myclass.php);
$output = new myClass();

require_once 行を削除したいのですが、これを含めずにクラスをロードする方法がわかりません。

とにかく、私の主な質問は、1つのフロントエンドクラスを使用して、さまざまなコントローラー、モデル、ビューなどをロードする方法です。これまでのところ、私は思いついた:

class myClass
{
    private $name;
    public $root = $_SERVER['DOCUMENT_ROOT'];
    private $route = array("Controller" => "", "Model" => "", "View" => "", "Paremeters" => "");
    function __construct() 
    {   $uri = explode("/",$_SERVER['REQUEST_URI']);
        if(isset($uri[2])) {$this->route['Controller'] = $uri[2];}
        if(isset($uri[3])) {$this->route['Model'] = $uri[3];}
        if(isset($uri[4])) {$this->route['View'] = $uri[4];}
        if(isset($this->route['Controller'])) 
        {
            include($this->root."/".$this->route['Controller'].".php");
        }
    }

}

しかし、それは少し複雑で、やり過ぎのようです。また、新しいクラスを __construct に含めたら、どのようにロードすればよいですか?

知識不足で申し訳ありませんが、これを何度もグーグルで検索しましたが、この問題に関する知識が広がらないように見える同じページが引き続き表示されます.

4

3 に答える 3

5

URL が確実にhttp://domain.com/[controller]/[action]/ parametersになる場合、フロント コントローラーは次のようになります。

<?php
class Application
{
    public function __construct()
    {
        $this->setupAutoloader();
        $this->route();
    }

    private function setupAutoloader()
    {
        // do your autoloading here
    }

    private function route()
    {
        $request = explode('/', trim($_SERVER['REQUEST_URI'], '/'));

        $controller = isset($request[0]) ? ucwords(array_shift($request)) . 'Controller' : 'HomeController';
        $action = isset($request[0]) ? array_shift($request) : 'index';
        $parameters = $request;

        $response = call_user_func_array(array($controller, $action), $parameters);
    }
}

ここから、オートローダの実装を追加し、応答で必要なことを行い、次のようにindex.phpから呼び出すことができます。

<?php
require 'path/to/Application.php';

$application = new Application();

残念ながら、最初のファイルがファイル システムの別の場所に保存されている場合は常に最初のファイルを含める必要がありますが、上記のようにここからライブラリ、コントローラー、モデルなどの他のクラスをオートロードできます。

于 2012-11-19T14:30:54.463 に答える
3

これらの 2 つの長く有益な以前の回答で、誰もあなたの質問に最も簡単な方法で実際に答えようとしなかったことに驚いています。

あなたはその__autoload()機能が欲しいです。コードのどこかで定義する必要がありますが、単純にグローバル ヘッダー ファイルに追加することができ、すべてのクラス定義に対して明示的にインクルードを記述する必要はありません。

/* auto load model classes */
function __autoload($class_name) {
        $filename = 'class.' . strtolower($class_name) . '.php';
        $file = __SITE_PATH . '/_model/' . $filename;
        if( file_exists($file) == false ) {
                return false;
        }
        require($file);
}
于 2012-11-19T16:07:05.983 に答える
1

手動でインクルードせずにクラスをロードするには、アプリケーションで必要なときにクラスを自動的にロードできるようにするspl_autoload_registerを確認する必要があります。

他の質問に関しては、まあ、それはすべてあなたのデザイン次第です。共通の「コントローラー」と「アクション」をロードする場合は、ルーティング可能なフォルダー (コントローラーのみが存在できるフォルダーを意味します) を作成し、すべてのコントローラー クラスを配置してから、ルーティング可能なアクション スペース (ルーティング可能なグループ) を作成する必要があります。コントローラ クラス内のメソッドは、通常、アクション メソッドの前に が付くという規則を定義することによって行われaction_ます)。それが完了したら、次のようにコントローラーを作成するだけです。

class Blog {
    public function action_posts() { ... };
}

URL/blog/posts/がこれを呼び出すように管理します。(すでに得意であることが証明されているのと同じ URI 操作が必要なだけです)。(オートローダは、すべてのコントローラ クラスをロードする必要なく、実際のクラス ファイルのインクルードを単独で処理する必要があることに注意してください)。コントローラーの名前とアクションを取得したら、次の行に何かが必要です。

if (class_exists($controller)) {
    $app = new $controller;
    if (method_exists($app, $action)) {
        $app->$action(); // also take a look at call_user_func and call_user_func_array
    }
}

パラメータを許可することもできますが、この種の結果を許可するには、非常に困難です。

class Blog {
    public function action_post($id) { ... };
}

/blog/post/14/たとえば、によって呼び出されます。

URI を扱うときは、不適切な入力がある可能性があり、それらを処理する必要があることも覚えておいてください。ただし、正しいルーティング スペースを作成していれば、すでに半分は完了しています。

最後に、インスピレーションを得たい場合やその他の目的がある場合は、CodeIgniter (最も簡単に習得できるフレームワークの 1 つ) またはその他のフレームワークを参照してください。

それが役に立ったことを願っています。

于 2012-11-19T14:22:00.750 に答える