Jobeetをやってみる 4日目

ControllerとViewの扱いを学ぶために以下のページを作成する

  • jobsのリスト表示
  • 新しいjobの作成
  • 作成済のjobの更新
  • jobの削除

Layoutについて

symfonyではLayout方式を採用している。

Layout方式というのは、対象のテンプレートを共通のテンプレートの真ん中に表示するタイプ

JobeetのCSSJavaScriptと画像ファイル

以下の場所からそれぞれ入手可能

JavaScriptは web/js/ に保存する

CSSファイルについて

CSSはテンプレート内で include_stylesheets() を呼び出すと読み込むタグを出力する。
何を呼び出すかは、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, jobs.css, job.css, print: { media: print }]

  javascripts:    []

  has_layout:     on
  layout:         layout

こうすると以下のようなタグが出力されるようになる

<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" />

このままだと、全てのページで4つのCSSを読み込むようになってしまうので個々のページで必要なCSSファイルを読み込むように変更する


まずは先程変更した設定ファイルを元に戻す

# apps/frontend/config/view.yml
stylesheets: [main.css]


そして個々のページでそれぞれのCSSファイルを読み込むように変更を加える

# apps/frontend/modules/job/config/view.yml
indexSuccess:
  stylesheets: [jobs.css]

showSuccess:
  stylesheets: [job.css]

または

<?php /* apps/frontend/modules/job/indexSuccess.php */ ?>
<?php use_stylesheet('jobs.css') ?>

<?php /* apps/frontend/modules/job/showSuccess.php */ ?>
<?php use_stylesheet('job.css') ?>

レイアウトを変更する

<?php /* 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="/job"><img src="http://www.symfony-project.org/images/jobeet.gif" alt="Jobeet Job Board" /></a></h1>
          <div id="sub_header">
            <div class="post">
              <h2>Ask for people</h2>
              <div>
                <a href="/job/new">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="http://www.symfony-project.org/images/jobeet-mini.png" />
            powered by <a href="http://www.symfony-project.org/"><img src="http://www.symfony-project.org/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>

テンプレートを変更する

<?php /* apps/frontend/modules/job/templates/indexSuccess.php */ ?>
<div id="jobs">
  <table class="jobs">
    <?php foreach ($jobeet_job_list 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>
<?php /* apps/frontend/modules/job/templates/showSuccess.php */ ?>
<?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="http://www.symfony-project.org/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 date('m/d/Y',
strtotime($job->getCreatedAt())) ?></small>
  </div>
  <div style="padding: 20px 0">
    <a href="<?php echo url_for('job/edit?id='.$job->getId()) ?>">
       Edit
    </a>
  </div>
</div>

テンプレートの中で利用する変数を $jobeet_job から $job に変更したので、Actionの中も変更する

<?php
public function executeShow(sfWebRequest $request)
{
  $this->job = Doctrine::getTable('JobeetJob')->find(array($request->getParameter('id')));
  $this->forward404Unless($this->job);
}

Slots

Slotとはテンプレートの中で共通の部分を作成する機能のことをいう
効果範囲は表示に利用した、全テンプレートになるので layout で定義すれば全てのページで同じ部分を利用することができます。

例えば layout.php のTitleの部分をSlot化する

<?php /* apps/frontend/templates/layout.php */ ?>
<?php if (!include_slot('title')): ?>
  <title>Jobeet - Your best job board</title>
<?php endif; ?>

include_slot()にて定義されたSlotを呼び出します。
また、定義されていない場合は null なので、if文を使って「定義されていない場合」のテキストも用意することができます。


Slotの定義は各々のテンプレート内にて定義します。
定義方法には2種類あり、メソッドタイプとブロックタイプがあります。

<?php
/**
 * apps/frontend/modules/job/templates/showSuccess.php
 * method type
 */
?>
<?php slot(
  'title',
  sprintf('<title>%s is looking for a %s</title>', $job->getCompany(), $job->getPosition())) ?>
<?php
/**
 * apps/frontend/modules/job/templates/showSuccess.php
 * block type
 */
?>
<?php slot('title') ?>
  <title><?php sprintf('%s is looking for a %s', $job->getCompany(), $job->getPosition())) ?></title>
<?php end_slot(); ?>

forward()

PHPオーバーロード技術を使って、様々なショートカットが実現されてます。
先程出てきた $this->forward404Unless($this->job); は

<?php
if (!$this->job) {
  $this->forward('default', '404');
}

と同じ意味となってます。

他には

<?php
// $this->forward404If($this->job);
if ($this->job) {
  $this->forward404();
}

// $this->forward404();
$this->forward('default', '404');

RequestとResponse

Requestのリスト (ブラウザから送られてくる値)
symfonyでの書き方 同等のコード
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']
Response (サーバから送られてくる値)
symfonyでの書き方 同等のコード
setCookie() setrawcookie()
setStatusCode() header()
setHttpHeader() header()
setContentType() header()
setVaryHttpHeader() header()
addCacheControlHttpHeader() header()