リクエスト、コントローラ、レスポンスのライフサイクル
リクエストは、フロントコントローラ(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)
{
//
}
関連サイト