Symfony Component Advent Calendar 2022の1日目の記事です。
最初に
SymfonyはPHPのフレームワークのひとつです。しかし、公式サイトの説明文には
Symfony is a set of PHP Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony.
(SymfonyはPHPコンポーネントのセットで、Webアプリケーションフレームワークで、哲学、そしてコミュニティです。それらがハーモニーを奏でながら動作しています。)
と書かれている通り、PHPコンポーネントのセットで、たくさんのコンポーネントを提供しており、それらを組み合わせてひとつのフレームワークとして動作しています。Symfonyのコンポーネントは、Symfony上だけで動作するのではなく、他のPHPフレームワークやアプリケーションでも動作している強力なものが揃っています。
今回はそれらの中から、役立ちそうなもの・お薦めしたいものを紹介していきたいと思います。
※記事内ではautoloadのインポートは省略します。
HTTPのやりとりに使うデータを扱う、 "HttpFoundation"
HttpFoundationは、HTTPで扱うデータをオブジェクトとして扱うことができるようになるコンポーネントです。Symfony以外のフレームワークやアプリケーションでも動作します。Symfonyではフレームワークインストール時に初期インストールされているコンポーネントです。
インストール
composer require symfony/http-foundation
リクエスト
PHPでは$_GET
, $_POST
, $_COOKIE
など、標準のリクエスト用の変数が用意されています。それらをHttpFoundationではオブジェクトとして扱えるようにします。
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
$request->query->get('hoge'); // $_GET['hoge']にアクセス
$request->request->get('hoge'); // $_POST['hoge']にアクセス
$request->cookies->get('hoge'); // $_COOKIE['hoge']にアクセス
$request->files->get('hoge'); // $_FILE['hoge']にアクセス
$request->attributes->get('hoge'); // HTTPリクエストではない追加した値にアクセス
$request->server->get('hoge'); // $_SERVER['hoge']にアクセス
$request->headers->get('hoge'); // $_SERVER['hoge']にアクセス
$request->getContent(); // POSTの生データにアクセス
上記のように、リクエストオブジェクトの中にそれぞれ対応したプロパティがあり、それを使ってHTTPリクエストの値にアクセスします。
この中で特殊なのはattribute
とgetContent()
です。
attribute
HTTPリクエストにはないけど、一緒に扱うと便利そうなデータを追加するためにあります。
$request = Request::createFromGlobals();
$request->attributes->set('hoge', 'abcde');
echo($request->attributes->get('hoge')); // 'abcde'
また、Symfonyコントローラーで、リクエストを使うとデフォルトで以下の値が追加されています。
class TestController extends AbstractController
{
#[Route('/test/{id}, name: 'app_test')]
public function index(Request $request)
{
dd($request->attributes);
}
}
^ Symfony\Component\HttpFoundation\ParameterBag {#13 ▼
#parameters: array:5 [▼
"_route" => "app_test" // ルーティング名
"_controller" => "App\Controller\TestController::index" // 呼び出したコントローラー::アクション
"id" => "1" // ルーティングでパスに設定したパラメータ属性の値(/test/1でアクセスした場合、"1")
"_route_params" => array:1 [▼ // ルーティングでパスに設定したパラメータ属性の値の配列
"id" => "1"
]
]
}
getContent()
getContent()
は、POSTされた生データを扱います。XMLやJSONなどの生データを使う必要があるときに便利です。さらにJSONの場合はtoArray()
を使うと配列にしたJSONデータを受け取ることができます。
$rawData = $request->getContent(); // 生データ
$data = $request->toArray(); // JSONが連想配列になったデータ
レスポンス
レスポンスも、ヘッダーやコンテンツなどをオブジェクトとして扱えます。
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Cookie;
$response = new Response(
'コンテンツ',
Response::HTTP_OK, // 200
['Content-Type' => 'text/html']
);
$response->headers->get('Content-Type'); // ヘッダーのContent-Typeにアクセス
$response->headers->set('Content-Type', 'text/html');// ヘッダーのContent-Typeを設定
$response->getContent(); // コンテンツにアクセス
$response->setContent('コンテンツ'); // コンテンツを設定
$response->getStatusCode(); // ステータスコードにアクセス
$response->setStatusCode(200); // ステータスコード設定
$response->headers->getCookie('hoge'); // クッキー hoge にアクセス
$response->headers->setCookie(Cookie::create('hoge', 'foo')); // クッキー hoge を設定
$response->send(); // レスポンスを出力
send()
は内部でecho()
などの出力処理をしてたりするので、send()を呼ぶだけで出力されます。
また、レスポンスはそれぞれの出力形式によって便利なクラスが用意されています。
リダイレクト
リダイレクト用にRedirectResponseが用意されています。
use Symfony\Component\HttpFoundation\RedirectResponse;
$response = new RedirectResponse('http://qiita.com');
ストリーミング
ストリーミング出力もあります。setCallback()
内で出力処理は書く必要があります。
use Symfony\Component\HttpFoundation\StreamedResponse;
$response = new StreamedResponse();
$response->setCallback(function() {
for (i = 0; i < 10; i ++) {
echo("${i}<br>");
flush();
}
});
$response->send();
ファイル
ファイル出力の場合、環境内のファイルを出力する場合はBinaryFileResponse
, 動的に作った値を出力する場合はResponse
を使います。
use Symfony\Component\HttpFoundation\BinaryFileResponse;
$file = 'public/images/image.png';
$response = new BinaryFileResponse($file);
$response->send();
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Response;
$csv = "a,b,c\nd,e,f\n";
$response = new Response($csv);
$disposition = HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHEMENT,
'result.csv'
);
$response->headers->set('Content-Disposition', $disposition);
$response->send();
JSON
JSONを出力する場合は JsonResponse
を使います。APIとか作ったときに便利です。
use Symfony\Component\HttpFoundation\JsonResponse;
$data = [
'hoge' => 'foo',
'bar' => [
1,
2,
],
];
$response = new JsonResponse($data);
$response->send();
まとめ
上記のような感じで、HTTPリクエスト、レスポンスをオブジェクトで扱えるようになります。
素のPHPにこれだけインストールして使うだけでもだいぶ作りやすくなるんじゃないかなと思います。
※2日目からは、もうちょっと記述量減らしてエコでやっていくとおもいます。