2012-02-23 9 views
2

PHPで自分のMVCフレームワークを作成しようとしていますが、現在はコントローラの動作を実装するのに問題があります。PHP MVCフレームワークでコントローラアクションを実装するにはどうすればよいですか?

問題は、actionView($ id)などの1つまたは複数の引数を持つコントローラもあれば、actionCreate()などの引数を持たないコントローラです。これらをどうやって扱うのですか?例えば

:私は呼ぶだろう私のコントローラで

$action; //contains my action 
$params; //array containing my arguments 

...

$this->$action(); //for no parameters 
$this->$action($params[0]); //for one parameter 
$this->$action($params[0], $params[1]); //for two parameters 
... and so on 

このようなあらゆる状況に対処することは可能ではないでしょう。おそらく私は間違った行動を実装しているのかもしれません。誰かが正しい方向に私を導くことができますか?

EDIT:MVCフレームワークで複数の引数を処理する方法は可能ですか?

+0

でhome.phpとのindex.phpにいくつかの変更を加えました。 php)を使って各メソッドのパラメータを取得します。しかし、私はあなたのコードの多くを見ていないので、私はあなたのMVCの構造がどのようなものか分かりません。私のフレームワークでは、 'call_user_func_array()'を使ってメソッドをディスパッチし、引数を配列として提供するディスパッチャを持っています。 – F21

+0

私は、ある程度前からPHP MVCをセットアップしている[this](http://www.youtube.com/watch?v=Aw28-krO7ZM)ビデオチュートリアルを発見しました。これまでに6つの部品があり、すべてが次の部品に委ねられています。だから、いつでも好きな場所で止めることができますし、それでもたくさんのことができます。今、あなたが求めていることのための非常に良いチュートリアルです。 – Shea

+0

ありがとう、私はリフレクションクラスはちょうど私が探していたものだと思うし、チュートリアルのおかげで私はそれらをチェックアウトするでしょう! – Rain

答えて

2

私は単純にすべてのアクションの唯一の引数として引数の配列を渡します。フレームワークの規約には、このようにアクションに引数を渡すことが含まれていることがわかります。これにより、実装コードは対処方法を選択できます。 func_get_args()は多分使用したり、メソッドのシグネチャでのparamaterを提供します。あなたのアクションがパラメータを必要とするかもしれないが、ユーザーが実際には1つを提供しないかもしれないということですが、警戒すべき

public function action(array $args = array()) { ... 

何か。メソッドシグネチャが値渡しを要求するようにセットアップされていて、プラグインする値が不十分な場合は、すべての種類のエラーが発生する可能性があります。これは、パラメータの配列を渡し、配列が空であっても常に渡すという理由の一部です。


また、一部BrNathanHの答えのオフ、あなたが何らかの形で特定のアクションにオブジェクトを結びつけた後、オブジェクトのコンストラクタにその配列を挿入可能性が影響します。そのオブジェクトは、アクションに必要なデータを提供し、値が存在するための適切なデフォルト/チェックを行う責任があります。適切なデータを取得していることを二重に確かめたい場合は、アクションにオブジェクト・シグネチャを追加するだけです。私はあなた自身のコードでこれをどのように実装するか正確にはわかりません。主な問題はcontroller :: actionを適切な "ParamObject"にマッピングすることです。しかし、配列をオブジェクトにラップすることは良い考えであり、渡すべきパラメータの数を知らないという問題を解決します。常に1つです。そのアクションに関連付けられた「ParamObject」です。

+0

いつでもデフォルト値を設定し、渡されたパラメータでそれらを上書きすることができます。これはいつもうまくいくわけではありませんが、何よりも優れています。 –

+0

@SurrealDreamsそれは本当です。しかし、最も重要なことは、すべての引数がデフォルト値で提供されることです。私はそれが本当に個人的な好みだと思います。答えを書いた後、私は自分自身のMVCペットプロジェクトで "ParamObject"アイデアを実装すると思います。 – cspray

+0

ありがとう、私は配列を渡すことについて考えましたが、私はすべてのアクションの配列引数を持つのではなく、メソッドヘッダーを普通に書き出すというアイデアが気に入っています。 – Rain

0

あなたは配列全体を渡すことができます。問題は、各コントローラが正しい値が存在するかどうかを確認するためにエラーチェックを行わなければならないことです。別の解決策は、パラメータを保持するデータオブジェクトを作成することです。あなたはコントローラにアクセスしています(すべてのエラーチェックを行います)。

0

引数の場合、いくつかの引数をオプションとして設定できます。このように:

function($argument='', $argument2='') 
{ 
    // ... 
} 

これは$argument$argument2がオプションであることを意味します。関数が呼び出されたときにそれらの引数が設定されていれば、それらの引数は値を持ちます。

array()を渡してから(設定した配列キーまたは項目を確認するためにisset()を使用すると)、一部の機能ではより簡単になります。

1

私がこれを説明する方法を知っている最善の方法は、例であるので、ここにPHP-MVCアプリケーションのための私自身の実装の例があります。コントロールをロードする引数を処理するHook::run関数には十分注意してください。

のindex.php:

<?php 
class Hook { 
    const default_controller = 'home'; 
    const default_method = 'main'; 
    const system_dir = 'system/'; 

    static function control ($name, $method, $parameter) { 
     self::req(Hook::system_dir.$name.'.php'); // Include the control file 
     if (method_exists('Control', $method)) { // For my implementation, I can all control classes "Control" since we should only have one at a time 
      if (method_exists('Control', 'autoload')) call_user_func(array('Control', 'autoload')); // This is extremely useful for having a function to execute everytime a particular control is loaded 
      return call_user_func(array('Control', $method), $parameter); // Our page is actually a method 
     } 
     throw new NotFound($_GET['arg']); // Appear page.com/control/method does not exist, so give a 404 
    } 

    static function param ($str, $limit = NULL) { // Just a wrapper for a common explode function 
     return (
      $limit 
       ? explode('/', rtrim($str, '/'), $limit) 
       : explode('/', rtrim($str, '/')) 
      ); 
    } 

    static function req ($path) { // Helper class to require/include a file 
     if (is_readable($path)) return require_once($path); // Make sure it exists 
     throw new NotFound($path); // Throw our 404 exeception if it doesn't 
    } 

    static function run() { 
     list($name, $method, $parameter) = (// This implementaion expects up to three arguements 
      isset($_GET['arg']) 
       ? self::param($_GET['arg'], 3) + array(self::default_controller, self::default_method, NULL) // + array allows to set for default params 
       : array(self::default_controller, self::default_method, NULL) // simply use default params 
     ); 
     return self::control($name, $method, $parameter); // Out control loader 
    } 

} 

class AuthFail extends Exception {} 
class UnexpectedError extends Exception {} 
class NotFound extends Exception {} 

try { 
    Hook::run(); 
} 
catch (AuthFail $exception) { // Makes it posssible to throw an exception when the user needs to login 
    // Put login page here 
    die('Auth failed'); 
} 
catch (UnexpectedError $exception) { // Easy way out for error handling 
    // Put error page here 
    die('Error page'); 
} 
catch (NotFound $exception) { // Throw when you can't load a control or give an appearance of 404 
    die('404 not found'); 
} 

システム/ home.php:

<?php 

class Control { 
    private function __construct() {} 
    static function autoload() { // Executed every time home is loaded 
     echo "<pre>Home autoload\n"; 
    } 
    static function main ($param='') { // This is our page 
     // Extra parameters may be delimited with slashes 
     echo "Home main, params: ".$param; 
    } 
    static function other ($param='') { // Another page 
     echo "Home other, params:\n"; 
     $param = Hook::param($param); 
     print_r($param); 
    } 
} 

.htaccessファイル:このhtaccessのファイルを使用して

RewriteEngine On 

RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-l 

RewriteRule ^(.+)$ index.php?arg=$1 [QSA,L] 

、私たちは家をロードすることができます.phpコントロールlocalhost/home/mainを使用します。それがなければ、私たちのURLはlocalhost/index?args=home/mainのようになります。

デモスクリーンショット1(ローカルホスト/ simple_mvc /ホーム/メイン/ args1/args2/args3):あなたは、常に特定の制御方法が理由である、期待しようとしているどのように多くの引数を知らない Demonstration screenshot 1

私はスラッシュで区切られた単一の引数を渡すことが最善であると信じています。制御メソッドが複数の引数を必要とする場合、提供されたHook::param関数を使用してさらに評価することができます。

デモスクリーンショット2(ローカルホスト/ simple_mvc /ホーム/その他/ args1/args2/args3): Demonstration screenshot 2

あなたの質問に答えるために:
を本当にあなたの質問に答えるのに役立ちますここで重要なファイルがありますファイルは、localhost/these/types/of/urlsを透過的にlocalhost/index.php?args=these/types/of/urlsのように変換します。そうすれば、explode($_GET['args'], '/');を使って引数を分割することができます。

この件に関する大きなビデオチュートリアルはhereです。それは本当に多くを説明するのに役立ちます。

私はあなたがリフレクション(http://www.php.net/manual/en/reflectionfunctionabstract.getparametersを使用することができ、最新の編集

+0

ありがとう、これは本当に役に立ちます。 – Rain

+0

これを少し変更しました。変更を確認すると効果があります。最後の値を表示していなかった 'Hook :: param'関数のバグを修正しました。また、' Control :: other'関数を修正して、複数の引数を渡す方法をよりよく説明しました。 'Hook :: param'を使って関数を制御します。 – Shea

関連する問題