2 フォロワー

コントローラー

コントローラーはMVCアーキテクチャの一部です。yii\base\Controllerから拡張したクラスのオブジェクトであり、リクエストの処理とレスポンスの生成を担当します。特に、アプリケーションから制御を引き継いだ後、コントローラーは着信リクエストデータの分析を行い、それをモデルに渡し、モデルの結果をビューに挿入し、最終的に発信レスポンスを生成します。

アクション

コントローラーは、エンドユーザーがアドレス指定して実行をリクエストできる最も基本的な単位であるアクションで構成されています。コントローラーには、1つまたは複数のアクションを含めることができます。

次の例は、`view`と`create`の2つのアクションを持つ`post`コントローラーを示しています。

namespace app\controllers;

use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;

class PostController extends Controller
{
    public function actionView($id)
    {
        $model = Post::findOne($id);
        if ($model === null) {
            throw new NotFoundHttpException;
        }

        return $this->render('view', [
            'model' => $model,
        ]);
    }

    public function actionCreate()
    {
        $model = new Post;

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            return $this->render('create', [
                'model' => $model,
            ]);
        }
    }
}

`view`アクション(`actionView()`メソッドで定義)では、コードは最初にリクエストされたモデルIDに従ってモデルを読み込みます。モデルが正常に読み込まれた場合、`view`という名前のビューを使用して表示されます。そうでない場合は、例外をスローします。

`create`アクション(`actionCreate()`メソッドで定義)では、コードは似ています。最初に、リクエストデータを使用してモデルの新しいインスタンスを設定し、モデルを保存しようとします。両方が成功した場合、新しく作成されたモデルのIDを使用して`view`アクションにブラウザをリダイレクトします。そうでない場合は、ユーザーが必要な入力を提供できる`create`ビューを表示します。

ルート

エンドユーザーは、いわゆるルートを通じてアクションにアクセスします。ルートは、次の部分で構成される文字列です。

  • モジュールID:これは、コントローラーがアプリケーション以外のモジュールに属する場合にのみ存在します。
  • コントローラーID:同じアプリケーション内(またはコントローラーがモジュールに属する場合、同じモジュール内)のすべてのコントローラーの中でコントローラーを一意に識別する文字列。
  • アクションID:同じコントローラー内のすべてのアクションの中でアクションを一意に識別する文字列。

ルートは次の形式になります。

ControllerID/ActionID

コントローラーがモジュールに属する場合、次の形式になります。

ModuleID/ControllerID/ActionID

そのため、ユーザーがURL `https://hostname/index.php?r=site/index` でリクエストした場合、`site`コントローラーの`index`アクションが実行されます。ルートがどのようにアクションに解決されるかについては、ルーティングとURLの作成セクションを参照してください。

コントローラーの作成

ウェブアプリケーションにおいては(Webアプリケーション)、コントローラーはyii\web\Controllerまたはその子クラスを継承する必要があります。同様に、コンソールアプリケーション(コンソールアプリケーション)では、コントローラーはyii\console\Controllerまたはその子クラスを継承する必要があります。以下のコードはsiteコントローラーを定義しています。

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
}

コントローラーID

通常、コントローラーは特定の種類のリソースに関するリクエストを処理するように設計されています。このため、コントローラーIDは、処理するリソースの種類を表す名詞であることがよくあります。たとえば、記事データを処理するコントローラーのIDとしてarticleを使用できます。

デフォルトでは、コントローラーIDには、小文字の英字、数字、アンダースコア、ハイフン、スラッシュのみを含める必要があります。たとえば、articlepost-commentはどちらも有効なコントローラーIDですが、article?PostCommentadmin\postは無効です。

コントローラーIDには、サブディレクトリプレフィックスを含めることもできます。たとえば、admin/articleは、コントローラー名前空間の下のadminサブディレクトリにあるarticleコントローラーを表します。サブディレクトリプレフィックスに使用できる有効な文字には、大文字と小文字の英字、数字、アンダースコア、スラッシュが含まれます。スラッシュは、複数レベルのサブディレクトリ(例:panels/admin)のセパレーターとして使用されます。

コントローラークラスの命名

コントローラークラス名は、次の手順に従ってコントローラーIDから導出できます。

  1. ハイフンで区切られた単語の最初の文字を大文字にします。コントローラーIDにスラッシュが含まれる場合、このルールはIDの最後のスラッシュ以降の部分にのみ適用されます。
  2. ハイフンを削除し、スラッシュをバックスラッシュに置き換えます。
  3. サフィックスControllerを追加します。
  4. コントローラー名前空間をプリフィックスに追加します。

以下は、コントローラー名前空間がデフォルト値app\controllersであることを前提とした例です。

  • articleapp\controllers\ArticleControllerになります。
  • post-commentapp\controllers\PostCommentControllerになります。
  • admin/post-commentapp\controllers\admin\PostCommentControllerになります。
  • adminPanels/post-commentapp\controllers\adminPanels\PostCommentControllerになります。

コントローラークラスは自動ロード可能である必要があります。このため、上記の例では、articleコントローラークラスは、エイリアス@app/controllers/ArticleController.phpであるファイルに保存する必要があります。一方、admin/post-commentコントローラーは@app/controllers/admin/PostCommentController.phpに保存する必要があります。

情報:最後の例admin/post-commentは、コントローラー名前空間のサブディレクトリにコントローラーを配置する方法を示しています。これは、コントローラーをいくつかのカテゴリに整理したい場合に、モジュールを使用したくない場合に役立ちます。

コントローラーマップ

コントローラーマップを構成することで、上記のコントローラーIDとクラス名の制約を克服できます。これは主に、サードパーティのコントローラーを使用しており、そのクラス名を制御できない場合に役立ちます。

コントローラーマップは、アプリケーション構成で構成できます。例:

[
    'controllerMap' => [
        // declares "account" controller using a class name
        'account' => 'app\controllers\UserController',

        // declares "article" controller using a configuration array
        'article' => [
            'class' => 'app\controllers\PostController',
            'enableCsrfValidation' => false,
        ],
    ],
]

デフォルトコントローラー

各アプリケーションには、yii\base\Application::$defaultRouteプロパティで指定されたデフォルトコントローラーがあります。リクエストがルートを指定していない場合、このプロパティで指定されたルートが使用されます。ウェブアプリケーション(Webアプリケーション)では、その値は'site'であり、コンソールアプリケーション(コンソールアプリケーション)ではhelpです。そのため、URLがhttps://hostname/index.phpの場合、siteコントローラーがリクエストを処理します。

次のアプリケーション構成でデフォルトコントローラーを変更できます。

[
    'defaultRoute' => 'main',
]

アクションの作成

アクションの作成は、コントローラークラスにいわゆる「アクションメソッド」を定義するほど簡単です。アクションメソッドとは、名前がactionという単語で始まる「public」メソッドです。アクションメソッドの戻り値は、エンドユーザーに送信されるレスポンスデータを表します。次のコードは、indexhello-worldの2つのアクションを定義しています。

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    public function actionIndex()
    {
        return $this->render('index');
    }

    public function actionHelloWorld()
    {
        return 'Hello World';
    }
}

アクションID

アクションは、リソースの特定の操作を実行するように設計されることがよくあります。このため、アクションIDは通常、viewupdateなどの動詞です。

デフォルトでは、アクションIDには、小文字の英字、数字、アンダースコア、ハイフンのみを含める必要があります(ハイフンを使用して単語を区切ることができます)。たとえば、viewupdate2comment-postはすべて有効なアクションIDですが、view?Updateは無効です。

アクションは、インラインアクションとスタンドアロンアクションの2つの方法で作成できます。インラインアクションはコントローラークラスのメソッドとして定義され、スタンドアロンアクションはyii\base\Actionまたはその子クラスを拡張するクラスです。インラインアクションは作成の手間が少なく、これらのアクションを再利用する予定がない場合は、多くの場合優先されます。一方、スタンドアロンアクションは、主に異なるコントローラーで使用したり、拡張機能として再配布するために作成されます。

インラインアクション

インラインアクションとは、説明したようにアクションメソッドで定義されるアクションのことです。

アクションメソッドの名前は、次の手順に従ってアクションIDから導出されます。

  1. アクションIDの各単語の最初の文字を大文字にします。
  2. ハイフンを削除します。
  3. プレフィックスactionを追加します。

たとえば、indexactionIndexになり、hello-worldactionHelloWorldになります。

注意:アクションメソッドの名前は大文字と小文字が区別されます。ActionIndexという名前のメソッドがある場合、それはアクションメソッドとは見なされず、その結果、indexアクションのリクエストは例外になります。また、アクションメソッドはpublicである必要があることに注意してください。privateまたはprotectedメソッドはインラインアクションを定義しません。

インラインアクションは、作成の手間が少ないため、最も一般的に定義されるアクションです。ただし、同じアクションを異なる場所で再利用する場合、またはアクションを再配布する場合は、スタンドアロンアクションとして定義することを検討する必要があります。

スタンドアロンアクション

スタンドアロンアクションは、yii\base\Actionまたはその子クラスを拡張するアクションクラスで定義されます。たとえば、Yiiリリースにはyii\web\ViewActionyii\web\ErrorActionがあり、どちらもスタンドアロンアクションです。

スタンドアロンアクションを使用するには、コントローラークラスでyii\base\Controller::actions()メソッドをオーバーライドして、アクションマップで宣言する必要があります。次のようになります。

public function actions()
{
    return [
        // declares "error" action using a class name
        'error' => 'yii\web\ErrorAction',

        // declares "view" action using a configuration array
        'view' => [
            'class' => 'yii\web\ViewAction',
            'viewPrefix' => '',
        ],
    ];
}

ご覧のとおり、actions()メソッドは、キーがアクションIDで、値が対応するアクションクラス名または構成である配列を返す必要があります。インラインアクションとは異なり、スタンドアロンアクションのアクションIDには、actions()メソッドで宣言されている限り、任意の文字を含めることができます。

スタンドアロンアクションクラスを作成するには、yii\base\Actionまたは子クラスを拡張し、run()という名前のpublicメソッドを実装する必要があります。run()メソッドの役割は、アクションメソッドの役割と似ています。例:

<?php
namespace app\components;

use yii\base\Action;

class HelloWorldAction extends Action
{
    public function run()
    {
        return "Hello World";
    }
}

アクションの結果

アクションメソッドの戻り値またはスタンドアロンアクションのrun()メソッドの戻り値は重要です。それは、対応するアクションの結果を表します。

戻り値は、エンドユーザーにレスポンスとして送信されるレスポンスオブジェクトにすることができます。

上記の例では、アクションの結果はすべて文字列であり、エンドユーザーに送信されるレスポンスボディとして扱われます。次の例は、レスポンスオブジェクトを返すことによって(redirect()メソッドはレスポンスオブジェクトを返すため)、アクションがユーザーのブラウザーを新しいURLにリダイレクトする方法を示しています。

public function actionForward()
{
    // redirect the user browser to https://example.com
    return $this->redirect('https://example.com');
}

アクションパラメーター

インラインアクションのアクションメソッドとスタンドアロンアクションのrun()メソッドは、「アクションパラメーター」と呼ばれるパラメーターを受け取ることができます。それらの値はリクエストから取得されます。ウェブアプリケーション(Webアプリケーション)では、各アクションパラメーターの値は、パラメーター名をキーとして$_GETから取得されます。コンソールアプリケーション(コンソールアプリケーション)では、コマンドライン引数に対応します。

次の例では、viewアクション(インラインアクション)は、$id$versionの2つのパラメーターを宣言しています。

namespace app\controllers;

use yii\web\Controller;

class PostController extends Controller
{
    public function actionView($id, $version = null)
    {
        // ...
    }
}

アクションパラメーターは、異なるリクエストに対して次のように設定されます。

  • https://hostname/index.php?r=post/view&id=123$idパラメーターには'123'の値が設定されますが、versionクエリパラメーターがないため、$versionnullのままです。
  • https://hostname/index.php?r=post/view&id=123&version=2$idパラメーターと$versionパラメーターには、それぞれ'123''2'の値が設定されます。
  • https://hostname/index.php?r=post/view:必須の$idパラメーターがリクエストに提供されていないため、yii\web\BadRequestHttpException例外がスローされます。
  • https://hostname/index.php?r=post/view&id[]=123$idパラメーターが予期しない配列値['123']を受け取っているため、yii\web\BadRequestHttpException例外がスローされます。

アクションパラメーターが配列値を受け入れるようにするには、次のようにarrayで型ヒントを付ける必要があります。

public function actionView(array $id, $version = null)
{
    // ...
}

これで、リクエストがhttps://hostname/index.php?r=post/view&id[]=123の場合、$idパラメーターは['123']の値を取ります。リクエストがhttps://hostname/index.php?r=post/view&id=123の場合、スカラー値'123'は自動的に配列に変換されるため、$idパラメーターは同じ配列値を受け取ります。

上記の例は主に、ウェブアプリケーションのアクションパラメーターの動作を示しています。コンソールアプリケーションについては、詳細についてはコンソールコマンドセクションを参照してください。

デフォルトアクション

各コントローラーには、yii\base\Controller::$defaultActionプロパティで指定されたデフォルトアクションがあります。ルートにコントローラーIDのみが含まれている場合、指定されたコントローラーのデフォルトアクションがリクエストされていることを意味します。

デフォルトでは、デフォルトアクションはindexとして設定されています。デフォルト値を変更するには、コントローラークラスでこのプロパティをオーバーライドするだけです。次のようになります。

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    public $defaultAction = 'home';

    public function actionHome()
    {
        return $this->render('home');
    }
}

コントローラーのライフサイクル

リクエストを処理する場合、アプリケーションは、リクエストされたルートに基づいてコントローラーを作成します。次に、コントローラーは次のライフサイクルを経てリクエストを処理します。

  1. コントローラが生成され、設定された後に、yii\base\Controller::init()メソッドが呼び出されます。
  2. コントローラは、リクエストされたアクションIDに基づいてアクションオブジェクトを作成します。
    • アクションIDが指定されていない場合、デフォルトのアクションIDが使用されます。
    • アクションIDがアクションマップで見つかった場合、スタンドアロンアクションが作成されます。
    • アクションIDがアクションメソッドと一致する場合、インラインアクションが作成されます。
    • それ以外の場合は、yii\base\InvalidRouteException例外がスローされます。
  3. コントローラは、アプリケーション、モジュール(コントローラがモジュールに属している場合)、コントローラのbeforeAction()メソッドを順次呼び出します。
    • 呼び出しのいずれかがfalseを返す場合、残りの未呼び出しのbeforeAction()メソッドはスキップされ、アクションの実行はキャンセルされます。
    • デフォルトでは、各beforeAction()メソッド呼び出しはbeforeActionイベントをトリガーし、ハンドラをアタッチできます。
  4. コントローラはアクションを実行します。
    • アクションパラメータは解析され、リクエストデータから設定されます。
  5. コントローラは、コントローラ、モジュール(コントローラがモジュールに属している場合)、アプリケーションのafterAction()メソッドを順次呼び出します。
    • デフォルトでは、各afterAction()メソッド呼び出しはafterActionイベントをトリガーし、ハンドラをアタッチできます。
  6. アプリケーションはアクションの結果を取得し、レスポンスに割り当てます。

ベストプラクティス

適切に設計されたアプリケーションでは、コントローラは多くの場合非常に薄く、各アクションには数行のコードしか含まれていません。コントローラが非常に複雑な場合は、通常、リファクタリングして他のクラスにコードを移動する必要があることを示しています。

具体的なベストプラクティスをいくつか示します。コントローラ

  • リクエストデータにアクセスできます。
  • はリクエストデータを使用してモデルやその他のサービスコンポーネントのメソッドを呼び出すことができます。
  • ビューを使用してレスポンスを作成できます。
  • はリクエストデータを処理すべきではありません。これはモデルレイヤーで行う必要があります。
  • はHTMLやその他のプレゼンテーションコードを埋め込むべきではありません。これはビューで行う方が良いです。

タイプミスを見つけた場合、またはこのページの改善が必要だと考える場合は、
Githubで編集してください !