Jobeetをやってみる 5日目
ルーティングについて学ぶ
設定ファイルについて
ルーティングの設定は routing.yml に記述されており、上から順にマッチしていく
アプリルートのカスタマイズ
初期設定ではルートの設定が /job になっていて、ドキュメントルートにアクセスしてもJobeetが表示されないようになっている。
まずはこれを変更する
# apps/frontend/config/routing.yml homepage: url: / param: { module: job, action: index }
そしたらlayoutのJobeet TOPへのリンクも修正する
<?php /* apps/frontend/templates/layout.php at 16 */ ?> <h1><a href="<?php echo url_for('@homepage') ?>"><img src="http://www.symfony-project.org/images/jobeet.gif" alt="Jobeet Job Board" /></a></h1>
詳細表示ページのカスタマイズ
下記のようにアクセスできると、URLで表示しているページの内容を理解できるようになる
/job/sensio-labs/paris-france/1/web-developer
これになるように設定を変更していく
設定を変更
# apps/frontend/config/routing.yml # 一番上に設定を追加する job_show_user: url: /job/:company/:location/:id/:position param: { module: job, action: show }
詳細ページへのリンクを修正する
<?php /* apps/frontend/modules/job/templates/indexSuccess.php at 7 */ ?> <a href="<?php url_for("job/show?id={$job->getId()}&company={$job->getCompany()}&location={$job->getLocation()}&position={$job->getPosition()}") ?>">
配列で書く方法もある
<?php /* apps/frontend/modules/job/templates/indexSuccess.php at 7 */ ?> <a href="<?php echo url_for(array( 'module' => 'job', 'action' => 'show', 'id' => $job->getId(), 'company' => $job->getCompany(), 'location' => $job->getLocation(), 'position' => $job->getPosition(), )) ?>">
パラメータの書式指定
requirements の設定値で指定が可能
# apps/frontend/config/routing.yml job_show_user: url: /job/:company/:location/:id/:position param: { module: job, action: show } requirements: id: \d+
許可するHTTPメソッドを指定
指定できるのは GET, POST, HEAD, DELETE, PUT
今回はGETのみ許可する
# apps/frontend/config/routing.yml job_show_user: url: /job/:company/:location/:id/:position param: { module: job, action: show } requirements: id: \d+ sf_method: [get]
Routeクラスを利用する
先程のリンクの張り方は冗長過ぎて、毎回書いていると可読性が低くなる
そんな時は、Routeクラスを利用して設定を名前で利用することができる
設定の変更
# apps/frontend/config/routing.yml job_show_user: url: /job/:company/:location/:id/:position class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: show } requirements: id: \d+ sf_method: [get]
リンクの記述方法
記述方法は2通り
<?php /* apps/frontend/modules/job/templates/indexSuccess.php at 7 */ ?> <a href="<?php echo url_for(array('sf_route' => 'job_show_user', 'sf_subject' => $job)) ?>">
<?php /* apps/frontend/modules/job/templates/indexSuccess.php at 7 */ ?> <a href="<?php echo url_for(array('job_show_user', $job) ?>">
英数字以外の扱い
jobデータを取得する際に、英数字(非単語)以外を除去するようにする
<?php // lib/model/doctrine/JobeetJob.class.php public function getCompanySlug() { return Jobeet::slugify($this->getCompany()); } public function getPositionSlug() { return Jobeet::slugify($this->getPosition()); } public function getLocationSlug() { return Jobeet::slugify($this->getLocation()); }
<?php // lib/Jobeet.class.php class Jobeet { public static function slugify($text) { $text = preg_replace('/\W+/', '-', $text); $text = strtolower(trim($text, '-')); return $text; } }
# apps/frontend/config/routing.yml job_show_user: url: /job/:company_slug/:location_slug/:id/:position_slug class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: show } requirements: id: \d+ sf_method: [get]
キャッシュをクリアして、URIが下記のようになればOK
/frontend_dev.php/job/sensio-labs/paris-france/1/web-developer
ModelをRoute Classから取得する
Doctrineから取得していましたが、route.ymlにて指定したModelを取得することが可能なので、Routeクラスから取得するように変更します
<?php // apps/frontend/modules/job/actions/actions.class.php public function executeShow(sfWebRequest $request) { $this->job = $this->getRoute()->getObject(); $this->forward404Unless($this->job); }
404エラーページ
<?php $this->forward404Unless($this->job);
を削除しても404 error pageが表示されます。
これはgetRoute()が自動で行なっているもので、optionsにallow_emptyをtrueにすると抑制できます。
# apps/frontend/config/routing.yml job_show_user: url: /job/:company_slug/:location_slug/:id/:position_slug class: sfDoctrineRoute options: { model: JobeetJob, type: object, allow_empty: true } param: { module: job, action: show } requirements: id: \d+ sf_method: [get]
Template内でのルーティング
<?php echo link_to($job->getPosition(), 'job_show_user', $job) ?> 絶対パスを利用する場合 <?php echo link_to($job->getPosition(), 'job_show_user', $job, true) ?> <a href="/job/sensio-labs/paris-france/1/web-developer">Web Developer</a>
Action内でのルーティング
<?php $this->redirect($this->generateUrl('job_show_user', $job));
また、redirect()にもforward()と同様のオーバーロードが利用されており、redirectIf()とredirectUnless()が利用できます
Collection Route Class
index. new, edit, create, update, deleteアクションのルーティングがまだdefaultの設定のままになっています。
defaultの設定は
default: url: /:module/:action/*
となっており、全てのアクションを受け入れてしまいます。
なので、本来はページ毎にルーティングを設定します。
今回はCRUD環境なのでモデルから自動でルーティングの設定をします。
# apps/frontend/config/routing.yml job: class: sfDoctrineRouteCollection options: { model: JobeetJob } job_show_user: url: /job/:company_slug/:location_slug/:id/:position_slug class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: show } requirements: id: \d+ sf_method: [get] # default rules homepage: url: / param: { module: job, action: index }
RouteCollectionについて
RouteCollectionを利用した場合、以下の設定をしたのと同じ状態になります。
job: url: /job.:sf_format class: sfDoctrineRoute options: { model: JobeetJob, type: list } param: { module: job, action: index, sf_format: html } requirements: { sf_method: get } job_new: url: /job/new.:sf_format class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: new, sf_format: html } requirements: { sf_method: get } job_create: url: /job.:sf_format class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: create, sf_format: html } requirements: { sf_method: post } job_edit: url: /job/:id/edit.:sf_format class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: edit, sf_format: html } requirements: { sf_method: get } job_update: url: /job/:id.:sf_format class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: update, sf_format: html } requirements: { sf_method: put } job_delete: url: /job/:id.:sf_format class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: delete, sf_format: html } requirements: { sf_method: delete } job_show: url: /job/:id.:sf_format class: sfDoctrineRoute options: { model: JobeetJob, type: object } param: { module: job, action: show, sf_format: html } requirements: { sf_method: get }
sf_***について
詳しいことは明日説明みたいなので、ここでは深く考えない