FuelPHPのControllerクラス

FuelPHP

世間ではPHPのフレームワークと言えば、Laravelのようですが、、、FuelPHPによる案件も個人的には多い気がしてます。

開発が止まっているので、何かあった際には個々で対応する必要が出てきますがほぼ安定しているため、そんな対応はあまりないです。

今回は、FuelPHPのコントローラについて簡単な解説と使い方を説明していきます。

コントローラの種類

FuelPHPには、4つのコントローラが存在しています。

  • Controller
  • Contoller_Template
  • Controller_Rest
  • Controller_Hybrid

Controller

公式では「Base」とされている、他3つのコントローラの元になっているものがこちらの「Controller」になります。

Controllerの使い方

classes/controllerにuser.phpというファイル名で、Controllerを継承したController_Userを作成しながら説明していきます。

classes/controller/user.php

<?php

class Controller_User extends Controller
{
    public function action_index()
    {
        return Response::forge(View::forge('user/index'));
    }
}

この記述内容で「http(s)://localhost/user」へアクセスするとviews/user/index.phpのファイルの中身が表示される状態になります。

コントローラに記載したメソッドaction_index () は、GET/POSTのどちらでもリクエストを受け付ける状態になります。

次に、上で記載した内容を少し変えてみたいと思います。

classes/controller/user.php

<?php

class Controller_User extends Controller
{
    public function get_index()
    {
        return Response::forge(View::forge('user/index'));
    }
}

変えた箇所はaction_index()のメソッド名となります。
get_index ()とすることで、GETでのリクエストのみ受け付ける状態になります。

POSTでリクエストを行うと、リクエストが拒否される状態になります。

では、次にPOSTのみでリクエストを受け付けられる状態にしていきます。

classes/controller/user.php

<?php

class Controller_User extends Controller
{
    public function post_index()
    {
        return Response::forge(View::forge('user/index'));
    }
}

post_index () にメソッド名を変更するだけで、POSTのリクエストのみを受け付ける状態になります。

基本的には、get_xxxx()やpost_xxxx()のようにリクエストのメソッドに応じた処理を記載しますが、場合によってはaction_xxxx()で、どんなリクエストでも受け付ける状態として、処理の中で分岐させたりもします。

どちらが良いかは各個人の判断によりますが、明確にPOSTのみを受け付ける処理にもかかわらず、action_xxxx()で書くのは色々な温床になりそうです。

Controller のクラスメソッド

コントローラには、幾つかの便利なメソッドが最初から用意されています。

  • before()
  • router($method, $params)
  • after($response)

before()

文字からも理解できるかもしれませんが、コントローラのメソッドが呼び出される前に実行される処理となります。

classes/controller/user.php

<?php

class Controller_User extends Controller
{
    private $data = null;

    public function before()
    {
        $this->data = 'user';
    }

    public function get_index()
    {
        return Response::forge(View::forge('user/index', $this->data));
    }
}

上記の処理では、get_index()が実行される前に、before()によって、$dataの中に user と言う文字列が設定されている状態になります。

注意点としては、before()の中からは、レスポンスが返せない点です。
※リダイレクトは可能です。

classes/controller/user.php

<?php

class Controller_User extends Controller
{
    private $data = null;

    public function before()
    {
        $this->data = 'user';
        if (!Session::get('login')) {
            return Response::forge(View::forge('error/404'));
        }
    }

    public function get_index()
    {
        return Response::forge(View::forge('user/index', $this->data));
    }
}

上記の記述では、セッション内に login が存在していなければ、以降の処理を行わずに/views/error/404.phpを表示させたいのですが、このままではget_index()の処理も実行されてしまい、期待した処理にはなりません。

では、どうしたらいいのか?

そんなときには、routerを利用すると期待した処理となります。

router($method, $params)

router()を利用することで、beforeで出来なかったレスポンスの返却が可能です。

classes/controller/user.php

<?php

class Controller_User extends Controller
{
    private $data = null;

    public function router($method, $params)
    {
        if (!Session::get('login')) {
            return Response::forge(View::forge('error/404'));
        }

        parent::router($method, $params);
    }

    public function before()
    {
        $this->data = 'user';
    }

    public function get_index()
    {
        return Response::forge(View::forge('user/index', $this->data));
    }
}

先ほどbefore()で行っていた、セッション内に login が存在しているかを判別する個所をrouter()に変更しました。

この記述であれば、セッション内に login がない場合に、get_index()が実行されることなく、 views/error/404.phpが表示されます。

レスポンス(viewなど)を返却したい場合にはrouter()、その必要がない場合にはbefore()で、使用についての判断をしてもいいかもしれません。

after($response)

before()とは全く反対の処理となり、対象となるメソッドが呼び出され処理が終わった後に呼ばれるメソッドがafter()となります。

classes/controller/user.php

<?php

class Controller_User extends Controller
{
    private $user_id = 1;

    private $data = null;

    public function before()
    {
        $this->data = 'user';
    }

    public function get_index($id)
    {
        $this->user_id = $id;
        return Response::forge(View::forge('user/index', $this->data));
    }

    public function after($response)
    {
        $response = parent::after($response);
        $response->set_header('X-USER-ID', $this->user_id);
        return $response;
    }
}

先ほどまでのコードとの違いは、2点です。

  • get_index()に引数を追加
  • after()メソッドを追加

受け取った $id を $user_id にいれておき、after()の処理の際にレスポンスヘッダに X-USER-ID と命名したキーに対しての値として $user_id を設定しています。

このように対象のコントローラでの処理が完了した後、レスポンスを返す前に何かを行いたい場合に、after()を利用します。

Controller_Template

Controllerを継承した、公式では「Template」とされている「Controller_Template」になります。
Controllerとは違い、レスポンスとして返すビュー部分も扱っているコントローラです。

Controller_Template の使い方

引き続き、classes/controllerにuser.phpというファイル名で、Controller_Templateを継承したController_Userを作成しながら説明していきます。

classes/controller/user.php

<?php

class Controller_User extends Controller_Template
{
    private $data = [];

    public function action_index()
    {
        $this->data['id'] = 1;
        $this->data['name'] = 'USER NAME';

        $this->template->title = 'USER NAME PAGE';
        $this->template->content = View::forge('user/index', $this->data);
    }
}

利用されるテンプレートのコードは以下の内容です。

views/template.php

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title><?php echo $title; ?></title>
    <?php echo Asset::css('main.css'); ?>
</head>
<body>
    <div id="wrapper">
        <h1><?php echo $title; ?></h1>

        <div id="content">
            <?php echo $content; ?>
        </div>
    </div>
</body>
</html>

テンプレートのコードを見る限り、変数は「$title」と「$content」しか存在していません。
どこから変数を取得しているのかと言うと、以下の部分になります。

$this->template->title = ‘USER NAME PAGE’;
$this->template->content = View::forge(‘user/index’, $this->data);

$this->templateへ「title」と「content」を設定しています。
これが、views/template.phpで利用できるようになっています。

さて、この2つのファイルだけでは画面の表示はされません。
views/template.phpは、枠組みだけのため対象となるviews/user/index.phpのファイルがないためエラーになります。

話を進めるため、views/user/index.phpのファイルを作成していきます。

views/user/index.php

<ul>
    <li>
        <p>ID</p>
        <p><?php echo $id; ?></p>
    <li>
        <p>NAME</p>
        <p><?php echo $name; ?></p>
    </li>
</ul>

views/user/index.phpの変数については、View::forgeを呼び出した際に第2引数で渡している$dataが利用できるようになっています。

テンプレートの切替

このままの状態では、Controller_Templateを継承したControllerから返されるレスポンスには常に、views/template.phpが枠組みとして表示されてしまいます。
テンプレートの変更(切替)が出来ないと、都合が悪いこともあるため変更方法を下記に記載します。

classes/controller/user.php

<?php

class Controller_User extends Controller_Template
{
    public $template = 'template_user';

    private $data = [];

    public function action_index()
    {
        $this->data['id'] = 1;
        $this->data['name'] = 'USER NAME';

        $this->template->title = 'USER NAME PAGE';
        $this->template->content = View::forge('user/index', $this->data);
    }
}

先ほどまでの記述に、$template = ‘template_user’が追加された状態となります。
この記述だけで、枠組みとして利用されるテンプレートが、views/template_user.phpとなります。
※$templateに指定する内容に拡張子(.php)は必要ありません。

Controller_Templateのクラスメソッド

用意されているメソッドは基本的には変わりません。

  • before()
  • router($method, $params)
  • after($response)

before()

Controllerと同じ動きはしますが、記述時に注意点があります。

classes/controller/user.php

<?php

class Controller_User extends Controller_Template
{
    private $data = [];

    public function before()
    {
        parent::before();

        $this->data['name'] = 'BEFORE_USER_NAME';
    }

    public function action_index()
    {
        $this->data['id'] = 1;

        $this->template->title = 'USER NAME PAGE';
        $this->template->content = View::forge('user/index', $this->data);
    }
}

before()を呼び出す際に、継承元のControllerのbefore()を呼び出す必要があります。
そのため、before()の処理の中で、parent::before()の記述をしています。

after($response)

こちらも、before()と同様にControllerのafter()を呼び出す必要があります。

classes/controller/user.php

<?php

class Controller_User extends Controller_Template
{
    private $data = [];

    public function action_index()
    {
        $this->data['id'] = 1;
        $this->data['name'] = 'USER NAME';

        $this->template->title = 'USER NAME PAGE';
        $this->template->content = View::forge('user/index', $this->data);
    }

    public function after($response)
    {
        $response = parent::after($response);
        $response->set_header('X-USER-ID', $this->user_id);
        return $response;
    }
}

コメント

タイトルとURLをコピーしました