紹介 その4 MVCのC

※この記事は以下の公式ドキュメントを元に書いています。
http://kohanaframework.org/3.2/guide/kohana/mvc

今回はフレームワークの肝であるMVCのControllerについて紹介します。

Controllerについて

MVCフレームワークの基本動作はControllerがリクエストを受け取り、Modelから情報を取得してブラウザにViewを返します。では、Controllerはどのように呼び出されるのでしょう。
まずスタートするのはindex.phpです。Webサーバは.htaccess等により、index.phpを呼び出すように設定されています。index.phpはapplicationやmodules、systemへのpathの設定がされています。そしてapplication/bootstrap.phpをrequireします。
このbootstrapでアプリケーションの重要な設定を行います。その中にRouteの設定があります。以下はデフォルトのbootstrapに用意されているRouteの設定です。

Route::set('default', '(<controller>(/<action>(/<id>)))')
        ->defaults(array(
                'controller' => 'welcome',
                'action'     => 'index',
        ));

この意味については後日詳しく紹介します。ここで、リクエストされたURLを元にどのControllerを呼び出すかを決定し、Controllerクラスをnewして実行します。
この設定だとapplicationかmodulesの、classes/controller/welcome.phpが呼び出されます。デフォルトのwelcome.phpはapplication/classes/controller/welcome.phpにあり、中身はこのようになっています。

<?php defined('SYSPATH') or die('No direct script access.');

class Controller_Welcome extends Controller {

        public function action_index()
        {
                $this->response->body('module hello, world!');
        }

} // End Welcome

ここではModelもViewも登場しません。Controllerはclasses/controllerの下、もしくはそこに作られたサブディレクトリに設置する必要があります。そしてControllerクラスを継承する必要があります。あとはクラスロードの仕組み紹介 その2 クラスロードについて - isherの日記に従います。
以下のような例になります。

// classes/controller/foobar.php
class Controller_Foobar extends Controller {
 
// classes/controller/admin.php
class Controller_Admin extends Controller {
Controllers can be in sub-folders:

// classes/controller/baz/bar.php
class Controller_Baz_Bar extends Controller {
 
// classes/controller/product/category.php
class Controller_Product_Category extends Controller {

それと、継承元(System)のControllerには他にもいくつかの種類があります。Controller_Templateであったり、Controller_RESTです。これらの説明をすると長くなるので省略しますが、テンプレートやRESTなリクエストを処理するのに便利な仕組みが用意されています。もちろん、あなた自身もControllerを継承して独自のベースControllerを作る事が出来ます。共通の認証処理等をまとめて行うことが可能です。

actionについて

Controllerはクラスであり、処理を行うのはactionと呼ばれるメソッドです。この定義はControllerクラスに action_ のprefixを付けたpublicなメソッドになります。action_が付いていなかったりpublicでないメソッドはRouteから呼び出されることはありません。
actionの役割はデータをブラウザに返す事ですが、ここでViewを利用することになります。(利用しなくても良いですが)

public function action_hello()
{
    $this->response->body(View::factory('hello/world', $data)); // This will load views/hello/world.php
}

Controllerにはbefore()とafter()というメソッドを定義出来ます。before()はactionが呼び出される前に呼び出され、after()はactionが終了した後に呼び出されます。例えばログインが必要な処理をbefore()にまとめて記述することが可能です。

// Checking auth/login in before, and redirecting if necessary:
 
Controller_Admin extends Controller {
 
    public function before()
    {
        // If this user doesn't have the admin role, and is not trying to login, redirect to login
        if ( ! Auth::instance()->logged_in('admin') AND $this->request->action !== 'login')
        {
            $this->request->redirect('admin/login');
        }
    }
 
    public function action_login() {
        ...