コントローラーは、CController またはそのサブクラスのインスタンスです。ユーザーの要求に応じてアプリケーションによって作成されます。 コントローラーが実行されると、要求されたアクションが実行され、通常は必要なモデルが導入され、対応するビューがレンダリングされます。アクションの最も単純な形式は、名前が action で始まるコントローラー クラスのメソッドです。
コントローラーには通常、デフォルトのアクションがあります。ユーザーのリクエストで実行するアクションが指定されていない場合は、デフォルトのアクションが実行されます。 デフォルトでは、デフォルトのアクション名はindexです。 CController::defaultAction を設定することで変更できます。
以下は、コントローラー クラスに必要な最も単純なコードです。このコントローラーにはアクションが定義されていないため、コントローラーへのリクエストは例外をスローします。
class SiteController extends CController { }
コントローラーとアクションは ID によって識別されます。コントローラー ID は「path/to/xyz」の形式で、対応するコントローラー クラス ファイル protected/controllers/path/to/XyzController.php に対応します。フラグ xyz は実際の名前に置き換える必要があります (たとえば、 post は protected/controllers/PostController.php に対応します)。アクション ID は、アクションの接頭辞を除いたアクション メソッド名です。たとえば、コントローラー クラスに actionEdit という名前のメソッドが含まれている場合、対応するアクション ID は edit になります。
注: バージョン 1.0.3 より前では、コントローラー ID の形式は path/to/xyz ではなく path.to.xyz です。
ユーザーは、ルートの形式で特定のコントローラーとアクションをリクエストします。ルートは、スラッシュで区切られたコントローラー ID とアクション ID によって接続されます。 たとえば、ルート post/edit は PostController とその編集アクションを表します。デフォルトでは、URL http://www.php.cn/ はこのコントローラーとアクションを要求します。
注: デフォルトでは、ルーティングでは大文字と小文字が区別されます。 バージョン 1.0.1 以降では、アプリケーション構成で CUrlManager::caseSensitive を false に設定することで、ルーティングで大文字と小文字を区別しないようにできます 。大文字と小文字を区別しないモードでは、コントローラー クラス ファイルを含むディレクトリ名は小文字であり、コントローラー マップとアクション マップで使用されるキーは小文字であるという規則に従っていることを確認してください。
バージョン 1.0.3 以降、アプリケーションにモジュールを含めることができます。モジュールでは、コントローラー アクションのルーティング形式は moduleID/controllerID/actionID です。 詳細については、モジュール関連の章を参照してください。
コントローラー インスタンスは、CWebApplication が受信リクエストを処理するときに作成されます。コントローラー ID が指定されると、アプリケーションは次のルールを使用してコントローラーのクラスとクラス ファイルの場所を決定します。
CWebApplication::catchAllRequest が指定されている場合、コントローラーはこのプロパティに基づいて作成され、ユーザーが指定したコントローラー ID は無視されます。 これは通常、アプリをメンテナンスステータスに設定し、静的なプロンプトページを表示するために使用されます。
CWebApplication::controllerMap で ID が見つかった場合、対応するコントローラー設定を使用してコントローラー インスタンスが作成されます。
IDが「path/to/xyz」の形式の場合、コントローラークラス名はXyzControllerと判断され、対応するクラスファイルはprotected/controllers/path/to/XyzControllerとなります。 php.たとえば、コントローラー ID admin/user はコントローラー クラス UserController に解決され、クラス ファイルは protected/controllers/admin/UserController.php になります。 クラス ファイルが存在しない場合、404 CHttpException がトリガーされます。
モジュール (バージョン 1.0.3 以降で利用可能) を使用した後の上記のプロセスは若干異なります。 具体的には、アプリケーションは、この ID がモジュール内のコントローラーを表しているかどうかを確認します。その場合、最初にモジュール インスタンスが作成され、次にモジュール内のコントローラー インスタンスが作成されます 。
前述したように、アクションは接頭語として action という単語を付けた名前のメソッドとして定義できます。より高度な方法は、アクション クラスを定義し、コントローラーがリクエストを受信したときにそのクラスをインスタンス化するようにすることです。 これによりアクションを再利用できるようになり、再利用性が向上します。
新しいアクション クラスを定義するには、次のコードを使用できます:
class UpdateAction extends CAction { public function run() { // place the action logic here } }
コントローラーがこのアクションを認識できるようにするには、コントローラー クラスの events() メソッドを次のようにオーバーライドする必要があります。
class PostController extends CController { public function actions() { return array( 'edit'=>'application.controllers.post.UpdateAction', ); } }
上に示したように、パス エイリアス application.controllers.post.UpdateAction を使用して、アクション クラス ファイルを protected/controllers/post/UpdateAction.php として指定しました。
クラスを記述することでベースのアクションを使用すると、アプリケーションはモジュール スタイルで編成されます。たとえば、次のディレクトリ構造は、コントローラー関連のコードを整理するために使用できます:
protected/ controllers/ PostController.php UserController.php post/ CreateAction.php ReadAction.php UpdateAction.php user/ CreateAction.php ListAction.php ProfileAction.php UpdateAction.php
アクション パラメーター バインディング
从版本 1.1.4 开始,Yii 提供了对自动动作参数绑定的支持。 就是说,控制器动作可以定义命名的参数,参数的值将由 Yii 自动从 $_GET 填充。
为了详细说明此功能,假设我们需要为 PostController 写一个 create 动作。此动作需要两个参数:
category: 一个整数,代表帖子(post)要发表在的那个分类的ID。
language: 一个字符串,代表帖子所使用的语言代码。
从 $_GET 中提取参数时,我们可以不再下面这种无聊的代码了:
class PostController extends CController { public function actionCreate() { if(isset($_GET['category'])) $category=(int)$_GET['category']; else throw new CHttpException(404,'invalid request'); if(isset($_GET['language'])) $language=$_GET['language']; else $language='en'; // ... fun code starts here ... } }
现在使用动作参数功能,我们可以更轻松的完成任务:
class PostController extends CController { public function actionCreate($category, $language='en') { $category=(int)$category; // ... fun code starts here ... } }
注意我们在动作方法 actionCreate 中添加了两个参数。 这些参数的名字必须和我们想要从 $_GET 中提取的名字一致。 当用户没有在请求中指定 $language 参数时,这个参数会使用默认值 en 。 由于 $category 没有默认值,如果用户没有在 $_GET 中提供 category 参数, 将会自动抛出一个 CHttpException (错误代码 400) 异常。从版本1.1.5开始, Yii还支持数组类型的动作参数绑定。 这是通过PHP的类型约束来实现的,语法如下:
class PostController extends CController { public function actionCreate(array $categories) { // Yii will make sure $categories be an array } }
也就是说我们在方法参数声明里的$categories之前添加了array关键字。这样的话,如果$_GET['categories']只是一个简单的字符串,它将会被转化为一个包含该字符串的数组。
注意: 如果参数声明没有加上 array 类型约束, 意味着参数必须是标量 (i.e., not an array)。这种情况下,通过 $_GET 传入一个数组参数将会引发HTTP异常。
过滤器是一段代码,可被配置在控制器动作执行之前或之后执行。例如, 访问控制过滤器将被执行以确保在执行请求的动作之前用户已通过身份验证;性能过滤器可用于测量控制器执行所用的时间。
一个动作可以有多个过滤器。过滤器执行顺序为它们出现在过滤器列表中的顺序。过滤器可以阻止动作及后面其他过滤器的执行
过滤器可以定义为一个控制器类的方法。方法名必须以 filter 开头。例如,现有的 filterAccessControl 方法定义了一个名为 accessControl 的过滤器。 过滤器方法必须为如下结构:
public function filterAccessControl($filterChain) { // 调用 $filterChain->run() 以继续后续过滤器与动作的执行。 }
其中的 $filterChain (过滤器链)是一个 CFilterChain 的实例,代表与所请求动作相关的过滤器列表。在过滤器方法中, 我们可以调用 $filterChain->run() 以继续执行后续过滤器和动作。
过滤器也可以是一个 CFilter 或其子类的实例。如下代码定义了一个新的过滤器类:
class PerformanceFilter extends CFilter { protected function preFilter($filterChain) { // 动作被执行之前应用的逻辑 return true; // 如果动作不应被执行,此处返回 false } protected function postFilter($filterChain) { // 动作执行之后应用的逻辑 } }
要对动作应用过滤器,我们需要覆盖 CController::filters() 方法。此方法应返回一个过滤器配置数组。例如:
class PostController extends CController { ...... public function filters() { return array( 'postOnly + edit, create', array( 'application.filters.PerformanceFilter - edit, create', 'unit'=>'second', ), ); } }
上述代码指定了两个过滤器: postOnly 和 PerformanceFilter。 postOnly 过滤器是基于方法的(相应的过滤器方法已在 CController 中定义); 而 performanceFilter 过滤器是基于对象的。路径别名application.filters.PerformanceFilter 指定过滤器类文件是protected/filters/PerformanceFilter。我们使用一个数组配置 PerformanceFilter ,这样它就可被用于初始化过滤器对象的属性值。此处 PerformanceFilter 的 unit 属性值将被初始为 second。
使用加减号,我们可指定哪些动作应该或不应该应用过滤器。上述代码中, postOnly 应只被应用于 edit 和 create动作,而 PerformanceFilter 应被应用于 除了 edit 和 create 之外的动作。 如果过滤器配置中没有使用加减号,则此过滤器将被应用于所有动作。
附图:控制器的run方法执行过程
以上就是Yii框架官方指南系列7——基础知识:控制器的内容,更多相关内容请关注PHP中文网(www.php.cn)!