昨日は symfony がどうやってデータベースエンジン間の違いを吸収していたり、オブジェクト指向クラスに変換しているかを見ました。そして Doctrine でデータベーススキーマを記述したりテーブルを作成したり初期データをデータベースに投入したりしました。
今日は昨日作った job
モジュールの基本的なカスタマイズを続けます。job
モジュールは Jobeet に必要なコードをすべて有しています:
- 求人の一覧ページ
- 新しく求人を投稿するページ
- 投稿した求人を更新するページ
- 求人を削除するページ
すでにコードの準備ができてるのでモックアップに近づくようにリファクタリングしてゆきます。
MVC アーキテクチャ
もしフレームワークなしで PHP で Web サイトの開発を行うならば、HTML ごとに1つの PHP ファイルのパラダイムを使うでしょう。これらの PHP ファイルは同じ種類の構造を含んでます。それは初期化、全体設定、ページリクエストのためのビジネスロジックやデータベースからレコードの検索、最終的にはページを生成するための HTML コードを含んでいます。
HTML からロジックを分離するためにテンプレートエンジンを利用しているかもしれません。ビジネスロジックからモデルとのやりとりを分離するためにデータベース抽象化レイヤーを利用しているでしょう。しかしたいていの場合、メンテナンスが悪夢になるたくさんのコードで終わることになります。速く作れますが、時間が経つにつれて、とりわけ変更するのが難しくなります。どのように作り、どのように動くのか、あなた以外は誰も理解できないからです。
これらすべての問題に対し、よい解決方法があります。Web 開発の分野では近年コーディングのための最適解として認識されているのはMVC デザインパターンです。手短に言えば、MVC デザインパターンはコードの性質ごとに体系化する方法を定義しています。このパターンは3つのレイヤーにわけられます。
Model レイヤーはビジネスロジックを定義します (データベースはこのレイヤーに所属する)。ご存じのとおり、symfony は Model に関連するすべてのクラスとファイルを
lib/model/
ディレクトリに保存します。View はユーザーが情報をやりとりするレイヤーです (テンプレートエンジンはこのレイヤーの一部)。symfony において、View レイヤーは主に PHP テンプレートで構成されます。今日の後で見るようにこれらは
templates/
ディレクトリに保存されます。Controller はモデルからデータを取得し、クライアントへ表示するため View にデータを渡す処理を担当します。symfony をインストールした初日に、すべてのリクエストはフロントコントローラ (
index.php
とfrontend_dev.php
) によって管理されているのを見ました。
これらフロントコントローラは実際の動作はアクション (action) で行われます。昨日見たようにこれらアクションはモジュール (module) で論理的にグループにわけられます。
今日は、ホームページと求人ページをカスタマイズするために2日目で定義したモックアップを使います。これらを動的なものにもします。この先、symfony のディレクトリを構造とレイヤーのあいだでコードを分離する方法を示すためにたくさんの異なるファイルでたくさんの調整を行います。
レイアウト
まず、モックアップをじっと見てみると各ページのほとんどが同じ部品であることに気づくでしょう。PHP や HTML であろうとなかろうと、コードの重複はわるいことです。ですので、コードが重複している View 要素を抑える方法が必要となります。
この問題を解決する1つの方法としてテンプレートごとにヘッダーとフッターを定義する方法があります:
しかし、この場合、ヘッダーやフッターは有効な HTML を含んでいません。よい方法であることは違いありません。車輪の再発明をする代わりに、この問題を解決するため別のデザインパターンを使うことにします。それは Decorator デザインパターンです。Decorator デザインパターンは別のやり方で問題を解決します。
グローバルテンプレートによって表示されるコンテンツの後に、デコレートされるテンプレートを使います。
symfony ではグローバルテンプレートをレイアウトと呼びます:
アプリケーションのデフォルトテンプレートとして layout.php
が呼び出されます。それは apps/frontend/templates
ディレクトリにあります。このディレクトリにはアプリケーションのグローバルテンプレートすべてが置かれます。
symfony のデフォルトレイアウトを下記コードに置き換えましょう:
<!-- apps/frontend/templates/layout.php --> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Jobeet - Your best job board</title> <link rel="shortcut icon" href="/favicon.ico" /> <?php include_javascripts() ?> <?php include_stylesheets() ?> </head> <body> <div id="container"> <div id="header"> <div class="content"> <h1><a href="<?php echo url_for('job/index') ?>"> <img src="/legacy/images/logo.jpg" alt="Jobeet Job Board" /> </a></h1> <div id="sub_header"> <div class="post"> <h2>Ask for people</h2> <div> <a href="<?php echo url_for('job/index') ?>">Post a Job</a> </div> </div> <div class="search"> <h2>Ask for a job</h2> <form action="" method="get"> <input type="text" name="keywords" id="search_keywords" /> <input type="submit" value="search" /> <div class="help"> Enter some keywords (city, country, position, ...) </div> </form> </div> </div> </div> </div> <div id="content"> <?php if ($sf_user->hasFlash('notice')): ?> <div class="flash_notice"> <?php echo $sf_user->getFlash('notice') ?> </div> <?php endif ?> <?php if ($sf_user->hasFlash('error')): ?> <div class="flash_error"> <?php echo $sf_user->getFlash('error') ?> </div> <?php endif ?> <div class="content"> <?php echo $sf_content ?> </div> </div> <div id="footer"> <div class="content"> <span class="symfony"> <img src="/legacy/images/jobeet-mini.png" /> powered by <a href="/"> <img src="/legacy/images/symfony.gif" alt="symfony framework" /> </a> </span> <ul> <li><a href="">About Jobeet</a></li> <li class="feed"><a href="">Full feed</a></li> <li><a href="">Jobeet API</a></li> <li class="last"><a href="">Affiliates</a></li> </ul> </div> </div> </div> </body> </html>
symfony のテンプレートは単なるプレーンな PHP ファイルです。レイアウトテンプレートにおいて、PHP 関数の呼び出しと PHP 変数への参照が見られます。$sf_content
はもっとも興味深い変数です: この変数には symfony によって定義され、アクションによって生成される HTML が収められています。
job
モジュール (http://jobeet.localhost/frontend_dev.php/job
) を見ると、すべてのアクションがレイアウトによってデコレートされていることがわかります。
スタイルシート、画像、JavaScript
このチュートリアルの目的は Web デザインではないので、Jobeet で必要なすべてのアセットはすでに用意されています: 画像ファイルをダウンロードして web/legacy/images/
ディレクトリに設置します; スタイルシートファイルをダウンロードして web/css/
ディレクトリに設置します。
note
レイアウトにおいて、ファビコン (favicon) を含めることができます。Jobeet のファビコンをダウンロードして web/
ディレクトリに設置します。
tip
標準では、generate:project
タスクはプロジェクトのアセットとして3つのディレクトリを生成します。web/images
は画像用、web/~css|CSS~
はスタイルシート用、web/js
は JavaScript 用です。これは symfony で定義される多くの規約の1つですが、もちろん web
ディレクトリの下であればどこにでも置くことはできます。
鋭い読者なら main.css
がデフォルトレイアウトのどこにも記述されていないことにお気づきでしょう。main.css
は生成された HTML のなかに確かに含まれています。しかしどこにも見当たりません。どうやって可能にしているのでしょうか?
スタイルシートはレイアウトの <head>
タグブロックで見つかる include_stylesheets()
関数の呼び出しによってインクルードされました。include_stylesheets()
関数はヘルパー (helper) と呼ばれます。ヘルパーは symfony によって定義される関数で、パラメータを受け取り、HTML コードを返します。たいていの場合、ヘルパーによって時間が節約され、テンプレートで頻繁に使われるコードスニペットをパッケージにまとめます。
include_stylesheets()
ヘルパーはスタイルシート用に <link>
タグを生成します。
それにしても、ヘルパーはどうやって格納するスタイルシートを知るのでしょうか?
View レイヤーはアプリケーションの設定ファイルである view.yml
のスタイルシートのキーを編集することで設定できます。generate:app
タスクがデフォルトで生成する view.yml
は次のとおりです:
# apps/frontend/config/view.yml default: http_metas: content-type: text/html metas: #title: symfony project #description: symfony project #keywords: symfony, project #language: en #robots: index, follow stylesheets: [main.css] javascripts: [] has_layout: on layout: layout
view.yml
ファイルはアプリケーションのすべてのテンプレートの default
を設定します。たとえば、stylesheets
エントリはアプリケーションすべてのページに含むためのスタイルシートファイルの配列が定義されます (含めたファイルは include_stylesheets()
ヘルパーから呼び出されます)。
note
標準の view.yml
ファイルには、参照ファイルとして main.css
が設定されており、/css/main.css
ではありません。実際のところ、symfony によって相対パスにプレフィックスの /~css|CSS~/
がつけられるので、両方の定義は同じです。
多くのファイルが定義されたのであれば、定義と同じ順序でこれらをインクルードします:
stylesheets: [main.css, jobs.css, job.css]
media
属性を変更し、.css
を省略することもできます。:
stylesheets: [main.css, jobs.css, job.css, print: { media: print }]
この設定では下記のような表示となります:
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/jobs.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/job.css" /> <link rel="stylesheet" type="text/css" media="print" href="/css/print.css" />
tip
view.yml
設定ファイルはアプリケーションによって使われるデフォルトのレイアウトも定義します。デフォルトでは、名前は layout
で、symfony はすべてのページを layout.php
ファイルでデコレートします。has_layout
エントリを false
に切り替えることでデコレーションプロレスを無効にすることもできます。
jobs.css
ファイルはホームページに必要とされるときだけ読み込まれ、job.css
ファイルは求人ページだけに適用されます。
view.yml
ファイルはモジュール単位でカスタマイズできます。アプリケーションの view.yml
ファイルは main.css
だけをもつように変更します:
# apps/frontend/config/view.yml stylesheets: [main.css]
job
モジュールの View をカスタマイズするには、apps/frontend/modules/job/config
ディレクトリのなかで view.yml
ファイルを生成します:
# apps/frontend/modules/job/config/view.yml indexSuccess: stylesheets: [jobs.css] showSuccess: stylesheets: [job.css]
indexSuccess
と showSuccess
セクション (index
と show
アクションで使われるテンプレート名であり、後で出てきます) の下で、アプリケーションの view.yml
のデフォルトセクションで見たようなエントリを使ってカスタマイズできます。すべての固有のエントリはアプリケーションのコンフィギュレーションとしてマージされます。all
セクションを使えば、モジュールのすべてのアクションに対してコンフィギュレーションを定義できます。
経験上、設定ファイル経由で変更可能なのは、PHP コードで完成するのと同じことです。例として job
モジュールに view.yml
ファイルを作る代わりに、テンプレートからスタイルシートを呼び出すための use_stylesheet()
ヘルパーを使うこともできます:
<?php use_stylesheet('main.css') ?>
スタイルシートを全体に含めるために、レイアウト内で上記のヘルパーを使うことも可能です。
このメソッドもしくはほかのメソッドを選ぶのは本当に好みの問題です。view.yml
ファイルはモジュールのすべてのアクション用の内容を定義する方法を提供します。これはテンプレートでは定義できませんが、コンフィギュレーションはとても静的です。
一方で、use_stylesheet()
ヘルパーを利用すればより柔軟になり、さらに、同じ場所ですべての内容: スタイルシートの定義と HTML コードを同じ位置で定義されます。Jobeet に関しては、use_stylesheet()
ヘルパーを使うので、先ほど作った view.yml
を削除して use_stylesheet()
を呼び出して job
テンプレートを更新できます:
<!-- apps/frontend/modules/job/templates/indexSuccess.php --> <?php use_stylesheet('jobs.css') ?> <!-- apps/frontend/modules/job/templates/showSuccess.php --> <?php use_stylesheet('job.css') ?>
note
対照的に、JavaScript のコンフィギュレーションも view.yml
の javascripts
エントリを使ったり、テンプレートのなかから use_javascript()
ヘルパーで呼び出すことで行うことができます。
job モジュールのホームページ
3日目に見たように、ホームページは job
モジュールの index
アクションで作られています。index
アクションはページの Controller 部分で、関連テンプレートである indexSuccess.php
は View 部分です:
apps/ frontend/ modules/ job/ actions/ actions.class.php templates/ indexSuccess.php
アクション
各アクションはクラスメソッドで表されます。ホームページでは jobActions
クラス (モジュール名の末尾に Actions
をつけたもの) と executeIndex
メソッド (execute
の末尾にアクション名をつけたもの) が使われます。データベースからすべての求人情報を取得します:
// apps/frontend/modules/job/actions/actions.class.php class jobActions extends sfActions { public function executeIndex(sfWebRequest $request) { $this->jobeet_jobs = Doctrine::getTable('JobeetJob') ->createQuery('a') ->execute(); } // ... }
コードをよく見てみましょう: すべての求人情報を検索するクエリを作るために executeIndex()
メソッド (Controller) はテーブルの JobeetJob
を呼び出します。jobeet_jobs
オブジェクトプロパティに割り当てられた JobeetJob
オブジェクトの Doctrine_Collection
を返します。
このようなすべてオブジェクトプロパティは自動的にテンプレート (View) に渡されます。Controller からのデータを View に渡すには、次のように新しいプロパティを作ります:
public function executeFooBar(sfWebRequest $request) { $this->foo = 'bar'; $this->bar = array('bar', 'baz'); }
このコードはテンプレートからアクセス可能な $foo
と $bar
変数を定義しています。
テンプレート
デフォルトでは、アクションに関連するテンプレートは symfony によって推測されます (アクションの名前に サフィックスの Success
をつけたもの)。
indexSuccess.php
テンプレートはすべての求人用の HTML テーブルを生成します。現在のテンプレートコードは次のとおりです:
<!-- apps/frontend/modules/job/templates/indexSuccess.php --> <?php use_stylesheet('jobs.css') ?> <h1>Job List</h1> <table> <thead> <tr> <th>Id</th> <th>Category</th> <th>Type</th> <!-- more columns here --> <th>Created at</th> <th>Updated at</th> </tr> </thead> <tbody> <?php foreach ($jobeet_jobs as $jobeet_job): ?> <tr> <td> <a href="<?php echo url_for('job/show?id='.$jobeet_job->getId()) ?>"> <?php echo $jobeet_job->getId() ?> </a> </td> <td><?php echo $jobeet_job->getCategoryId() ?></td> <td><?php echo $jobeet_job->getType() ?></td> <!-- more columns here --> <td><?php echo $jobeet_job->getCreatedAt() ?></td> <td><?php echo $jobeet_job->getUpdatedAt() ?></td> </tr> <?php endforeach ?> </tbody> </table> <a href="<?php echo url_for('job/new') ?>">New</a>
テンプレートコードのなかでは foreach
と Job
オブジェクト ($jobeet_jobs
) のリストを繰り返し取得して、各求人ごとのカラムごとに出力させます。覚えておいて欲しいのは、カラムの値は get
から始まりカラム名のラクダ記法 になっているアクセサメソッドが呼び出されていることです (たとえば、getCreatedAt()
メソッドは create_at
カラムからデータを取得します)。
利用できるカラムのみを表示するように整理してみましょう:
<!-- apps/frontend/modules/job/templates/indexSuccess.php --> <?php use_stylesheet('jobs.css') ?> <div id="jobs"> <table class="jobs"> <?php foreach ($jobeet_jobs as $i => $job): ?> <tr class="<?php echo fmod($i, 2) ? 'even' : 'odd' ?>"> <td class="location"><?php echo $job->getLocation() ?></td> <td class="position"> <a href="<?php echo url_for('job/show?id='.$job->getId()) ?>"> <?php echo $job->getPosition() ?> </a> </td> <td class="company"><?php echo $job->getCompany() ?></td> </tr> <?php endforeach ?> </table> </div>
テンプレートの中で呼び出されている url_for()
関数は symfony のヘルパーで、明日詳しく説明します。
job ページのテンプレート
求人ページのテンプレートをカスタマイズしましょう。showSuccess.php
ファイルを開いて、次のコードに置き換えてください:
<!-- apps/frontend/modules/job/templates/showSuccess.php --> <?php use_stylesheet('job.css') ?> <?php use_helper('Text') ?> <div id="job"> <h1><?php echo $job->getCompany() ?></h1> <h2><?php echo $job->getLocation() ?></h2> <h3> <?php echo $job->getPosition() ?> <small> - <?php echo $job->getType() ?></small> </h3> <?php if ($job->getLogo()): ?> <div class="logo"> <a href="<?php echo $job->getUrl() ?>"> <img src="/uploads/jobs/<?php echo $job->getLogo() ?>" alt="<?php echo $job->getCompany() ?> logo" /> </a> </div> <?php endif ?> <div class="description"> <?php echo simple_format_text($job->getDescription()) ?> </div> <h4>How to apply?</h4> <p class="how_to_apply"><?php echo $job->getHowToApply() ?></p> <div class="meta"> <small>posted on <?php echo $job->getDateTimeObject('created_at')->format('m/d/Y') ?></small> </div> <div style="padding: 20px 0"> <a href="<?php echo url_for('job/edit?id='.$job->getId()) ?>"> Edit </a> </div> </div>
求人情報を表示するために、テンプレートはアクションから渡される $job
変数を使います。テンプレートへ渡す変数を $jobeet_job
から $job
にリネームしたいので、show
アクションの該当箇所を変更してください (変数が2カ所にあることにご注意ください):
// apps/frontend/modules/job/actions/actions.class.php public function executeShow(sfWebRequest $request) { $this->job = Doctrine::getTable('JobeetJob')-> find($request->getParameter('id')); $this->forward404Unless($this->job); }
日付のカラムを PHP の DateTime オブジェクトインスタンスに変換できることに注目してください。created_at
カラムをタイムスタンプとして定義したので、getDateTimeObject()
メソッドを使うことでカラムの値を DateTime オブジェクトに変換することができ、最初の引数として日付の書式パターンをとる format()
メソッドを呼び出します:
$job->getDateTimeObject('created_at')->format('m/d/Y');
note
求人の説明文で使われている simple_format_text()
ヘルパーは HTML を整形します。たとえば、改行を <br />
へ置き換えます。このヘルパーは Text
ヘルパーグループに属しており、デフォルトではロードされないので、use_helper()
ヘルパーを使って手動でロードさせています。
スロット
今のところ、すべてのページのタイトルはレイアウトの <title>
タグで定義されます:
<title>Jobeet - Your best job board</title>
しかし求人ページでは会社名や役職のようなもっと役に立つ情報を提供したいと考えます。
symfony ではレイアウトの領域が表示されるテンプレートに依存するとき、スロットを定義する必要があります:
動的にタイトルを変更するために、スロットをレイアウトに追加します:
// apps/frontend/templates/layout.php <title><?php include_slot('title') ?></title>
各スロットは (title
) という名前で定義され、include_slot()
ヘルパーで表示されます。今から showSuccess.php
テンプレートの冒頭部分で、求人ページのコンテンツについて定義した slot()
ヘルパーを使うようにします:
// apps/frontend/modules/job/templates/showSuccess.php <?php slot( 'title', sprintf('%s is looking for a %s', $job->getCompany(), $job->getPosition())) ?>
タイトルが複雑であるなら、slot()
ヘルパーをコードブロックで使うこともできます:
// apps/frontend/modules/job/templates/showSuccess.php <?php slot('title') ?> <?php echo sprintf('%s is looking for a %s', $job->getCompany(), $job->getPosition()) ?> <?php end_slot() ?>
(ホームページのように)ページのなかには、一般的なタイトルが必要となる場合があります。テンプレートのなかで同じタイトルを何度も繰り返す代わりに、レイアウトのなかでデフォルトのタイトルを定義します:
// apps/frontend/templates/layout.php <title> <?php include_slot('title', 'Jobeet - Your best job board') ?> </title>
include_slot()
メソッドの第2引数はスロットが定義されていない場合のデフォルト値です。デフォルトの値が長いもしくは HTML タグをもつ場合、次のコードのように定義できます:
// apps/frontend/templates/layout.php <title> <?php if (!include_slot('title')): ?> Jobeet - Your best job board <?php endif ?> </title>
include_slot()
ヘルパーはスロットが定義されていれば true
を返します。よって、テンプレートコンテンツのなかで title
スロットが定義されていれば、それを使い、デフォルトタイトルを使うようになります:
tip
ごくわずかですが include_
で始まるヘルパーを見てきました。これらのヘルパーは HTML を出力し、たいていの場合、内容を返すためだけに get_
ヘルパーに対応するものがあります:
<?php include_slot('title') ?> <?php echo get_slot('title') ?> <?php include_stylesheets() ?> <?php echo get_stylesheets() ?>
求人ページのアクション
求人のページは job
モジュールの executeShow()
メソッドで定義される show
アクションで生成されます:
class jobActions extends sfActions { public function executeShow(sfWebRequest $request) { $this->job = Doctrine::getTable('JobeetJob')-> find($request->getParameter('id')); $this->forward404Unless($this->job); } // ... }
index
アクションに関しては、今回の場合、JobeetJob
テーブルクラスは find()
メソッドを利用して求人情報を検索するために使われます。このメソッドのパラメータは job、主キーの一意性をもつ識別子です。次の節では $request->getParameter('id')
ステートメントが job の主キーを返す理由を説明します。
求人データがデータベースに存在しない場合に、ユーザーを404エラーのページに転送させることを考えます。この役目はまさに forward404Unless()
メソッドが担うことです。最初の引数のブール値をチェックして、true
でなければ現在実行中のフローを中止します。forward
メソッドは sfError404Exception
に投げて実行中のアクションをすぐに停止させるので、その後で return 文は必要ありません。
例外に関して、ユーザーに表示されるページは prod
環境と dev
環境で異なります:
note
Jobeet の Web サイトを運用サーバーにデプロイする前に、デフォルトの404エラーページをカスタマイズする方法を学びます。
リクエストとレスポンス
/job
ページや /job/show/id/1
ページをブラウザ上で見る際、データが Web サーバーのあいだを往復し始めます。ブラウザはリクエスト (request) を送信し、サーバーはレスポンス (response) を返します。
すでに symfony がリクエストを sfWebRequest
オブジェクトでカプセル化されるのは見ました (executeShow()
メソッドをご覧ください)。symfony はオブジェクト指向フレームワークであるのでレスポンスもオブジェクトです。これは sfWebResponse
クラスです。$this->getResponse()
メソッドを呼び出すことで、アクションのなかからレスポンスオブジェクトにアクセスすることができます。
これらオブジェクトは PHP 関数やグローバル変数から情報を受け取るために便利なメソッドをたくさん提供します。
note
なぜ symfony は既存の PHP 関数をラップしているのでしょうか?第一に、symfony のメソッドは PHP の標準関数より強力です。そして、アプリケーションのテストをするときは、グローバル変数をあれこれいじったり、マジックのような header()
関数を使うよりも、リクエストやレスポンスオブジェクトを使えばもっと簡単になります。
リクエスト
sfWebRequest
クラスは $_SERVER
、$_COOKIE
、$_GET
、$_POST
、$_FILES
といった PHP のスーパーグローバルをラップしています:
メソッドの名前 | 対応する PHP のスーパーグローバル |
---|---|
getMethod() |
$_SERVER['REQUEST_METHOD'] |
getUri() |
$_SERVER['REQUEST_URI'] |
getReferer() |
$_SERVER['HTTP_REFERER'] |
getHost() |
$_SERVER['HTTP_HOST'] |
getLanguages() |
$_SERVER['HTTP_ACCEPT_LANGUAGE'] |
getCharsets() |
$_SERVER['HTTP_ACCEPT_CHARSET'] |
isXmlHttpRequest() |
$_SERVER['X_REQUESTED_WITH'] == 'XMLHttpRequest' |
getHttpHeader() |
$_SERVER |
getCookie() |
$_COOKIE |
isSecure() |
$_SERVER['HTTPS'] |
getFiles() |
$_FILES |
getGetParameter() |
$_GET |
getPostParameter() |
$_POST |
getUrlParameter() |
$_SERVER['PATH_INFO'] |
getRemoteAddress() |
$_SERVER['REMOTE_ADDR'] |
すでに getParameter()
メソッドを使ってリクエストパラメータにアクセスしました。このメソッドは $_GET
または $_POST
グローバル変数や PATH_INFO
変数から値を返します。
これらのなかの特定の1つを取得できるようにしたいのであれば、getGetParameter()
や getPostParameter()
や getUrlParameter()
メソッドを利用する必要があります。
note
特定の HTTP メソッド用のアクションを制限したい場合、たとえばフォームが POST
として投稿されることを保証したい場合、isMethod()
メソッドを使うことができます: $this->forwardUnless($request->isMethod('POST'));
レスポンス
sfWebResponse
クラスは PHP 関数の ~header|HTTP ヘッダー~()
と setraw~cookie|Cookie~()
をラップします:
メソッドの名前 | 対応する PHP 関数 |
---|---|
setCookie() |
setrawcookie() |
setStatusCode() |
header() |
setHttpHeader() |
header() |
setContentType() |
header() |
addVaryHttpHeader() |
header() |
addCacheControlHttpHeader() |
header() |
もちろん sfWebResponse
クラスはレスポンスのコンテンツをセットする方法 (setContent()
) とブラウザにレスポンスを送る方法 (send()
) も提供します。
本日のチュートリアルの最初の方で view.yml
とテンプレートの両方でスタイルシートや JavaScript を管理するやり方を見ました。結局2つのテクニックともレスポンスオブジェクトの addStylesheet()
と addJavascript()
メソッドを使います。
tip
sfAction
、sfRequest
、sfResponse
クラスもたくさんの有用なメソッドを提供します。API ドキュメントを読んで symfony の内部クラスをもっと学習しましょう。
また明日
今日は、symfony で使われているいくつかのデザインパターンを説明しました。プロジェクトのディレクトリ構造の理解が進むことを願っております。レイアウトとテンプレートファイルを操作することでテンプレートで遊びました。スロットとアクションのおかげでこれらを少し動的なものに変えることもしました。
明日は、今日使った url_for()
ヘルパーとルーティングサブフレームワークについて学びます。
This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License license.