コントローラ


コントローラーは作成する php 関数であり、http リクエスト情報を取得し、http レスポンスを構築して (Symfony Response オブジェクトとして) 返すことができます。レスポンスは HTML ページ、XML ドキュメント、またはシリアル化 JSON の場合があります。配列、画像、リダイレクト、404 エラーなど、想像できるものなら何でも。コントローラーには、アプリケーションがページをレンダリングするために必要なロジックがすべて含まれています。

symfony のシンプルなコントローラーを見てみましょう。次のコントローラーは hello word を出力します:

use Symfony\Component\HttpFoundation\Response; public function helloAction(){
    return new Response('Hello world!');}

コントローラーの目的は同じです: Response オブジェクトを作成して返すことです。このプロセス中に、リクエストから情報を読み取り、データベース リソースをロードし、電子メールを送信し、ユーザー セッションに情報を設定することがあります。ただし、どのような場合でも、コントローラーは最終的に Response オブジェクトをクライアントに返します。

魔法のようなことは何もありません。他の要件については心配する必要はありません。一般的な例をいくつか示します。

  • コントローラー A は、ホームページ上に Response オブジェクトを準備します。 -

  • コントローラー B は、リクエストから {slug} パラメーターを読み取り、データベースからブログ投稿を読み込み、ブログ投稿を表示する を作成します。 . 応答 オブジェクト。 {slug} をデータベースから取得できない場合、コントローラーは Response オブジェクトを作成し、404 ステータス コードを返します。

  • コントローラー C は、連絡先に関するフォームの送信を処理します。リクエストからフォーム情報を読み取り、連絡先情報をデータベースに保存し、連絡先情報を含む電子メールを Web サイト管理者に送信します。最後に、ユーザーのブラウザを問い合わせフォームの「ありがとうございます」ページにリダイレクトする Response オブジェクトを作成します。

リクエスト、コントローラー、レスポンスのライフサイクル

symfony によって処理されるすべてのリクエストは同じライフサイクルになります。フレームワークは、カスタム アプリケーション コードを実行するコントローラーを使用して、多くの繰り返しタスクを最終的に実行する責任を負います。

  1. 各リクエストは、単一のフロントエンド コントローラー ( など) によって処理されます。 app.php実稼働環境または app_dev.php開発環境) ファイル処理では、フロントエンド コントローラーがフレームワークの起動を担当します。

  2. 唯一のフロントエンドコントローラーのジョブ Symfony エンジンを初期化し (Kernel を呼び出し)、Request オブジェクトを渡して処理させます。

  3. Symfony コアはルーターにリクエストを確認するように要求します。

  4. ルーターはリクエスト情報を調べて照合し、特定のルートを指すようにします。 、どのコントローラーを呼び出すかはルーティングによって決定されます;

  5. コントローラーを実行すると、コントローラー内のコードが Response オブジェクトを作成して返します;

  6. HTTP ヘッダーと Response オブジェクトの内容がクライアントに返されます。

コントローラーの作成はページを作成するのと同じくらい簡単で、URI をコントローラーにマップします。

1466410869_65826_51226_http-xkcd-request.png

名前は似ていますが、フロントエンド コントローラーは、この章で説明しているコントローラーとは異なります。フロントエンド コントローラーは、web/# の PHP アプレットです。 ## ディレクトリ.ファイルの場合、すべてのリクエストはそれを直接通過します。一般的なアプリケーションには、実稼働用のフロントエンド コントローラー (app.php など) と開発用のフロントエンド コントローラー (app_dev.php など) があります。フロントコントローラーを編集したり、表示したり、気にしたりする必要はありません。この章の「コントローラ クラス」は、便利なメソッドを使用して、アクションとも呼ばれるそれぞれの「コントローラ」を 1 つのクラスに編成します (例: updateAction()deleteAction() 、 待って)。したがって、コントローラーはコントローラー クラス内のメソッドです。これらは作成したコードを保持し、Response 応答オブジェクトを返します。

単純なコントローラー

コントローラーは PHP で呼び出し可能なもの (関数、オブジェクト メソッド、または

Closure) にすることができます。 、Symfony では、コントローラーは通常コントローラー クラスのメソッドであり、コントローラーはアクションと呼ばれることがよくあります。

// src/AppBundle/Controller/HelloController.phpnamespace AppBundle\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController{
    public function indexAction($name)
    {
        return new Response('<html><body>Hello '.$name.'!</body></html>');
    }}

ここでのコントローラーは

indexAction メソッドであり、コントローラー クラスに属します こんにちはコントローラー

このコントローラーは非常に単純です:

  • 行 2: Symfony は PHP 名前空間関数を使用してコントローラー クラス全体に名前を付けます

  • 4 行目: Symfony は PHP5.3 の名前空間関数を最大限に活用します:

    use キーワードは、コントローラーが返さなければならない Response クラスをインポートします。

    #行 6: クラス名は、コントローラー クラス名 (
  • hello
  • など) と

    Controller キーワードを連結したものです。これは、コントローラに一貫性を提供し、ルーティング設定としてコントローラ名 (例: hello) を参照できるようにする規則です。

    8 行目: コントローラー クラスの各アクションにはサフィックス
  • Action
  • が付いており、アクション名 (

    index) はルーティングに参照されます。設定ファイル。次のセクションでは、ルーティングを使用して URI をアクションにマップし、ルート プレースホルダー ({name}) をアクション パラメーター ($name) に変換する方法を示します。

    行 10: コントローラーは
  • Response
  • オブジェクトを作成して返します。

    URI のコントローラへのマッピング

新しいコントローラは、単純な HTML ページを返します。指定された URI でこのコントローラーをレンダリングできるようにするには、そのコントローラーのルートを作成する必要があります。 ルーティング コンポーネントの詳細についてはルーティングの章で説明しますが、ここではコントローラーの単純なルートを作成しましょう:

Annotations:// src/AppBundle/Controller/HelloController.phpnamespace AppBundle\Controller; use Symfony\Component\HttpFoundation\Response;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class HelloController{
    /**
     * @Route("/hello/{name}", name="hello")
     */
    public function indexAction($name)
    {
        return new Response('<html><body>Hello '.$name.'!</body></html>');
    }}

YAML:# app/config/routing.ymlhello:
    path:      /hello/{name}
    # uses a special syntax to point to the controller - see note below
    defaults:  { _controller: AppBundle:Hello:index }.
XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/routing        http://symfony.com/schema/routing/routing-1.0.xsd">     <route id="hello" path="/hello/{name}">
        <!-- uses a special syntax to point to the controller - see note below -->
        <default key="_controller">AppBundle:Hello:index</default>
    </route></routes>
PHP:// app/config/routing.phpuse Symfony\Component\Routing\Route;use Symfony\Component\Routing\RouteCollection; $collection = new RouteCollection();$collection->add('hello', new Route('/hello/{name}', array(
    // uses a special syntax to point to the controller - see note below
    '_controller' => 'AppBundle:Hello:index',))); return $collection;

これで、/hello/ryan に移動します (たとえば、組み込み Web サービス http://localhost:8000/hello/ryan を使用する場合) HelloController::indexAction() コントローラーが実行され、ryan$name 変数に割り当てられます。このようなページを作成すると、ルーティングとコントローラーを簡単に関連付けることができます。

シンプルですよね?

AppBundle:Hello:index コントローラー構文

YAML または XML 形式を使用している場合は、コントローラーに使用するもの 特定のショートカット構文は、AppBundle:Hello:index などの論理コントローラー名と呼ばれます。コントローラーの形式の詳細については、「ルーター」の章の「コントローラーの命名パターン」を参照してください。

ルーティング パラメーターをコントローラーに渡す ¶

ルートが AppBundle の HelloController::indexAction() メソッドを指していることがわかりました。 。さらに興味深いのは、コントローラー メソッドのパラメーターの受け渡しです。

// src/AppBundle/Controller/HelloController.php// ...use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; /**
 * @Route("/hello/{name}", name="hello")
 */public function indexAction($name){
    // ...}

コントローラーにはパラメーター $name があり、これは次の {name} パラメーターに対応します。一致したルート (/hello/ryan にアクセスした場合、この場合は ryan)。実際、コントローラーが実行されると、Symfony は一致したルート内のパラメーター化されたコントローラー内のすべてのパラメーターと一致します。したがって、この {name} 値は $name に渡されます。プレースホルダー名がパラメーター名と一致していることを確認してください。

ここでは、コントローラーに 2 つのパラメーターがある、より興味深い例を示します。

Annotations:// src/AppBundle/Controller/HelloController.php// ... use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class HelloController{
    /**
     * @Route("/hello/{firstName}/{lastName}", name="hello")
     */
    public function indexAction($firstName, $lastName)
    {
        // ...
    }}
YAML:# app/config/routing.ymlhello:
    path:      /hello/{firstName}/{lastName}
    defaults:  { _controller: AppBundle:Hello:index }
XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/routing        http://symfony.com/schema/routing/routing-1.0.xsd">     <route id="hello" path="/hello/{firstName}/{lastName}">
        <default key="_controller">AppBundle:Hello:index</default>
    </route></routes>
PHP:// app/config/routing.phpuse Symfony\Component\Routing\Route;use Symfony\Component\Routing\RouteCollection; $collection = new RouteCollection();$collection->add('hello', new Route('/hello/{firstName}/{lastName}', array(
    '_controller' => 'AppBundle:Hello:index',))); return $collection;

ルート パラメーターをコントローラー パラメーターにマッピングするのは、非常に簡単かつ柔軟です。開発するときは次の考えに従ってください:

1. コントローラー パラメーターの順序は重要ではありません

Symfony はルート パラメーター名に基づいてコントローラー メソッドのパラメーターを照合できます。つまり、last_name パラメータと $last_name パラメータを照合できます。コントローラーは、どのようなパラメーターを配置しても正常に動作します。

public function indexAction($lastName, $firstName){
    // ...}

2. コントローラーに必要なパラメーターはルーティング パラメーターと一致する必要があります

以下で実行時例外がスローされます (RuntimeException ) 、ルート定義に foo パラメーターがないため:

public function indexAction($firstName, $lastName, $foo){
    // ...}

パラメーターがオプションであれば便利です。次の例では例外はスローされません:

public function indexAction($firstName, $lastName, $foo = 'bar'){
    // ...}

3. すべてのルーティング パラメーターがコントローラーに応答パラメーターを持つ必要があるわけではありません

If,たとえば、last_name はコントローラにとってあまり重要ではないため、完全に無視できます:

public function indexAction($firstName){
    // ...}


you 他のパラメータを渡すこともできます。ルーターからコントローラーのパラメーターまで。追加情報をルートからコントローラーに渡す方法を参照してください


Controller 基本クラス ¶

便宜上、Symfony はオプションの Controller 基本クラスを提供します。これを継承する場合、コントローラーの動作方法については何も変わりません。また、いくつかのヘルパー メソッドとサービス コンテナーを簡単に継承できます (下記の「他のコンテナーへのアクセス」を参照): システム内のすべてのものにアクセスできるようになります。配列オブジェクトに。これらの便利なオブジェクトはサービスと呼ばれ、symfony にはテンプレートをレンダリングしたり、ログ情報を記録したりできるこれらのサービス オブジェクトが付属しています。

先頭の use ステートメントを使用して Controller クラスを追加し、HelloController を変更してそれを継承します。以下に示すように:

// src/AppBundle/Controller/HelloController.phpnamespace AppBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class HelloController extends Controller{
    // ...}

Controller 基本クラスを使用するかどうかに関係なく、これらのヘルパー メソッドを使用すると、Symfony のコア機能を簡単に使用できるようになります。実際、コア機能を確認する最良の方法は、Controller クラス自体を確認することです。

コントローラーの基本クラスを継承せずにコントローラーがどのように動作するかを知りたい場合は、コントローラーをサービスとして定義する方法を確認してください。これはオプションですが、コントローラーに注入できるより多くの「オブジェクト/依存関係」を正確に制御できるようになります。

Generate URL ¶

generateUrl()ルーターへの URL を生成できる補助メソッド。

リダイレクト

ユーザーを別のページにリダイレクトしたい場合は、redirectToRoute() メソッド:

public function indexAction(){
    return $this->redirectToRoute('homepage');     // redirectToRoute is equivalent to using redirect() and generateUrl() together:
    // return $this->redirect($this->generateUrl('homepage'));}
## を使用してください。 #デフォルトでは、

redirectToRoute() メソッドは 302 (一時) リダイレクトを実行します。 301 (永続) リダイレクトを実行したい場合は、2 番目のパラメータを変更してください:

public function indexAction(){
    return $this->redirectToRoute('homepage', array(), 301);}

外部 Web サイトへのダイレクトから、

redirect() を使用し、外部URL:

public function indexAction(){
    return $this->redirect('http://symfony.com/doc');}

詳細については、「フレームワークの開始

ルーティング」を参照してください。

redirectToRoute() メソッドは、ユーザーのリダイレクトに特化した Response オブジェクトを作成するより簡単なショートカットです。 rreeee

テンプレートのレンダリング

HTML を使用する場合は、テンプレートをレンダリングする必要があります。 render() メソッドを使用して、テンプレートをレンダリングし、出力コンテンツを Response オブジェクトに入れることができます。

use Symfony\Component\HttpFoundation\RedirectResponse; 
public function indexAction()
{
    return new RedirectResponse($this->generateUrl('homepage'));
    }

テンプレートは、より深いサブテーブルを防ぐこともできます。内容の。ただし、不必要な深い構造の作成は避けてください。

// renders app/Resources/views/hello/index.html.twig
return $this->render('hello/index.html.twig', array('name' => $name));

テンプレートは、あらゆるファイル形式で普遍的な方法でコンテンツをレンダリングできます。ほとんどの場合、テンプレートを使用して HTML コンテンツをレンダリングしますが、テンプレートを使用して、JavaScript、CSS、XML、またはその他の考えられる形式を簡単に生成することもできます。さまざまなテンプレートの書式設定方法については、「テンプレートの作成と使用」の「テンプレートの書式設定」を参照してください。

テンプレートの命名パターン

テンプレートをバンドルに入れることもできますリソース/ビューディレクトリと@App/Hello/index.html.twig@App/layout.html.twig などの特別なショートカット構文を参照してください。これらは、バンドルの Resources/views/Hello/index.html.twig および Resources/views/layout.html.twig

にそれぞれ保存されます。 。

他のサービスにアクセスする

Symfony は、多くの便利なオブジェクトをサービスに詰め込みました。これらのサービスは、テンプレートのレンダリング、電子メールの送信、データベースのクエリ、その他考えられるあらゆる「ジョブ」に使用されます。新しいバンドルをインストールすると、さらに多くのサービスが提供される場合があります。

controller 基本クラスを継承した後、get() メソッドを通じて任意の Symfony サービスにアクセスできます。一般的なサービスの一部を以下に示します。

// renders app/Resources/views/hello/greetings/index.html.twigreturn $this->render('hello/greetings/index.html.twig', array(
    'name' => $name));

どのようなサービスがありますか?すべてのサービスを確認したい場合は、debug:container コマンド ライン ビューを使用してください:

$templating = $this->get('templating'); 
$router = $this->get('router'); 
$mailer = $this->get('mailer');

詳細については、サービス コンテナ

「エラーと 404 の管理」ページを参照してください。 ¶

一部のアクションが見つからない場合は、404 応答が返されます。これを行うには、例外をスローする必要があります。基本 Controller クラスを継承する場合、次の操作を行うことができます。

$ php bin/console debug:container

createNotFoundException() メソッドは、トリガーする特別な NotFoundHttpException オブジェクトを作成します。 symfony 内の http の 404 応答。

もちろん、コントローラーで任意の Exception クラスを自由にスローすることもでき、Symfony は自動的に HTTP 応答コード 500 を返します。

public function indexAction(){
    // retrieve the object from database
    $product = ...;
    if (!$product) {
        throw $this->createNotFoundException('The product does not exist');
    }     return $this->render(...);}

各例では、書式設定されたエラー ページがエンド ユーザーに表示され、エラーが満載のデバッグ ページが開発者に表示されます (デバッグ モードの場合 app_dev.php 表示時)このページ - Symfony (および環境) の設定を表示できます。

これらのエラー ページはカスタマイズできます。詳細については、「エラー ページをカスタマイズする方法」を参照してください。

コントローラー パラメーターとしてオブジェクトをリクエストする ¶

クエリ パラメーターを取得したり、リクエスト ヘッダーを取得したり、アップロードされたファイルを取得したりする必要がある場合はどうすればよいでしょうか?この情報は、Symfony の Request オブジェクトに保存されます。コントローラーでそれらを取得するには、Request オブジェクトをパラメーターとして追加し、型を Request クラスに強制します:

throw new \Exception('Something went wrong!');

Manage Session

Symfony は、リクエスト間のユーザー (ブラウザ、ボット、または Web サービスを使用している人) に関する情報を保存できる便利な Session オブジェクトを提供します。デフォルトでは、Symfony は PHP のネイティブセッションを使用して属性を Cookie に保存します。

このセッションを取得するには、Request オブジェクトの getSession() メソッドを呼び出す必要があります。このメソッドは、SessionInterface を返します。これは、セッション データの保存と取得に最も単純なメソッドを使用します。

use Symfony\Component\HttpFoundation\Request;
public function indexAction($firstName, $lastName, Request $request){
$page = $request->query->get('page', 1);     // ...}

これらの属性は、ユーザー セッションの有効期間中保持されます。

フラッシュ メッセージ

指定したメッセージをユーザー セッションに保存することもできます。このメッセージは「フラッシュ メッセージ」と呼ばれます。経験則として、Flash メッセージは 1 回しか使用できません。取得すると自動的に消えます。このプロパティにより、「フラッシュ」メッセージがユーザー通知の保存に特に適したものになります。

フォーム送信の処理例を見てみましょう:

use Symfony\Component\HttpFoundation\Request; public function indexAction(Request $request){
    $session = $request->getSession();     // store an attribute for reuse during a later user request
    $session->set('foo', 'bar');     // get the attribute set by another controller in another request
    $foobar = $session->get('foobar');     // use a default value if the attribute doesn't exist
    $filters = $session->get('filters', array());}

リクエストを処理した後、コントローラーは Notice というフラッシュ メッセージを設定し、リダイレクトします。名前 (notice) は重要ではありません。これはメッセージを識別する識別子です。

次は、セッションから各情報を読み取るテンプレート (または、基本レイアウト内のテンプレート) です。

use Symfony\Component\HttpFoundation\Request; public function updateAction(Request $request){
    $form = $this->createForm(...);     $form->handleRequest($request);     if ($form->isValid()) {
        // do some sort of processing         $this->addFlash(
            'notice',
            'Your changes were saved!'
        );         // $this->addFlash is equivalent to $this->get('session')->getFlashBag()->add         return $this->redirectToRoute(...);
    }     return $this->render(...);}
XML:{% for flash_message in app.session.flashBag.get('notice') %}    <div class="flash-notice">
        {{ flash_message }}    </div>{% endfor %}

通常使用される Noticewarningerror はさまざまな種類の通知メッセージのキーとして使用されますが、必要なキーであればどれでも使用できます。

peek() メソッドを使用してメッセージを取得すると、メッセージを保存できます。 #Request オブジェクトと Response オブジェクト ¶

前述したように、フレームワークの
Request

オブジェクトはコントローラーのパラメーターとして渡され、データ型は強制的に

Request になります。

クラス:

PHP:<?php foreach ($view['session']->getFlash('notice') as $message): ?>
    <div class="flash-notice">        <?php echo "<div class='flash-error'>$message</div>" ?>
    </div><?php endforeach ?>
この Request クラスには、必要なリクエスト情報を返すことができるパブリック プロパティとメソッドがいくつかあります。

Request
と同様、

Response

オブジェクトにもパブリック headers プロパティがあります。これは ResponseHeaderBag です。応答ヘッダーを取得および設定するための優れたメソッドがいくつかあります。ヘッダー名の正規化により、Content-Typecontent-type または content_type と等しくなりますが、これらはすべて同じになります。 コントローラーの場合、唯一の要件は、Response オブジェクトを返すことです。 Response クラスは、HTTP 応答の PHP 抽象化です。テキストベースのメッセージが HTTP ヘッダーに入力され、その内容がクライアントに送り返されます:

use Symfony\Component\HttpFoundation\Request; public function indexAction(Request $request){
    $request->isXmlHttpRequest(); // is it an Ajax request?     $request->getPreferredLanguage(array('en', 'fr'));     // retrieve GET and POST variables respectively
    $request->query->get('page');
    $request->request->get('page');     // retrieve SERVER variables
    $request->server->get('HTTP_HOST');     // retrieves an instance of UploadedFile identified by foo
    $request->files->get('foo');     // retrieve a COOKIE value
    $request->cookies->get('PHPSESSID');     // retrieve an HTTP request header, with normalized, lowercase keys
    $request->headers->get('host');
    $request->headers->get('content_type');}
特定の応答を簡素化できる特別なクラスもいくつかあります。

JSON の場合: これは

JosnResponse
    です。表示可能 JOSN 応答を作成します。
  • ファイル操作の場合: これは

    BinaryFileResponse
  • です。提供中のファイルを表示できます。
  • ストリーミング応答の場合は、

    StreamedResponse
  • があります。参照: レスポンスのストリーミング
  • JSON ヘルパー

##3.1

json()
ヘルパーは symfony3.1 から導入されました。

API ベースのアプリケーションでは、返される JSON タイプの人気が高まっています。このため、コントローラーの基本クラスは json() メソッドを定義して JsonResponse を作成し、指定されたコンテンツを自動的にエンコードします。

use Symfony\Component\HttpFoundation\Response; 
// create a simple Response with a 200 status code (the default)$response = new Response('Hello '.$name, Response::HTTP_OK); 
// create a CSS-response with a 200 status code
$response = new Response('<style> ... </style>');
$response->headers->set('Content-Type', 'text/css');

if Serializer サービスが有効な場合アプリケーションでは、json() に渡されたコンテンツが自動的にエンコードされます。それ以外の場合は、json_encode 関数を使用することをお勧めします。

これで、Symfony Request オブジェクトと Response オブジェクトの基本を理解できました。また、HttpFoundation コンポーネントを参照して学習することもできます。もっと。 。

静的ページの作成 ¶

コントローラーなしで静的ページを作成できます (ルートとテンプレートのみが必要です)。カスタム コントローラーを使用せずにテンプレートをレンダリングする方法を参照してください。

概要 ¶

ページを作成するときは、ページ内にビジネス ロジック コードを記述する必要があります。 symfony では、これらはコントローラーであり、最終的な Response オブジェクトをユーザーに返すために何でもできる PHP 関数です。

そして、Controller 基本クラスを継承して作業を容易にすることができます。たとえば、コントローラーに HTML コードを記述する代わりに、render() を使用してテンプレートをレンダリングし、テンプレートのコンテンツを返すことができます。

他の章では、データベースからオブジェクトを読み取って永続化し、フォームの送信を処理し、キャッシュを操作するためにコントローラーがどのように使用されるかを説明します。

継続 ¶

次に、Twig を使用してテンプレートをレンダリングする方法の学習に焦点を当てます。