Skip to content
Caution: You are browsing the legacy symfony 1.x part of this website.

symfony advent calendar day seven: model and view manipulation

Language

์ง€๋‚œ ์ค„๊ฑฐ๋ฆฌ

์ด์ œ ๋ฒŒ์จ 6์ผ์ด๋‚˜ ์ง€๋‚ฌ์Šต๋‹ˆ๋‹ค. ๋ช‡๋ช‡ ๋ถ„๋“ค์€ ์•„์ง ์šฐ๋ฆฌ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹ค์ง€๋„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ๋ถ„๋“ค์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์œ ์šฉํ•œ์ง€ ๊ทธ๋ ‡์ง€ ์•Š์€์ง€๋ฅผ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ œ๊ณตํ•˜๋Š” ํŽ˜์ด์ง€ ์ˆ˜๋กœ ํŒ๋‹จํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋ฉด์—์„œ ๋ณผ๋•Œ๋Š” askeet ์€ ๋‹จ์ˆœํžˆ ์งˆ๋ฌธ๋“ค ๋ชฉ๋ก๊ณผ ์งˆ๋ฌธ๋“ค์— ๋Œ€ํ•œ ๋‹ต๋ณ€๋“ค์„ ์ถœ๋ ฅํ•˜๊ณ , ์‚ฌ์šฉ์ž ์„ธ์…˜์„ ๋‹ค๋ฃจ๋Š” ์ •๋„์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ํŽ˜์ด์ง€ ์ˆ˜๋ฅผ ์ค‘์š”ํ•˜๊ฒŒ ์ƒ๊ฐํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ์‹ฌํฌ๋‹ˆ์—์„œ ํŽ˜์ด์ง€ ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๋Š” ๊ฒƒ์€ ์•„์ฃผ ์‰ฌ์šด ์ผ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ง„์งœ์ธ๊ฐ€์š”? ์ข‹์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ์ตœ๊ทผ ์ž…๋ ฅ๋œ ์งˆ๋ฌธ๋“ค๊ณผ ์ตœ๊ทผ ๋‹ต๋ณ€๋œ ์งˆ๋ฌธ๋“ค์„ ์ถœ๋ ฅํ•˜๊ณ , ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ํŽ˜์ด์ง€, ๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ์˜ ํŽ˜์ด์ง€๋งˆ๋‹ค ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฉ”๋‰ด๋ฅผ ๋‹ฌ์•„์„œ ์œ„ ๊ธฐ๋Šฅ๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ์ž‘์—…๋“ค์€ ํ•œ ์‹œ๊ฐ„๋„ ํ•œ ๊ฑธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์—, ๋ทฐ ์„ค์ •๊ณผ ์ด๋ฒˆ ํ•œ ์ฃผ์— ์–ด๋–ค ์ผ๋“ค์„ ํ•ด์™”๋Š”์ง€๋„ ํ•จ๊ป˜ ์‚ดํŽด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ค€๋น„๋˜์…จ๋‚˜์š”? ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ”„๋ฆฌํŽ™ํ† ๋ง

์ด์ œ question/templates/_list.php ์— ์žˆ๋Š” ํŽ˜์ด์ง€๊ฐ€ ๋‚˜๋‰œ ๋ชฉ๋ก๊ณผ ํŽ˜์ด์ง€ ๋ชฉ๋ก๊ฐ™์€ ๊ฒƒ๋“ค์„ ์ถ”๊ฐ€ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ฐ˜๋ณต์ ์ธ ์ผ์„ ์‹ซ์–ดํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŽ˜์ด์ง€ ๊ด€๋ จ๋œ ์ฝ”๋“œ๋ฅผ ์กฐ๊ฐ ํ…œํ”Œ๋ฆฟ์—์„œ ์‚ฌ์šฉ์ž ํ—ฌํผ ๋กœ ๋งŒ๋“ค๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ํ—ฌํผ๋Š” link_to() ๋‚˜ format_date() ๊ฐ™์ด ํ…œํ”Œ๋ฆฟ์—์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ PHP ํ•จ์ˆ˜๋“ค์ž…๋‹ˆ๋‹ค.

askeet/apps/frontend/lib/helper ์— GlobalHelper.php ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ๋‹ค์Œ์„ ์ž…๋ ฅํ•˜์‹ญ์‹œ์˜ค.

<?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
    $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;
}    

ํŽ˜์ด์ง€ ๋ชฉ๋ก ํ—ฌํผ๋Š” ์ด์ „์— ์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ณด๋‹ค ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋– ํ•œ ๋ผ์šฐํŒ… ๊ทœ์น™์ด๋ผ๋„ ์ ์šฉ์ด ๊ฐ€๋Šฅํ•˜๊ณ , ์ฒซ ํŽ˜์ด์ง€์ผ ๊ฒฝ์šฐ์—” '์ด์ „' ๋งํฌ๋ฅผ ํ‘œ์‹œํ•˜์ง€์•Š์œผ๋ฉฐ ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€์ผ ๊ฒฝ์šฐ์—๋„ '๋‹ค์Œ' ๋งํฌ๋ฅผ ํ‘œ์‹œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ ์šฐ๋ฆฌ๋Š” ๋„ค๊ฐ€์ง€ ์ด๋ฏธ์ง€ (first.gif, previous.gif, 'next.gif๊ทธ๋ฆฌ๊ณ last.gif`) ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋งํฌ๋“ค์ด ์ด์˜๊ฒŒ ๋ณด์—ฌ์ง€๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. askeet SVN ์ €์žฅ์†Œ ์—์„œ ์ด๋“ค ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด ๋ฐ›์œผ์‹ญ์‹œ์˜ค. ์•„๋งˆ ์—ฌ๋Ÿฌ๋ถ„๋“ค์€ ์ดํ›„์˜ ์—ฌ๋Ÿฌ๋ถ„ ์ž์‹ ์˜ ํ”„๋กœ์ ํŠธ์—์„œ ์œ„ ํ—ฌํผ๋ฅผ ์‚ฌ์šฉํ•˜์‹ค ์ˆ˜ ์žˆ์œผ์‹ค ๊ฒ๋‹ˆ๋‹ค.

question/templates/_list.php ์กฐ๊ฐ์— ์ด ํ—ฌํผ๋ฅผ ์‚ฌ์šฉํ•˜์‹œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ—ฌํผ ํŽ‘์…˜์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<?php use_helper('Text', 'Global') ?>
 
<?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>

์ด์ œ ์šฐ๋ฆฌ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ํ—ฌํผ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ๋•Œ๋ฌธ์— use_helper() ๋Œ€์‹  use_helper() ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•˜์‹ญ์‹œ์˜ค. Global ์ด๋ผ๋Š” ์ด๋ฆ„์€ GlobalHelper.php ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์—ฐ๊ฒฐ๋˜๋„๋ก ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜ ์ฃผ์†Œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๊ธฐ๋Šฅ์ด ์ •์ƒ์ž‘๋™ํ•˜๋Š”์ง€ ์‚ดํ‘œ๋ณด์‹ญ์‹œ์˜ค.

http://askeet/frontend_dev.php/

๊ฐœ์„ ๋œ ํŽ˜์ด์ง€ ๋ชฉ๋ก

์ตœ๊ทผ ์งˆ๋ฌธ ๋ชฉ๋ก

question ๋ชจ๋“ˆ์— recent ์•ก์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

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

๊ฐ„๋‹จํ•˜์ฃ ? ์šฐ๋ฆฌ๋Š” ์ตœ๊ทผ ์งˆ๋ฌธ๋“ค์˜ ๋ชฉ๋ก์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฒƒ์€ QuestionPeer ์˜ ๋ชซ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. -Peer ํด๋ž˜์Šค๋“ค์€ ํ•ด๋‹น ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋“ค์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. (์ž์„ธํ•œ ์‚ฌํ•ญ์€ ์˜จ๋ผ์ธ ๋ฌธ์„œ๋“ค ์ค‘ ๋ชจ๋ธ ๋ถ€๋ถ„ ์—์„œ ์‚ดํŽด๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.) ํ•˜์ง€๋งŒ getRecentPager() ํด๋ž˜์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. askeet/lib/model/QuestionPeer.php ํด๋ž˜์Šค๋ฅผ ์—ด๊ณ  ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

public static function getRecentPager($page)
{
  $pager = new sfPropelPager('Question', 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;
}

๋งˆ์ง€๋ง‰์œผ๋กœ ์˜ฌ๋ผ์˜จ ์งˆ๋ฌธ์ด ๋จผ์ € ์˜ฌ๋ผ์˜ค๋„๋ก ์ƒ์„ฑ์ผ์„ ๊ธฐ์ค€์œผ๋กœ ํ•œ ๋‚ด๋ฆผ์ฐจ์ˆœ ์ •๋ ฌ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์˜๋“œ๋Š” ๊ฐ์ฒด ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ํด๋ž˜์Šค ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— parent ๋Œ€์‹ ์— self ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค (์ฃผ - ์ด ๋ฉ”์˜๋“œ๋Š” ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ ์ดํ›„์— ->getRecentPager() ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋˜๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ QuestionPeer::getRecentPager() ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ $this ๋‚˜ parent ๋“ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค). doSelect() ๋Œ€์‹ ์— doSelectJoinUser ๋ฅผ ์‚ฌ์šฉํ•œ ์ด์œ ๋Š” ์งˆ๋ฌธํ•œ ์‚ฌ๋žŒ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด์—๋Š” ์งˆ๋ฌธ ๋ชฉ๋ก์„ ๋จผ์ € ์งˆ์˜ํ•˜๊ณ , ๊ฐ ์งˆ๋ฌธ์— ๋Œ€ํ•ด์„œ ์‚ฌ์šฉ์ž์˜ ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ๋‹ค์‹œ ์งˆ์˜ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. doSelectJoinUser() ๋ฉ”์˜๋“œ๋Š” ํ•˜๋‚˜์˜ ์งˆ์˜๋กœ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•ด๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์งˆ์˜ํ•˜์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

$question->getUser();

joinUser ๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์งˆ์˜์˜ ์ˆ˜๋ฅผ 1 + ์งˆ๋ฌธ ๊ฐฏ์ˆ˜์—์„œ ํ•˜๋‚˜๋กœ ์ค„์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๊ณ ๋งˆ์›Œํ•  ๊ฒƒ๋งŒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Propel ๋ฌธ์„œ๋“ค ์„ ๋ณด์‹œ๋ฉด ์ด๋Ÿฐ ๋ฉ‹์ง„ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ตœ๊ทผ ์งˆ๋ฌธ ๋ชฉ๋ก ํ…œํ”Œ๋ฆฟ์€ ๋ฉ”์ธํŽ˜์ด์ง€์— ์˜ฌ๋ผ๊ฐ€๋Š” ์งˆ๋ฌธ๋ชฉ๋ก๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. askeet/apps/frontend/module/question/templates/recentSuccess.php ํŒŒ์ผใ…‡๋ฅด ๋งŒ๋“ค๊ณ  ์•„๋ž˜ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

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

์ด์ œ ์™œ ์šฐ๋ฆฌ๊ฐ€ 5์ผ์งธ ์— ์งˆ๋ฌธ ๋ชฉ๋ก์„ ๋ฆฌํŒฉํ† ๋งํ•˜์˜€๋Š”์ง€ ์ดํ•ดํ•˜์‹ค ์ˆ˜ ์žˆ์œผ์‹ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ frontend/config/routing.yml ํŒŒ์ผ์—, 4์ผ์งธ ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ, recent_question ๊ทœ์น™์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

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

์ž ๊น๋งŒ์š”. question/_list ์กฐ๊ฐ ํŒŒ์ผ์€ question/list ๋ผ์šฐํŒ… ๊ทœ์น™์„ ์ด์šฉํ•˜์—ฌ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์—, ์ตœ๊ทผ ์งˆ๋ฌธ ๋ชฉ๋ก์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ผ์šฐํŒ… ๊ทœ์น™์„ ์กฐ๊ฐํŒŒ์ผ์— ์ธ์žํ˜•ํƒœ๋กœ ๋„˜๊ฒจ์ฃผ๋„๋ก ํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. recentSuccess.php ์˜ ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ€๋Šฅใ„น ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

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

list.php ์กฐ๊ฐํŒŒ์ผ์˜ ๋งˆ์ง€๋ง‰ ์ค„ ์—ญ์‹œ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

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

modules/question/templates/listSuccess.php ํŒŒ์ผ์—์„œ _list ์กฐ๊ฐํŒŒ์ผ์„ ํ˜ธ์ถœํ•˜๋Š” ๋ถ€๋ถ„์— ๋ผ์šฐํŒ… ๊ทœ์น™ ์ธ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋„ ์žŠ์ง€ ๋งˆ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

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

์บ์‰ฌ๋ฅผ ์‚ญ์ œํ•˜๋ฉด (์„ค์ •ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค) ๋์ž…๋‹ˆ๋‹ค.

์ด์ œ ์ตœ๊ทผ ์งˆ๋ฌธ๋ชฉ๋ก์„ ํ‘œ์‹œํ•˜์‹œ๋ ค๋ฉด ์•„๋ž˜ URL ๋กœ ์ ‘์†ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

http://askeet/recent

์ตœ๊ทผ ์งˆ๋ฌธ ๋ชฉ๋ก

์ตœ๊ทผ ๋‹ต๋ณ€ ๋ชฉ๋ก

๋ฐฉ๊ธˆ ํ•œ ๊ฒƒ๊ณผ ๊ฑฐ์˜ ๋น„์Šทํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋นจ๋ฆฌ ์ง„ํ–‰ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  • answer ๋ชจ๋“ˆ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    $ symfony init-module frontend answer
    
  • recent ์•ก์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    public function executeRecent()
    {
      $this->answer_pager = AnswerPeer::getRecentPager($this->getRequestParameter('page', 1));
    }   
  • AnswerPeer ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.

    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;
    }
  • 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://askeet/answer/recent
    

์ตœ๊ทผ ๋‹ต๋ณ€ ๋ชฉ๋ก

์ข€ ์ต์ˆ™ํ•ด์ง€์‹œ๊ณ  ๊ณ„์‹ ๊ฐ€์š”?

์ฐธ๊ณ : 4์ผ์งธ ์—๋„ ์ž์„ธํ•œ ๋‹ต๋ณ€์„ ์ถœ๋ ฅํ•˜๋Š”๋ฐ์— ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋˜๊ฑธ ๋ˆˆ์น˜์ฑ„์…จ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๊ฐ€ ์ตœ์†Œํ•œ ๋‘ ๊ตฐ๋ฐ์— ์“ฐ์˜€๊ธฐ๋•Œ๋ฌด๋„น, ์ด๋ฅผ _answer.php ์กฐ๊ฐํŒŒ์ผ๋กœ ์˜ฎ๊ธฐ๊ฒจ์„œ question/show ์™€ answer/recent ์— ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์‚ฌํ•ญ์€ askeet SVN ์ €์žฅ์†Œ ์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ํ”„๋กœํ•„

์งˆ๋ฌธ์— ์ถœ๋ ฅ๋˜๋Š” ์‚ฌ์šฉ์ž ์ด๋ฆ„์€, ์•„์ง ์ž‘์„ฑ๋˜์ง„ ์•Š์•˜์ง€๋งŒ, user/show ์•ก์…˜์œผ๋กœ ์—ฐ๊ฒฐ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ํŽ˜์ด์ง€๋Š” ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ํŽ˜์ด์ง€๋กœ, ์‚ฌ์šฉ์ž์— ๊ด€ํ•œ ๋ช‡๊ฐ€์ง€ ์ž์„ธํ•œ ์‚ฌํ•ญ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์ตœ๊ทผ ์งˆ๋ฌธ๋“ค๊ณผ ๋‹ต๋ณ€๋“ค์„ ์ถœ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฒซ๋ฒˆ์งธ๋กœ ํ•  ์ผ์€ ์•ก์…˜์„ ์ƒ์„ฑํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค.

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();
}

->getInterestsJoinQuestion() ๊ณผ ->getAnswerJoinQuestion() ๋ฉ”์˜๋“œ๋“ค์€ User ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ๋ฉ”์˜๋“œ๋“ค์ž…๋‹ˆ๋‹ค. askeet/lib/model/om/BaseUser.php ํด๋ž˜์Šค๋ฅผ ๋ณด์‹œ๋ฉด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์œผ์‹ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.

askeet/apps/frontend/modeules/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>

๋ฌผ๋ก  User ๊ฐ์ฒด์˜ ->getInterestsJoinQuestion() ์ด๋‚˜ ->getAnswersJoinQuestion(), getQuestion() ๋ฉ” ์—ฌ๊ธฐ์— ์ถœ๋ ฅ๋˜๋Š” ๊ฒฐ๊ณผ์˜ ๊ฐฏ์ˆ˜๋‚˜ ์ •๋ ฌ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๊ณ  ์‹ถ์œผ์‹ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์€ askeet/lib/model/User.php ํด๋ž˜์Šค์—์„œ ์ด๋“ค ๋ฉ”์˜๋“œ๋“ค์„ ์žฌ์ •์˜ (override) ํ•จ์œผ๋กœ์จ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€๋Š” ์—ฌ๊ธฐ์„œ ๊ณต๊ฐœํ•˜์ง„ ์•Š๊ฒ ์ง€๋งŒ ์˜ค๋Š˜์˜ ์†Œ์Šค์ฝ”๋“œ์—์„œ๋Š” ํ™•์ธ๊ฐ€๋Šฅํ•˜์‹ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ž ์ด์ œ ๋งˆ์ง€๋ง‰ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ฒซ๋ฒˆ์งธ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌด์—‡์„ ํ–ˆ๋Š”์ง€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

http://askeet/user/show/id/1

์‚ฌ์šฉ์ž ํ”„๋กœํ•„

์‚ฌ์šฉ์ž ํ”„๋กœํ•„์€ ์งˆ๋ฌธ์—์„œ๋„ ์—ฐ๊ฒฐ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. question/templates/showSuccess.php ์™€ /question/templates/_list.php ์˜ question_body ๋ฌธ๋‹จ์˜ ์ฒซ๋ถ€๋ถ„์— ๋‹ค์Œ ์ค„์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

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

_list.php ํŽ˜์ด์ง€์— Date ํ—ฌํผ ์‚ฌ์šฉ์„ ๋ช…์‹œํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ๋‹ฌ๊ธฐ

๊ธ€๋กœ๋ฒŒ ๋ ˆ์ด์•„์›ƒ์„ ์ˆ˜์ •ํ•˜์—ฌ ์ˆ˜ํ‰๋ฐ”๋ฅผ ๋„ฃ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐ”์—๋Š” ๋™์ ์ธ ๋‚ด์šฉ์ด ๋“ค์–ด๊ฐˆ ๊ฒƒ์ด์ง€๋งŒ, ๊ฐ๊ฐ์˜ ํ…œํ”Œ๋ฆฟ์— ๋“ค์–ด๊ฐ€๊ธฐ๋ณด๋‹ค๋Š” ๋ ˆ์ด์•„์›ƒ์˜ ํ•œ ์ž๋ฆฌ๋ฅผ ์ฐจ์ง€ํ•˜๋„๋ก ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ง๋ถ™์—ฌ์„œ ํ…œํ”Œ๋ฆฟ์— ๋ฐ” ๊ด€๋ จ ์ฝ”๋“œ๋ฅผ ๋„ฃ๋Š” ๊ฒƒ์€ ๋ฐ˜๋ณต์ ์ธ ์ž‘์—…์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋Ÿฐ๊ฒƒ ์‹ซ์–ดํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ž˜ ์•„์‹œ๊ฒ ์ฃ ?

๊ทธ๊ฒƒ์ด ์™œ ๋ฐ”๊ฐ€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋˜์–ด์•ผ ํ•˜๋Š”์ง€์— ๊ด€ํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋Š” ํ•˜๋‚˜์˜ ์•ก์…˜์˜ ๊ฒฐ๊ณผ๊ฐ€ (์˜ˆ๋ฅผ ๋“ค๋ฉด ํ…œํ”Œ๋ฆฟ ์‹คํ–‰์˜ ๊ฒฐ๊ณผ๋กœ HTML ์ฝ”๋“œ๊ฐ€ ํ˜•์„ฑ๋ฉ๋‹ˆ๋‹ค) ๋ณ€์ˆ˜ ํ˜•ํƒœ๋กœ ์ €์žฅ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜จ๋ผ์ธ ๋ฌธ์„œ์ค‘ ๋ทฐ ๋ถ€๋ถ„ ์— ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฌด์—‡์ด๊ณ , ์กฐ๊ฐํŒŒ์ผ๊ณผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ์ง€๊ฐ€ ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ ˆ์ด์•„์›ƒ์— ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ํ•˜๊ธฐ

๊ธ€๋กœ๋ฒŒ ๋ ˆ์ด์•„์›ƒ (askeet/apps/frontend/templates/layout.php) ์„ ์—ฝ๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„ ๊ธฐ์–ต๋‚˜์‹œ๋‚˜์š”?

<div id="content_bar">
  <!-- Nothing for the moment -->
  <div class="verticalalign"></div>
</div>

์ฃผ์„ ๋ถ€๋ถ„์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

<?php include_component_slot('sidebar') ?>

์ด์ƒ์ž…๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ์— ์–ด๋–ค ์•ก์…˜์ด ๋“ค์–ด๊ฐˆ์ง€ ์ •ํ•˜๊ธฐ

์šฐ๋ฆฌ๋Š” ๋‹จ์ˆœํ•œ ์ปดํฌ๋„ŒํŠธ ๋ณด๋‹ค๋Š” ์ข€ ๋” ๊ฐ•๋ ฅํ•œ ์ปดํฌ๋„ŒํŠธ ์Šฌ๋กฏ์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์Šฌ๋กฏ์€ ์–ด๋– ํ•œ ์•ก์…˜์—์„œ ํ˜ธ์ถœ๋˜์–ด์ง€๋А๋ƒ์— ๋”ฐ๋ผ์„œ ํ–‰๋™์ด ๋ณ€๊ฒฝ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. ๋ทฐ ์„ค์ •ํŒŒ์ผ (view.yml) ์—์„œ ์ปดํฌ๋„ŒํŠธ ์Šฌ๋กฏ์ด ์–ด๋– ํ•œ ์•ก์…˜๊ณผ ์—ฐ๊ฒฐ๋˜์–ด์ ธ์•ผ ํ•˜๋Š”์ง€๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

default:
  components:
    sidebar:      [sidebar, default]

์ด ์˜ˆ์ œ์—์„œ๋Š”, sidebar ๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ ์Šฌ๋กฏ์ด sidebar ๋ชจ๋“ˆ์˜ default ์•ก์…˜๊ณผ ์—ฐ๊ฒฐ๋˜๋„๋ก ์ •์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ทฐ ์„ค์ •์€ ์ „์ฒด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•ด ์ •์˜๋˜๊ฑฐ๋‚˜ (askeet/apps/frontend/config/ ๋””๋ ‰ํ† ๋ฆฌ) , ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ๋งŒ์„ ์œ„ํ•ด ์ •์˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (askeet/apps/frontend/modules/mymodule/config ๋””๋ ‰ํ† ๋ฆฌ). ์šฐ๋ฆฌ๋Š” ์ „์ฒด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•ด ์ •์˜ํ•˜๊ณ , ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์žฌ์ •์˜ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

askeet/apps/frontend/config/view.yml ํŒŒ์ผ์„ ์—ด๊ณ  ์œ„์˜ ์„ค์ • ๋‚ด์šฉ์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์˜จ๋ผ์ธ ๋ฌธ์„œ๋“ค์ค‘ ๊ด€๊ณ„๋œ ๋ถ€๋ถ„ ์—์„œ ์ข€ ๋” ์ž์„ธํ•œ ๋‚ด์šฉ์„ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

sidebar/default ์•ก์…˜๊ณผ ํ…œํ”Œ๋ฆฟ ์ž‘์„ฑํ•˜๊ธฐ

๋จผ์ € sidebar ๋ชจ๋“ˆ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

$ symfony init-module frontend sidebar

๋‹ค์Œ์œผ๋กœ default ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. askeet/apps/frontend/modules/sidebar/actions/ ๋””๋ ‰ํ† ๋ฆฌ์˜ actions.class.php ๋ฅผ components.class.php ๋กœ ์ˆ˜์ •ํ•˜๊ณ , ๋‚ด์šฉ์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

<?php 
 
class sidebarComponents extends sfComponents
{
  public function executeDefault()
  {
  }
}

์ปดํฌ๋„ŒํŠธ ๋ทฐ ์—ญ์‹œ ๋‹ค๋ฅธ ์•ก์…˜๋“ค์˜ ํ…œํ”Œ๋ฆฟ๊ณผ ๊ฐ™์€ ํ…œํ”Œ๋ฆฟ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ์ ์€ ์ด๋ฆ„์ง“๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ๋ทฐ๋Š” ์ผ๋ฐ˜ ํ…œํ”Œ๋ฆฟ์ฒ˜๋Ÿผ Success ๋“ฑ์œผ๋กœ ๋๋‚˜์ง€ ์•Š๊ณ  ์กฐ๊ฐํŒŒ์ผ์ฒ˜๋Ÿผ _ ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ askeet/apps/frontend/modules/sidebar/templates/_default.php ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  (๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ๋˜์ง€ ์•Š์„ indexSuccess.php ํŒŒ์ผ์„ ์ง€์šฐ์‹ญ์‹œ์˜ค) ๋‹ค์Œ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

<?php echo link_to('ask a new question', 'question/add') ?>
 
<ul>
  <li><?php echo link_to('popular questions', 'question/list') ?>
  <li><?php echo link_to('latest questions', 'question/recent') ?></li>
  <li><?php echo link_to('latest answers', 'answer/recent') ?></li>
</ul>

๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ askeet ์›น์‚ฌ์ดํŠธ์—์„œ ๋‹น์žฅ ๋„ค๋น„๊ฒŒ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ์—๋Ÿฌ๋ฅผ ๋งŒ๋‚˜์‹ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์—ฌ๋Ÿฌ๋ถ„์ธ ์„ค์ •๋“ค์ด ์บ์‰ฌ๋˜๋Š” ์•ˆ์ •๋ฒ„์ „ (production) ์˜ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋ณด์‹œ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์•ˆ์ •๋ฒ„์ „์—์„œ๋Š” ์ˆ˜์ •ํ•œ view.yml ์ด๋ผ๋Š” ์„ค์ •ํŒŒ์ผ์ด ์•„์ง ํšจ๋ ฅ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋ณด์‹œ๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด ์บ์‰ฌ๋ฅผ ์ง€์šฐ๋˜์ง€ ์•„๋‹ˆ๋ฉด ๊ฐœ๋ฐœ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

$ symfony clear-cache

๋˜๋Š”

http://askeet/frontend_dev.php/

๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฐ”๊ฐ€ ๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์ด๋“œ๋ฐ”

์ฐธ๊ณ : ์ด๊ฒƒ์€ ์•ˆ์ •๋ฒ„์ „์˜ ์ผ๋ฐ˜์ ์ธ ํšจ๊ณผ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์„ค์ •ํŒŒ์ผ ์ˆ˜์ •์ด ๋นˆ๋ฒˆํ•œ ๊ฐœ๋ฐœ๋„์ค‘์—๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ์‚ฌ์šฉํ•˜์‹œ๊ณ , ์„ค์ •ํŒŒ์ผ์ด ๋ฐ”๋€ ์ดํ›„์— ์•ˆ์ •๋ฒ„์ „์„ ํ†ตํ•ด ์›น์‚ฌ์ดํŠธ๋ฅผ ๋‘˜๋Ÿฌ๋ณด๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด ์บ์‰ฌ๋ฅผ ์ง€์šฐ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ข€ ๋” ์ž์„ธํ•œ ๋ทฐ ์„ค์ •

apps/config/ ์˜ view.yml ํŒŒ์ผ์„ ์ข€ ๋” ๋‘˜๋Ÿฌ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

default:
  http_metas:
    content-type: text/html; charset=utf-8

  metas:
    title:        symfony project
    robots:       index, follow
    description:  symfony project
    keywords:     symfony, project
    language:     en

  stylesheets:    [main, layout]

  javascripts:    []

  has_layout:     on
  layout:         layout

  components:
    sidebar:      [sidebar, default]

metas ๋ถ€๋ถ„์€ ์ „์ฒด ์‚ฌ์ดํŠธ์— ๊ด€ํ•œ ๋ฉ”ํƒ€ํƒœ๊ทธ๊ด€๋ จ ์„ค์ •์ด ๋ชจ๋‘ ๋“ค์–ด์žˆ์Šต๋‹ˆ๋‹ค. title ํ‚ค๋Š” ๋ธŒ๋ผ์šฐ์ € ์œˆ๋„์šฐ์— ์ถœ๋ ฅ๋  ์ œ๋ชฉ์ด ์ €์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ํƒ€์ดํ‹€์€ ๊ฒ€์ƒ‰์—”์ง„์ด ๊ฐ€์žฅ ๋จผ์ € ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ๊ต‰์žฅํžˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ askeet ์›น ์‚ฌ์ดํŠธ๋ฅผ ์ข€ ๋” ์ž˜ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  metas:
    title:        askeet! ask questions, find answers
    robots:       index, follow
    description:  askeet!, a symfony project built in 24 hours
    keywords:     symfony, project, askeet, php5, question, answer
    language:     en

ํ˜„์žฌ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจ ํ•˜์‹ญ์‹œ์˜ค. ๋งŒ์•ฝ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์•ˆ์ •๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ณ  ๊ณ„์‹œ๋ฉฐ ์บ์‰ฌ๋ฅผ ์ง€์šฐ์‹œ์ง€ ์•Š์œผ์‹  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์œˆ๋„์šฐ ์ œ๋ชฉ

์ฐธ๊ณ : ํ”„๋กœ์ ํŠธ ํŽ˜์ด์ง€์˜ ๊ธฐ๋ณธ ์ œ๋ชฉ ์ด์™ธ์—๋„, ์‹ฌํฌ๋‹ˆ๋Š” robots.txt ์™€ favicon.ico ๋ฅผ ์›น ๋””๋ ‰ํ† ๋ฆฌ (askeet/web/) ์— ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋“ค๋„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

์ฐธ๊ณ : ๊ฐ ํŽ˜์ด์ง€๋งˆ๋‹ค ํŽ˜์ด์ง€ ์ œ๋ชฉ์„ ๋ฐ”๊พธ์…”์•ผ ํ• ์ง€๋„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ๊ฐ ๋ชจ๋“ˆ๋งˆ๋‹ค view.yml ์„ค์ •ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์…”์„œ ํ•˜์‹ค์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์–ด๋””๊นŒ์ง€๋‚˜ ํŽ˜์ด์ง€ ์ œ๋ชฉ์ด ์ •์ ์ธ ๊ฒƒ์€ ๋งˆ์ฐฌ๊ฐ€์ง€ ์ž…๋‹ˆ๋‹ค. ->setTitle() ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•˜์‹œ๋ฉด ๋™์ ์œผ๋กœ ์ œ๋ชฉ์„ ์„ค์ •ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์˜จ๋ผ์ธ ๋ฌธ์„œ์ค‘ ๋ทฐ ์„ค์ • ๋ถ€๋ถ„ ์„ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค.

  [php]
  $this->getResponse()->setTitle($title);

์ง€๋‚œ ์ค„๊ฑฐ๋ฆฌ

์ด์ œ 7์ผ์งธ์ด๋‹ˆ, ์ž ์‹œ ๋ฉˆ์ถฐ์„œ ๊ทธ๋™์•ˆ ์šฐ๋ฆฌ๊ฐ€ ๋ฌด์—‡์„ ํ•ด ์™”๋Š”์ง€ ์‚ดํŽด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ์˜ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ํฌํ•จํ•ด์„œ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ์•ก์…˜๋“ค์ด ๋ฌด์—‡์ด ์žˆ๋Š”์ง€ ๊ฐ™์€ ๊ฒƒ๋“ค์— ๋Œ€ํ•ด์„œ ๊ธฐ๋ก์„ ๋‚จ๊ฒจ๋‘˜ ์ข‹์€ ๊ธฐํšŒ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์‹ค, ์—ฌ๋Ÿฌ๋ถ„์€ ์ฝ”๋”ฉ์„ ํ•˜๊ณ  ์žˆ๋Š” ๋™์•ˆ์— ๋ฌธ์„œ๋ฅผ ๋‚จ๊ฒจ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๊ฐ๊ฐ์˜ ๋ฉ”์˜๋“œ์— PHP doc ์Šคํƒ€์ผ๋กœ ์ฃผ์„์„ ๋‹จ๋‹ค๋˜๊ฐ€ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ž…๋‹ˆ๋‹ค. ์‹ฌํฌ๋‹ˆ ํ”„๋กœ์ ํŠธ๋Š” ๊ฐ ๋ฉ”์˜๋“œ๋‚˜ ํ•จ์ˆ˜๋“ค์˜ ์ด๋ฆ„์ด ๊ทธ๊ฒƒ์ด ํ•˜๋Š”์ผ์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์ œ๊ณตํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์˜๋“œ๋“ค์ด ์งง๊ณ  ๋งค์šฐ ์ฝ๊ธฐ ํŽธํ•˜๊ฒŒ ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค. ๋งŽ์€ ๊ฒฝ์šฐ์—, ํ…œํ”Œ๋ฆฟ๋“ค์€ foreach ์™€ if ๊ตฌ๋ฌธ๋งŒ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ํŒŒ์•…ํ•˜๊ธฐ๊ฐ€ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด askeet SVN ์ €์žฅ์†Œ ์˜ ์ฝ”๋“œ๋“ค์ด ์ฃผ์„์„ ๋งŽ์ด ํฌํ•จํ•˜๊ณ  ์žˆ์ง€ ์•Š์€ ์ด์œ ์ž…๋‹ˆ๋‹ค. ๋ง๋ถ™์—ฌ์„œ 7์‹œ๊ฐ„๋™์•ˆ ์šฐ๋ฆฌ๊ฐ€ ๋ฌด์—‡์„ ํ–ˆ๋Š”์ง€์— ๋Œ€ํ•ด์„œ ์„ค๋ช…์„ ์ž‘์„ฑํ•˜๊ธฐ๋„ ํ–ˆ๊ตฌ์š”.

์•„ ์ด์ œ ERD ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ERD

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์•ก์…˜๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

answer/
  recent
question/
  list
  show
  recent
sidebar/
  default (component)
user/
  show
  login
  logout
  handleErrorLogin

๋ชจ๋ธ๋“ค์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฉ”์˜๋“œ๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Anwser()
  getRelevancyUpPercent()
  getRelevancyDownPercent()
AnswerPeer::
  getRecentPager()
Interest->
  save()
Question->
  setTitle()
QuestionPeer::
  getQuestionFromTitle()
  getHomepagePager()
  getRecentPager()
Relevancy
  save()
User->
  __toString()
  setPassword()

myUser->
  signIn()
  signOut()
  getSubscriberId()
  getSubscriber()
  getNickName()

๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž ๋„๊ตฌ๋“ค๊ณผ ์‚ฌ์šฉ์ž ํผ๊ฐ’ ํ™•์ธ ํด๋ž˜์Šค๋Š” askeet/apps/frontend/lib/ ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ์Šต๋‹ˆ๋‹ค.

7์‹œ๊ฐ„์น˜๊ณค ๋‚˜์˜์ง€ ์•Š์ฃ ?

๋‚ด์ผ ์ด ์‹œ๊ฐ„์—

์˜ค๋Š˜์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ˆ˜์ •์ด ๋งŽ์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋˜ํ•œ ๋น ๋ฅด๊ฒŒ ์ง„ํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์‚ฌ์šฉ์ž-์ปดํ“จํ„ฐ ์ƒํ˜ธ์ž‘์šฉ๊ฐ„์— AJAX ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ๋ชจ๋“  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด์ผ์€ AJAX ๋ฅผ ์ด์šฉํ•ด์„œ ๋กœ๊ทธ์ธํ•˜๊ณ  ์งˆ๋ฌธ์— ๋Œ€ํ•œ ํ™๋ฏธ๋„๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋†“์น˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค!

์˜ค๋Š˜์˜ ๋ชจ๋“  ์ฝ”๋“œ๋Š” askeet SVN ์ €์žฅ์†Œ ์—์„œ release_day_7 ํƒœ๊ทธ๋กœ ๋‹ค์šด๋กœ๋“œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. askeet ๋ฉ”์ผ๋ง ๋ฆฌ์ŠคํŠธ ์—์„œ ๊ด‘์†๋ณด๋‹ค ๋น ๋ฅธ ์†๋„๋กœ ์งˆ๋ฌธ๋“ค์„ ๋‹ต๋ณ€ํ•ด๋“œ๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.