2015年10月13日火曜日

【Symfony2.7ドキュメント読んだ?】コントローラー

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

リクエストは、フロントコントローラ(app.php, app_dev.php)からアプリケーションが実行され、 RouterがURIを元にマッチするルートのコントローラを実行する。 コントローラがレスポンスオブジェクトを返し、HTTPヘッダー情報とレスポンスオブジェクトの内容を クライアントへ返す。

開発用フロントコントローラのIP制限解除

app_dev.phpの次のようにコメントアウトする
ローカルで開発する場合は不要
/* IP制限解除
if (isset($_SERVER['HTTP_CLIENT_IP'])
    || isset($_SERVER['HTTP_X_FORWARDED_FOR'])
    || !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1')) || php_sapi_name() === 'cli-server')
) {
    header('HTTP/1.0 403 Forbidden');
    exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
}
*/

アノテーションによるURLとコントローラのマッピング

// src/AppBundle/Controller/HelloController.php
namespace 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('Hello '.$name.'!');
    }
}

ベースコントローラの継承

よく使われそうなヘルパーメソッドが使えるようになる
namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class HelloController extends Controller
{
    // ...
}

複数の引数

引数の順番は関係がなく、対応した変数名があることが重要
public function indexAction($firstName, $lastName, $foo = 'bar')
{
    // ...
}

リダイレクト

return $this->redirectToRoute('homepage'); // 引数はルート
// redirectToRoute is equivalent to using redirect() and generateUrl() together:
// return $this->redirect($this->generateUrl('homepage'), 301);

# デフォルトは302リダイレクト
return $this->redirect('http://symfony.com/doc');

return $this->redirectToRoute('homepage', array(), 301);

# 元はレスポンスオブジェクト
return new RedirectResponse($this->generateUrl('homepage'));

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

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

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

他のサービスのアクセス

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

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

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

サービスの確認コマンド

cd project_name
php app/console debug:container

エラーと404レスポンスの管理

// 404
throw $this->createNotFoundException('The product does not exist');

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

フラッシュメッセージ

# コントローラ
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(...);
}

# テンプレート
{% for flashMessage in app.session.flashbag.get('notice') %}
    
{{ flashMessage }}
{% endfor %}

リクエストオブジェクト

リクエストオブジェクトを使ってパラメータの値など取得できる
ルーティングパラメータにマッチしない変数名がある場合に、RuntimeExceptionが発生する
use Symfony\Component\HttpFoundation\Request;

// create a simple Response with a 200 status code (the default)
$response = new Response('Hello '.$name, Response::HTTP_OK);

// create a JSON-response with a 200 status code
$response = new Response(json_encode(array('name' => $name)));
$response->headers->set('Content-Type', 'application/json');
use Symfony\Component\HttpFoundation\Response;

public function indexAction(Request $request)
{
    $request->isXmlHttpRequest(); // is it an Ajax request?

    $request->getPreferredLanguage(array('en', 'fr'));

    $request->query->get('page'); // get a $_GET parameter

    $request->request->get('page'); // get a $_POST parameter
}

他のコントローラへフォワードする

public function indexAction($name)
{
    $response = $this->forward('AppBundle:Something:fancy', array(
        'name'  => $name,
        'color' => 'green',
    ));
    // ... further modify the response or return it directly
    return $response;
}

# forward先のコントローラ
public function fancyAction($name, $color)
{
   // 
}

関連サイト


0 件のコメント:

コメントを投稿