[Symfony] Buzz\Browser でお手軽 HTTP リクエスト
HTTP リクエストを送る PHP ライブラリは数多くありますが、中でも Buzz\Browser が使いやすかったので Symfony での使用例をご紹介。
インストール
いつも通り、Composer でインストールします。作者は Assetic
で有名な Kirs Wallsmith さんです。
php composer.phar require kriswallsmith/Buzz:dev-master
折角 Symfony で使うのでサービスコンテナに登録しちゃいます。
# services.yml services: buzz.client.curl: class: Buzz\Client\Curl public: false # 証明書の検証が必要な場合は calls を削除 calls: - [ setVerifyPeer, [false] ] buzz.browser: class: Buzz\Browser arguments: ["@buzz.client.curl"]
使い方はこんな感じ
適当なコントローラに実装します。
$browser = $this->get('buzz.browser'); # ContainerInterface::get() # 診断くん $response = $browser->get('http://taruo.net/e/'); if (!$response->isSuccessful()) { throw new HttpException($response->getReasonPhrase(), $response->getStatusCode()); } $content = $response->getContent(); # 診断くんの HTML ソース
返却された Response オブジェクトの::isSuccessful()
でリクエスト結果の成否を調べる事ができます。
エラーの際は::getStatusCode()
,::getReasonPhrase()
で内容の確認しましょう。
本文の取得は::getContent()
です。
またBrowser::get()
の第2引数には任意のリクエストヘッダを配列で指定する事ができます。
$browser->get('http://taruo.net/e/', array('User-Agent', 'buzz.browser'));
::get()
の他にも::post()
や::put()
等基本的なものが揃っています。
cURL が使えない環境の人は...
file_get_contents
もサポートされているので安心。サービスコンテナの設定を次のように変更すればOKです。
# services.yml services: buzz.client.file_get_contents: class: Buzz\Client\FileGetContents public: false calls: - [ setVerifyPeer, [false] ] buzz.browser: class: Buzz\Browser arguments: ["@buzz.client.file_get_contents"]
もちろん実装部のソースコードを変える必要はありません。DI コンテナさまさまです♪
[Symfony] LiipThemeBundle でスマホ対応&Assetic を使う際の諸注意
Symfony でスマートフォン対応するにあたって LiipThemeBundle がよさげだったのでご紹介。また当バンドルを使用する際 Assetic でハマる箇所がある為メモ。
Symfony Standard Edition 2.2.1 の AcmeDemoBundle で試してみます。
LiipThemeBundle をインストール
Composer でインストール。
$ php composer.phar require liip/theme-bundle:dev-master
Bundle を登録。
# app/AppKernel.php public function registerBundles() { $bundles = array( // ... new Liip\ThemeBundle\LiipThemeBundle(), ); }
config.yml に追記。themes
には使用するテーマを定義します。今回は PC とスマホのみなのでweb
,phone
を定義します。
path_patterns
については後述。
# app/config/config.yml liip_theme: themes: ['web', 'phone'] active_theme: 'web' autodetect_theme: true path_patterns: app_resource: - %%app_path%%/views/themes/%%current_theme%%/%%template%% bundle_resource: - %%bundle_path%%/Resources/views/themes/%%current_theme%%/%%template%% cookie: name: site_theme lifetime: 31536000 # 1 year in seconds path: / domain: ~ secure: false http_only: false
続いてテーマ切り替えページ用に routing.yml に追記。
# app/config/routing.yml liip_theme: resource: "@LiipThemeBundle/Resources/config/routing.xml" prefix: /theme
スマホ用テンプレートの追加
準備が整ったので早速スマホ用のテンプレートを作成していきます。 src/Acme/DemoBundle/Resources/views 以下に themes/phone/Welcome とディレクトリを作っていき、その中に次のファイルを作成します。
{# src/Acme/DemoBundle/Resources/views/themes/phone/Welcome/index.html.twig #} {% extends 'AcmeDemoBundle::layout.html.twig' %} {% block title %}Symfony - Welcome Smartphone!{% endblock %} {% block content_header '' %} {% block content %} <h1 class="title">スマホレイアウト!!</h1> スマホだよ~ん {% endblock %}
それでは Web ブラウザで確認してみましょう。まず /theme/phone にアクセスします。トップにリダイレクトされたのち、先ほど追加したテンプレートが適用されているのが確認できます。
※今回autodetect_theme
を有効にしているのでスマホで直接アクセスしてもOKです。また、/theme/web にアクセスすると PC 用レイアウトに戻す事ができます。
次にベースレイアウトをスマホに最適化する為、以下を追加します。
{# src/Acme/DemoBundle/Resources/views/themes/phone/layout.html.twig #} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>{% block title %}Demo Bundle{% endblock %}</title> <meta content="telephone=no" name="format-detection"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> <meta content="noarchive" name="robots"> <style>h1{font-size:16pt;}</style> </head> <body> {% block content %} {% endblock %} </body> </html>
試しにスマホで表示するとこのような感じになります。(だいぶ質素になりました)
ちなみに app/Resources/views にも同様のディレクトリ構造を作ることでスマホ対応が可能です。
このライブラリの最も優れている所は、スマホ用にテンプレートが用意されていないページでも通常のテンプレートを使用してフォールバックしてくれる点です。
試しに /demo/hello/World にアクセスすると、PC 用テンプレートではありますがきちんとページが表示されます。
Assetic を併用する場合の注意点
Assetic は非常に便利ですが、LiipThemeBundle との併用にあたってひとつ注意点があります。
README によると本来ディレクトリ構造は Resources/themes/phone/... のようにするのですが、これだと中のテンプレートで定義しているアセットがphp app/console assetic:dump
でダンプできなくなります。(デバッグ環境では Routing Error が発生します)
これを回避する為テーマディレクトリは Resources/views 以下に配置し、前述のとおり config.yml にpath_patterns
を指定します。
それでも問題が発生する時は...
その時はphp app/console cache:clear --no-warmup
を試してみて下さい。
※--no-warmup
が重要です。
[Monolog][Symfony] Monolog が神過ぎる件 ~エラーログをメールで送ろう~
Symfony で採用されているロガーライブラリ Monolog は Python の LogBook と言うライブラリに影響を受けており、
柔軟なロギング処理が可能です。
今回は、Symfony の運用環境でERROR
レベル以上のログをファイルに書き込みつつ、メールでも通知するように設定してみます。
以下、config.yml
記述例。
monolog: handlers: # ERROR 以上でログファイル書き込み+メール送信 main: type: fingers_crossed action_level: ERROR handler: grouped # 以下 fingers_crossed 用 grouped: type: group members: [file, email] file: type: stream path: %kernel.logs_dir%/%kernel.environment%.log level: DEBUG email: type: swift_mailer from_email: no-reply@example.com to_email: issei.m7@gmail.com subject: "[example.com] An error occurred!" level: DEBUG
main
にはERROR
レベル以上でgrouped
が処理され、file
とemail
が実行されるように設定しています。
このfingers_crossed
が非常に優秀でgrouped
, file
, email
はmain
の下位ハンドラとなっており、通常は処理されません。この為file
やemail
はレベルがDEBUG
ですが、エラー発生時にだけ該当セッション中の全ログが書き込まれます。
これで無駄にログを肥大させる事なく、デバッグ効率が格段上がりまくりんぐです。
[Symfony] JSON レスポンスを返す
/** * @Route("/test.json", name="json") */ public function jsonAction() { // do something return new JsonResponse(array('id' => 12345, 'title' => 'json test')); }
バージョン 2.1
で追加された JsonResponse
をコントローラ内で返すだけです。コンストラクタの引数に渡した配列がそのまま出力されます。
Content-Type も自動で application/json
にしてくれます。更に、JSONP のコールバック処理もできたりします。
※詳しくは JsonResponse
とっても便利☆
[Symfony] サブドメイン別にルーティングを制御する
Symfony 2.2 で正式に追加された機能の様です。
フロントエンドをexample.com
、バックエンドをsystem.example.com
としてそれぞれ別のバンドルで運用する場合の設定例をご紹介。
まずはバックエンド用のバンドルを作成します。
$ php app/console generate:bundle --namespace=Acme/BackendBundle --format=annotation
続いて上記コマンドで自動追記されたBackendBundle
へのルーティングを修正します。
# app/config/routing.yml # バックエンド system: resource: "@BackendBundle/Controller/" type: annotation prefix: / host: system.example.com # 追加! # フロントエンド homepage: resource: "@FrontendBundle/Controller/" type: annotation prefix: /
新しく追加されたhost
によってサブドメインのルーティングを制御できるようになりました。これでsystem.example.com
はすべてBackendBundle
のコントローラにルーティングされます。
とっても簡単!