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