コントローラ

コントローラはアプリケーションの心臓部であり、HTTP リクエストがどのように処理されるべきかを決定する部分です。

コントローラとは何か?

コントローラは単純なクラスファイルですが、ある程度 URI に関連した名前を持ちます。

次の URI を考えてみましょう:

example.com/index.php/blog/

上の例では、CodeIgniter は Blog.php を探し出し、読み込もうとします。

コントローラの名前と URI の第1セグメントが一致するとき、それは読み込まれます。

やってみましょう: Hello World!

シンプルなコントローラを作ってみましょう。動作するところを見られます。テキストエディタを使い、Blog.php というファイルを作成し、次のコードを入力してください:

<?php
class Blog extends \CodeIgniter\Controller
{
        public function index()
        {
                echo 'Hello World!';
        }
}

/application/Controllers/ ディレクトリに保存してください。

重要

ファイル 'Blog.php' は大文字の 'B' でなくてはなりません。

さて、次のような URL でサイトを表示しましょう:

example.com/index.php/blog

うまくできたなら、これが見られます:

Hello World!

重要

クラス名は大文字で始めなければなりません。

これは正しいものです:

<?php
class Blog extends \CodeIgniter\Controller {

}

これは正しく ありません

<?php
class blog extends \CodeIgniter\Controller {

}

また、常に親コントローラクラスを継承していることを確認してください。その全メソッドを継承します。

メソッド

上の例では、メソッド名は index() です。"index" メソッドは URL の 第2セグメント がないとき、いつもデフォルトで呼ばれます。"Hello World" メッセージを表示するもう一つの方法はこれです:

example.com/index.php/blog/index/

URI の第2セグメントはコントローラのどのメソッドを呼ぶかを決定します。

試してみましょう。コントローラに新しいメソッドを追加します:

<?php
class Blog extends \CodeIgniter\Controller {

        public function index()
        {
                echo 'Hello World!';
        }

        public function comments()
        {
                echo 'これを見て!';
        }
}

さて、次の URL を読み込んで comments メソッドを見てみましょう:

example.com/index.php/blog/comments/

新しいメッセージを見れたはずです。

メソッドに URI セグメントを渡す

URI に2つより多くのセグメントが渡されたなら、それらはメソッドに引数として渡されます。

例として、次のような URI があったとします:

example.com/index.php/products/shoes/sandals/123

メソッドには第3・第4セグメント("sandals" と "123")が渡されます:

<?php
class Products extends \CodeIgniter\Controller {

        public function shoes($sandals, $id)
        {
                echo $sandals;
                echo $id;
        }
}

重要

もし URI ルーティング 機能を使っているなら、メソッドに渡されるセグメントは再ルーティングされたものになります。

デフォルトコントローラを定義する

CodeIgniter には URI にコントローラが与えられなかった場合にロードするデフォルトを指定することができます。サイトのルート URL がリクエストされたときだけ使用されます。 デフォルトコントローラを指定するには、application/Config/Routes.php ファイルを開いて次の変数を設定してください:

$routes->setDefaultController('Blog');

'Blog' のところは使用したいコントローラのクラス名です。これで URI セグメントに何も指定せずに index.php を読み込んだなら、"Hello World" メッセージがデフォルトで表示されるでしょう。

より詳しくは、URI ルーティング ドキュメントの "ルーティングの設定オプション" を参照してください。

呼び出しメソッドの再マッピング

上にも書きましたように、URI の第2セグメントはたいていコントローラのメソッドとして判定されます。CodeIgniter では _remap() メソッドを使ってこの動作をオーバーライドすることができます:

public function _remap()
{
        // 何かしらのコードをここに……
}

重要

コントローラが _remap() というメソッドを持っていたなら、URI が何であれこれは 常に 呼び出されます。これは URI から呼び出されるメソッドを決定するという通常の振る舞いをオーバーライドし、独自のメソッドルーティングルールを定義できます。

オーバーライドされた呼び出しメソッド(典型的には URI の第2セグメント)は _remap() メソッドの引数として渡されます:

public function _remap($method)
{
        if ($method === 'some_method')
        {
                $this->$method();
        }
        else
        {
                $this->default_method();
        }
}

メソッド名の後にある他の追加のセグメントも _remap() に渡されます。これらのパラメータは CodeIgniter のデフォルトの振る舞いに釣り合わせるためメソッドに渡すことができます。

例:

public function _remap($method, ...$params)
{
        $method = 'process_'.$method;
        if (method_exists($this, $method))
        {
                return $this->$method(...$params);
        }
        show_404();
}

プライベートメソッド

いくつかのケースでは、特定のメソッドを公開アクセスから隠したいことがあるでしょう。 そのためには、単にメソッドを private または protected として定義してください。URI リクエスト経由では呼び出されなくなります。例として、次のようなメソッドがあるならば:

protected function utility()
{
        // いくらかのコード
}

URL 経由でアクセスしようとしても、これは動きません:

example.com/index.php/blog/utility/

コントローラをサブディレクトリに整理する

もし大型アプリケーションを作っているなら、コントローラをサブディレクトリに入れて、階層的な整理ないし構造化したいことでしょう。CodeIgniter はそうすることができます。

単純にサブディレクトリを application/Controllers/ の下に作り、コントローラクラスをその中においてください。

注釈

この機能を使ったら、URI の第1セグメントにはフォルダ名を指定しなければなりません。例えば、こんなコントローラを持っているとしましょう:

application/controllers/products/Shoes.php

上のコントローラを呼ぶには、URI は次のようなものになります:

example.com/index.php/products/shoes/show/123

それぞれのサブディレクトリにはデフォルトコントローラを持たせられます。URI にサブディレクトリ だけ が指定されているときに呼ばれます。シンプルに、application/Config/Routes.php で指定したデフォルトコントローラ名に一致するコントローラを配置してください。

また、CodeIgniter では URI ルーティング 機能を使用することで URI の再マッピングが可能です。

クラスのコンストラクタ

もしコントローラのコンストラクタを使いたいなら、次のコードをコンストラクタに 必ず 書かなければなりません:

parent::__construct(...$params);

この記述の必要性の理由は、そのローカルのコンストラクタは親コントローラクラスのコンストラクタをオーバーライドするためで、そのため手動で呼び出してやる必要があります。

例:

<?php
class Blog extends \CodeIgniter\Controller
{
        public function __construct(...$params)
        {
                parent::__construct(...$params);

                // 独自のコンストラクタのコード
        }
}

デフォルト値を設定したい場合にコンストラクタは有用です。クラスがインスタンス化するときにデフォルトで処理が走ります。コンストラクタは値を return できませんが、いくらかのデフォルト処理をするものです。

持っているプロパティ

すべてのコントローラは CodeIgniter\Controller クラスを継承する必要があります。 このクラスはすべてのコントローラで有効になるいくつかの機能を提供します。

リクエストオブジェクト

アプリケーションのメインの リクエストインスタンス はクラスのプロパティ $this->request として常に利用可能です。

レスポンスオブジェクト

アプリケーションのメインの レスポンスインスタンス はクラスのプロパティ $this->response として常に利用可能です。

ロガーオブジェクト

ロガー クラスのインスタンスはクラスのプロパティ $this->logger として利用可能です。

HTTPS 強制

メソッドにHTTPS 経由のアクセスを強制するための便利なメソッドが、すべてのコントローラ内で利用可能です:

if (!$this->request->isSecure())
{
        $this->forceHTTPS();
}

デフォルトでは、モダンなブラウザでは HTTP Strict Transport Security ヘッダをサポートしていますが、この呼び出しはブラウザに non-HTTPS 呼び出しから HTTPS 呼び出しへ強制するのを1年間としています。第1引数でその期間(秒単位)を変更できます:

if (!$this->request->isSecure())
{
        $this->forceHTTPS(31536000);    // 1年
}

注釈

多くの 時間ベースの定数 が常に利用可能です。年、月、そのほかも。

ヘルパ

ヘルパファイルの配列をクラスのプロパティとして定義できます。コントローラが読み込まれればいつでも、そのヘルパファイルは自動的にメモリに読み込まれます。そのため、コントローラ内のどこでもそのメソッドを利用できます:

class MyController extends \CodeIgniter\Controller
{
        protected $helpers = ['url', 'form'];
}

$_POST データのバリデーション

また、コントローラは $_POST データのバリデーションをすこしだけシンプルにする便利メソッドを提供しています。validate() の第1引数は現在の Request、第2引数にはバリデーションルールの配列、そしてオプションとして、通過できなかった場合のカスタムエラーメッセージの配列です。バリデーションライブラリドキュメント にはルールとメッセージの配列の形式と利用可能なルールについて、詳細が書かれています:

public function updateUser(int $userID)
{
    if (!$this->validate($this->request, [
        'email' => "required|is_unique[users.email,id,{$userID}]",
        'name' => 'required|alpha_numeric_spaces'
    ]))
    {
        return view('users/update', [
            'errors' => $this->errors
        ]);
    }

    // 成功したときに行うことをここに
}

もしルールを設定ファイルに保存しておくのがより簡便と考えるなら、$rules 配列をグループ名に置き換え、Config\Validation.php に定義することができます:

public function updateUser(int $userID)
{
    if (!$this->validate($this->request, 'userRules'))
    {
        return view('users/update', [
            'errors' => $this->errors
        ]);
    }

    // 成功したときに行うことをここに
}

注釈

また、バリデーションはモデルで自動処理させることもできます。どこでバリデーションをするかはあなた次第です。いくつかの状況ではモデルよりコントローラのほうがシンプルに思われるでしょうし、逆もまた然りです。

これでおしまいです!

これが、かいつまんでですが、コントローラについて知るべきことのすべてです。