Practical symfony 6日目

#### Practical symfony 6日目(http://www.symfony-project.org/jobeet/1_4/Doctrine/ja/06)

#### 検索条件を設定する
> notepad .\apps\frontend\modules\job\actions\actions.class.php
$query = Doctrine_Query::create()
	->from('JobeetJob job')
	->where('job.created_at > ?', date('Y-m-d H:i:s', time() - (86400 * 30)));
$this->jobeet_jobs = $query->execute();

#### ログを確認
> notepad .\log\frontend_dev.log

#### どうやら元のコードの変数名を変えても勝手に j という名前にされる模様。
#### モデルの修正
> notepad .\lib\model\doctrine\JobeetJob.class.php
	public function save(Doctrine_Connection $connection = null)
	{
		if ($this->isNew() && !$this->getExpiresAt())
		{
			$now = $this->getCreatedAt() ? $this->getDateTimeObject('created_at')->format('U') : time();
			$this->setExpiresAt(date('Y-m-d H:i:s', $now + 86400 * 30));
		}
		
		return parent::save($connection);
	}

#### コントローラーの修正
> notepad .\apps\frontend\modules\job\actions\actions.class.php
		$query = Doctrine_Query::create()
			->from('JobeetJob job');
			->where('(job.expires_at is null) or (job.expires_at > ?)', date('Y-m-d H:i:s', time()));
		$this->jobeet_jobs = $query->execute();
#### null なら表示できるようにしてみたけど expires_at に 2010-10-10 00:00:00 が入っちゃってるから全部みえない。

#### fixture の修正(前はインデント崩れてたかも!?)
> notepad .\data\fixtures\jobs.yml
JobeetJob:
  job_sensio_labs:
    JobeetCategory: programming
    type:         full-time
    company:      Sensio Labs
    logo:         sensio-labs.gif
    url:          http://www.sensiolabs.com/
    position:     Web Developer
    location:     Paris, France
    description:  |
      You've already developed websites with symfony and you want to work
      with Open-Source technologies. You have a minimum of 3 years
      experience in web development with PHP or Java and you wish to
      participate to development of Web 2.0 sites using the best
      frameworks available.
    how_to_apply: |
      Send your resume to fabien.potencier [at] sensio.com
    is_public:    true
    is_activated: true
    token:        job_sensio_labs
    email:        job@example.com
    expires_at:   '2012-10-10'
  
  job_extreme_sensio:
    JobeetCategory:  design
    type:         part-time
    company:      Extreme Sensio
    logo:         extreme-sensio.gif
    url:          http://www.extreme-sensio.com/
    position:     Web Designer
    location:     Paris, France
    description:  |
      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
      eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
      enim ad minim veniam, quis nostrud exercitation ullamco laboris
      nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
      in reprehenderit in.
      
      Voluptate velit esse cillum dolore eu fugiat nulla pariatur.
      Excepteur sint occaecat cupidatat non proident, sunt in culpa
      qui officia deserunt mollit anim id est laborum.
    how_to_apply: |
      Send your resume to fabien.potencier [at] sensio.com
    is_public:    true
    is_activated: true
    token:        job_extreme_sensio
    email:        job@example.com
    expires_at:   '2012-10-10'
  
  expired_job:
    JobeetCategory: programming
    company:        Sensio Labs
    position:       Web Developer
    location:       Paris, France
    description:    Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    how_to_apply:   Send your resume to lorem.ipsum [at] dolor.sit
    is_public:      true
    is_activated:   true
    created_at:     '2005-12-01 00:00:00'
    token:          job_expired
    email:          job@example.com

#### EOF ####

#### データを読み直す
> symfony doctrine:data-load

#### 確認
> mysql --user=root --password=HiMiTsu
mysql> use jobeet
Database changed
mysql> SELECT `position`, `created_at`, `expires_at` FROM `jobeet_job`;
+---------------+---------------------+---------------------+
| position      | created_at          | expires_at          |
+---------------+---------------------+---------------------+
| Web Developer | 2011-02-22 13:30:19 | 2012-10-10 00:00:00 |
| Web Designer  | 2011-02-22 13:30:19 | 2012-10-10 00:00:00 |
| Web Developer | 2005-12-01 00:00:00 | 2005-12-31 00:00:00 |
+---------------+---------------------+---------------------+
3 rows in set (0.00 sec)

#### 設定の追加
> notepad .\apps\frontend\config\app.yml
# You can find more information about this file on the symfony website:
# http://www.symfony-project.org/reference/1_4/en/11-App

# default values
all:
  active_days: 30

#### EOF ####

#### 設定を使うようにコードを修正
> notepad .\lib\model\doctrine\JobeetJob.class.php
if ($this->isNew() && !$this->getExpiresAt())
{
	$now = $this->getCreatedAt() ? $this->getDateTimeObject('created_at')->format('U') : time();
	$this->setExpiresAt(date('Y-m-d H:i:s', $now + (86400 * sfConfig::get('app_active_days'))));
}

return parent::save($connection);

#### もしプロジェクト規模の設定が必要な場合は .\config\app.yml を作成する。

#### model にコードを移す
> notepad .\lib\model\doctrine\JobeetJobTable.class.php
	public function getActiveJobs()
	{
		$query = $this->createQuery('j')->where('j.expires_at > ?', date('Y-m-d H:i:s', time()));
		
		return $query->execute();
	}
> notepad .\apps\frontend\modules\job\actions\actions.class.php
	$this->jobeet_jobs = Doctrine_Core::getTable('JobeetJob')->getActiveJobs();

#### 有効期限でソートする
> notepad .\lib\model\doctrine\JobeetJobTable.class.php
	$query = $this->createQuery('j')->where('j.expires_at > ?', date('Y-m-d H:i:s', time()))->orderBy('j.expires_at DESC');
	
	return $query->execute();

#### カテゴリーの取得
> notepad .\lib\model\doctrine\JobeetCategoryTable.class.php
	public function getWithJobs()
	{
		$query = $this->createQuery('c')->leftJoin('c.JobeetJobs j')->where('j.expires_at > ?', date('Y-m-d H:i:s', time()));
		
		return $query->execute();
	}

#### controller を修正
> notepad .\apps\frontend\modules\job\actions\actions.class.php
	$this->categories = Doctrine_Core::getTable('JobeetCategory')->getWithJobs();

#### view も修正
> notepad .\apps\frontend\modules\job\templates\indexSuccess.php
	<?php foreach ($categories as $category): ?>
		<div class="category_<?php echo Jobeet::slugify($category->getName()) ?>">
			<div class="category">
				<div class="feed">
					<a href="">Feed</a>
				</div>
				<h1><?php echo $category ?></h1>
			</div>
			
			<table class="jobs">
				<?php foreach ($category->getActiveJobs() as $i => $job): ?>
					<tr class="<?php echo fmod($i, 2) ? 'even' : 'odd' ?>">
						<td class="location">
							<?php echo $job->getLocation() ?>
						</td>
						<td class="position">
							<?php echo link_to($job->getPosition(), 'job_show_user', $job) ?>
						</td>
						<td class="company">
							<?php echo $job->getCompany() ?>
						</td>
					</tr>
				<?php endforeach; ?>
			</table>
		</div>
	<?php endforeach; ?>

#### またモデルを修正
> notepad .\lib\model\doctrine\JobeetCategory.class.php
	public function getActiveJobs()
	{
		$query = Doctrine_Query::create()->from('JobeetJob j')->where('j.category_id = ?', $this->getId());
		
		return Doctrine_Core::getTable('JobeetJob')->getActiveJobs($query);
	}

> notepad .\lib\model\doctrine\JobeetJobTable.class.php
	public function getActiveJobs(Doctrine_Query $query = null)
	{
		if (is_null($query))
		{
			$query = Doctrine_Query::create()->from('JobeetJob j');
		}
		
		$query->andWhere('j.expires_at > ?', date('Y-m-d H:i:s', time()))->addOrderBy('j.expires_at DESC');
		
		return $query->execute();
	}

#### ブラウザで確認

#### 10件に絞る
> notepad .\lib\model\doctrine\JobeetCategory.class.php
	public function getActiveJobs($max = 10)
	{
		$query = Doctrine_Query::create()->from('JobeetJob j')->where('j.category_id = ?', $this->getId())->limit($max);
		
		return Doctrine_Core::getTable('JobeetJob')->getActiveJobs($query);
	}

#### 件数を設定可能に変更
> notepad .\apps\frontend\modules\job\templates\indexSuccess.php
<?php foreach ($category->getActiveJobs(sfConfig::get('app_max_jobs_on_homepage')) as $i => $job): ?>

> notepad .\apps\frontend\config\app.yml
  max_jobs_on_homepage: 10


#### fixture ファイルの修正
> notepad .\data\fixtures\jobs.yml
  
# Starts at the beginning of the line (no whitespace before)
<?php for ($i = 100; $i <= 130; $i++): ?>
  job_<?php echo $i ?>:
    JobeetCategory: programming
    company:      Company <?php echo $i."\n" ?>
    position:     Web Developer
    location:     Paris, France
    description:  Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    how_to_apply: |
      Send your resume to lorem.ipsum [at] company_<?php echo $i ?>.sit
    is_public:    true
    is_activated: true
    token:        job_<?php echo $i."\n" ?>
    email:        job@example.com
<?php endfor ?>

#### EOF ####

#### データの作り直し
> symfony doctrine:data-load
>> doctrine  Loading data fixtures from "Y:\Storage\jobeet\data/fixtures"


  SQLSTATE[HY000]: General error: 1364 Field 'expires_at' doesn't have a default value

#### エラーになってるじゃん。
#### 3日目のスキーマの定義を見直し、こうか?
> notepad .\config\doctrine\schema.yml
    # notnull==true means nullable==false
    # so notnull==false means nullable==true
    expires_at:   { type: timestamp, notnull: false, default: null }
> symfony doctrine:build --all --no-confirmation
> symfony doctrine:data-load

> mysql --user=root --password=HiMiTsu
mysql> use jobeet
Database changed
mysql> SELECT `position`, `created_at`, `expires_at` FROM `jobeet_job`;
+---------------+---------------------+---------------------+
| position      | created_at          | expires_at          |
+---------------+---------------------+---------------------+
| Web Developer | 2011-02-22 19:27:58 | 2012-10-10 00:00:00 |
| Web Designer  | 2011-02-22 19:27:58 | 2012-10-10 00:00:00 |
| Web Developer | 2005-12-01 00:00:00 | NULL                |
| Web Developer | 2011-02-22 19:27:58 | NULL                |
| Web Developer | 2011-02-22 19:27:58 | NULL                |
| Web Developer | 2011-02-22 19:27:58 | NULL                |

#### んー、.\lib\model\doctrine\JobeetJob.class.php::save(...) が効いてないっぽい...
#### 修正し間違えてた!! メソッドの最初の行に return 書いてあった--;

> symfony doctrine:data-load
mysql> SELECT `position`, `created_at`, `expires_at` FROM `jobeet_job`;
+---------------+---------------------+---------------------+
| position      | created_at          | expires_at          |
+---------------+---------------------+---------------------+
| Web Developer | 2011-02-22 19:37:06 | 2012-10-10 00:00:00 |
| Web Designer  | 2011-02-22 19:37:06 | 2012-10-10 00:00:00 |
| Web Developer | 2005-12-01 00:00:00 | 2005-12-31 00:00:00 |
| Web Developer | 2011-02-22 19:37:06 | 2011-03-24 19:37:06 |
| Web Developer | 2011-02-22 19:37:06 | 2011-03-24 19:37:06 |

#### さっきの schema.yml の修正は要らなかった。

#### 有効期限切れの URL の確認
#### http://jobeet.localhost/frontend_dev.php/job/sensio-labs/paris-france/37/web-developer-expired
#### http://jobeet.localhost/frontend_dev.php/job/sensio-labs/paris-france/37/web-developer
#### 最後の -expired は何だ??

#### routing の修正
> notepad .\apps\frontend\config\routing.yml
  options:
    model: JobeetJob
    type: object
    method_for_query: retrieveActiveJob
    allow_empty: false

#### model も修正
> notepad .\lib\model\doctrine\JobeetJobTable.class.php
	public function retrieveActiveJob(Doctrine_Query $query)
	{
		# ここでいきなり出てきてる a ってなんだ??
		$query->andWhere('a.expires_at > ?', date('Y-m-d H:i:s', time()));
		
		return $query->fetchOne();
	}

#### とりあえず有効期限が切れているページだけ 404 になるのを確認(500 なら何か本当に間違ってる)
#### 6日目終了。謎が増えてきたのと嫌な部分もいろいろ見えてきた。
#### そういえば今までメモり忘れてたけどコミットする
> svn commit -m "Day 6: More with the Model completed"