symfony askeet Day 7

  • リファスタリング
  • 最近の質問
  • 最近の答え
  • ユーザープロファイルを作る

リファスタリング

同じことを繰り返さないが原則なので
askeet/apps/question/templates/_list.phpにあるページ分割機能をヘルパーに抽出する。
ヘルパーはテンプレートにアクセス可能なPHP関数らしいです。

という説明はaskeetに書いてあるのでさっそくGlobalHelper.phpを作る。
場所はaskeet/apps/frontend/lib/helper/

<?php

function pager_navigation($pager,$uri)
{

  $navigation = '';

  if ($pager->haveToPaginate())
    {
      $uri .=(preg_match('/\?/',$uri) ? '&' :'?').'page=';

      // First and previous page (最初と最後のページ)
      if ($pager->getPage() != 1)
        {
          $navigation .= link_to(image_tag('first.gif','align=absmiddle'),$uri.'1');
          $navigation .= link_to(image_tag('previous.gif','align=absmiddle'),$uri.$pager->getPreviousPage()).'&nbsp;';
        }

      // Pages one by one (1つずつのページ)
      $links = array();
      foreach ($pager->getLinks() as $page)
        {
          $links[] = link_to_unless($page == $pager->getPage(),$page,$uri,$page);
        }
      $navigation .= join('&nbsp;&nbsp;',$links);

      // Next and last page (次と最後のページ)
      if ($pager->getPage() != $pager->getCurrentMaxLink())
        {
          $navigation .= '&nbsp;'.link_to(image_tag('next.gif','align=absmiddle'),$uri.$pager->getNextPage());
          $navigation .= link_to(image_tag('last.gif','align=absmiddle'),$uri.$pager->getLastPage());
        }

    }

  return $navigation;

}

ほげっと書いたら_list.phpを開く。
場所はaskeet/apps/question/templates/_list.php

<?php foreach($question_pager->getResults() as $question): ?>
  <div class="question">
    <div class="interested_block">
      <?php include_partial('interested_user', array('question' => $question)) ?>
    </div>
  
     <h2><?php echo link_to($question->getTitle(), 'question/show?stripped_title='.$question->getStrippedTitle()) ?></h2>
 
    <div class="question_body">
      <?php echo truncate_text($question->getBody(), 200) ?>
    </div>
  </div>
<?php endforeach; ?>

<div id="question_pager">
     <?php echo pager_navigation($question_pager,'question/list') ?>
</div>

で、修正したら確認。

おお、ついでに>とかが画像になってかっこよくなってる><
とても、海外っぽいデザインだけど。

最近の質問リスト

askeetのデモサイトだとこれのことですね。
http://www.askeet.com/recent/1
なるほど。ということで実装してみる。
まずは、askeet/apps/frontend/modules/question/actions/actions.class.php

  public function executeRecent()
  {
    $this->question_pager = QuestionPeer::getRecentPager($this->getRequestParameter('page',1));
  }

とても簡単に書けます。
askeetの説明を読むと呼び出す機能のはQuestionPeerクラスのメソッドに追加するとよい。とあるので追加します。
次はテンプレートの追加。
askeet/apps/frontend/modules/question/templates/recentSuccess.phpを作成する。

<h1>recent questions</h1>

<?php include_partial('list',array('question_pager' => $question_pager,'rule' => 'question/recent')) ?>

おお。
あとはルーティングの設定をする。
askeet/apps/frontend/config/routing.ymlに追加する。

recent_questions:
  url:   /question/recent/:page
  param: { module: question, action: recent, page: 1 }

ルーティングの設定を終えたのでokと言いたいところですが、actionsを弄ったのでいくつか修正する。
まずはaskeet/apps/frontend/modules/question/templates/_list.php

<div id="question_pager">
  <?php echo pager_navigation($question_pager, $rule) ?>
</div>

askeet/apps/frontend/modules/question/templates/listSuccess.phpも忘れずに。

<h1>popular questions</h1> 
 
<?php echo include_partial('list', array('question_pager' => $question_pager,'rule' => 'question/list')) ?> 


お、できてる。

最近の答え

次は「答え」のほうを作る。
見本:http://www.askeet.com/recent/answers/1
answerモジュールを作成する。

symfony init-module frondend answer

askeet/apps/frontend/actions/actions.class.phpに↓を書く。

  public function executeRecent()
  {
    $this->answer_pager = AnswerPeer::getRecentPager($this->getRequestParameter('page',1));
  }

askeet/lib/model/AnswerPeer.class.phpに↓を書く。

  public static function getRecentPager($page)
  {
    $pager = new sfPropelPager('Answer',sfConfig::get('app_pager_homepage_max'));
    $c = new Criteria();
    $c->addDescendingOrderByColumn(self::CREATED_AT);
    $pager->setCriteria($c);
    $pager->setPage($page);
    $pager->setPeerMethod('doSelectJoinUser');
    $pager->init();

    return $pager;
  }

askeet/apps/frontend/modules/answer/templates/recentSuccess.phpを作る

<?php use_helper('Date','Global') ?>

<h1>recent answers</h1>

<div id="answers">
<?php foreach ($answer_pager->getResults() as $answer): ?>
   <div class="answer">
   <h2><?php echo link_to($answer->getQuestion()->getTitle(),
                          'question/show?stripped_title='.$answer->getQuestion()->getStrippedTitle()) ?></h2>
   <?php echo count($answer->getRelevancys()) ?> points
   posted by <?php echo link_to($answer->getUser(),'user/show?id='.$answer->getUser()->getId()) ?>
   on <?php echo format_date($answer->getCreatedAt(),'p') ?>
     <div>
     <?php echo $answer->getBody() ?>
     </div>
   </div>
<?php endforeach ?>
</div>

<div id="question_pager">
   <?php echo pager_navigation($answer_pager,'answer/recent') ?>
</div>


おー

ユーザープロファイルを作る

デモサイトだと、http://www.askeet.com/user/fabpotのことですね。
ということでまずアクションを作る。
askeet/apps/frontend/modules/user/actions/actions.class.phpを作る。

  public function executeShow()
  {
    $this->subscriber = UserPeer::retrieveByPk($this->getRequestParameter('id', $this->getUser()->getSubscriberId()));
    $this->forward404Unless($this->subscriber);
    
    $this->interests = $this->subscriber->getInterestsJoinQuestion();
    $this->answers   = $this->subscriber->getAnswersJoinQuestion();
    $this->questions = $this->subscriber->getQuestions();
  }

次はテンプレート。
askeet/apps/frontend/modules/user/templates/showSuccess.phpに書きます。

<h1><?php echo $subscriber ?>'s profile</h1>

<h2>Interests</h2>

<ul>
<?php foreach($interests as $interest): $question = $interest->getQuestion() ?>
  <li><?php echo link_to($question->getTitle(),'question/show?stripped_title='.$question->getStrippedTitle()) ?></li>
<?php endforeach; ?>
</ul>

<h2>Contributions</h2>

<ul>
<?php foreach($answers as $answer): $question = $answer->getQuestion() ?>
  <li>
    <?php echo link_to($question->getTitle(),'question/show?stripped_title='.$question->getStrippedTitle()) ?><br />
    <?php echo $answer->getBody() ?>
  </li>
<?php endforeach; ?>
</ul>

<h2>Questions</h2>

<ul>
<?php foreach($questions as $question): ?>
  <li><?php echo link_to($question->getTitle(),'question/show?stripped_title='.$question->getStrippedTitle()) ?></li>
<?php endforeach; ?>
</ul>

ほげーっと書いたらリンクを追加するようにする。
まずはaskeet/apps/frontend/modules/question/templates/_list.php

<?php use_helper('Text', 'Global', 'Date') ?>
 
<?php foreach($question_pager->getResults() as $question): ?>
  <div class="question">
    <div class="interested_block">
      <?php include_partial('interested_user', array('question' => $question)) ?>
    </div>
 
    <h2><?php echo link_to($question->getTitle(), 'question/show?stripped_title='.$question->getStrippedTitle()) ?></h2>
    <div>asked by <?php echo link_to($question->getUser(), 'user/show?id='.$question->getUser()->getId()) ?> on <?php echo format_date($question->getCreatedAt(), 'f') ?></div>
    <div class="question_body">
      <?php echo truncate_text($question->getBody(), 200) ?>
    </div>
  </div>
<?php endforeach; ?>
 
<div id="question_pager">
  <?php echo pager_navigation($question_pager, $rule) ?>
</div>

次はaskeet/apps/frontend/modules/user/templates/showSuccess.php

<?php use_helper('Date') ?>
 
<div class="interested_block">
   <?php include_partial('interested_user', array('question' => $question)) ?>
</div>
 
<h2><?php echo $question->getTitle() ?></h2>

<div>asked by <?php echo link_to($question->getUser(), 'user/show?id='.$question->getUser()->getId()) ?> on <?php echo format_date($question->getCreatedAt(), 'f') ?></div>

<div class="question_body">
  <?php echo $question->getBody() ?>
</div>
 
<div id="answers">
<?php foreach ($question->getAnswers() as $answer): ?>
  <div class="answer">
    <?php echo $answer->getRelevancyUpPercent() ?>% UP <?php echo $answer->getRelevancyDownPercent() ?> % DOWN
    posted by <?php echo $answer->getUser()->getFirstName().' '.$answer->getUser()->getLastName() ?> 
    on <?php echo format_date($answer->getCreatedAt(), 'p') ?>
    <div>
      <?php echo $answer->getBody() ?>
    </div>
  </div>
<?php endforeach; ?>
</div>

で、確認。



よし、できてる。