[symfony] askeet 4日目
4日目です。
昨日までに作成した質問の一覧画面から質問の個別表示ページ
http://askeet/frontend_dev.php/question/show/id/1
にアクセスするとエラーになる。調べると show アクションもビューもない。
そこで actions.class.php に下記コードを追加
public function executeShow()
{
$this->question = QuestionPeer::retrieveByPk($this->getRequestParameter('id'));
$this->forward404Unless($this->question);
}
askeet/apps/frontend/modules/question/templates/showSuccess.php を作成する
<?php use_helper('Date') ?>
<div class="interested_block">
<div class="interested_mark">
<?php echo count($question->getInterests()) ?>
</div>
</div>
<h2><?php echo $question->getTitle() ?></h2>
<div class="question_body">
<?php echo $question->getBody() ?>
</div>
<div id="answers">
<?php foreach ($question->getAnswers() as $answer): ?>
<div class="answer">
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>
再度 http://askeet/frontend_dev.php/question/show/id/1 にアクセスすると表示できました。

URL からのパラメータの受け取り方
URL が http://askeet/frontend_dev.php/question/show/id/1 の場合
$id = $this->getRequestParameter('id')
これで $id=1 になる。
http://askeet/frontend_dev.php/question/show/id/1/myparam/myvalue
$param = $this->getRequestParameter('myparam');
これで $param = ‘myvalue’ になる。
テストデータの追加
answer テーブルにデータを追加するために askeet/data/fixtures/test_data.yml にチュートリアルにあるデータを追加して symfony コマンドを実行
symfony propel-load-data frontend
データ追加後の画面表示

追加した回答データが表示されている。
注意点は symfony propel-load-data コマンドを実行するとDBから一度データを全て削除して insert しなおすので各データの ID が変わります。そのために URL の /show/id/x の x の部分もデータをロードするたびに変わります。
モデルの変更
ユーザ名をビューで組み立てるのではなくモデルで組み立てる
askeet/lib/model/User.php
public function __toString()
{
return $this->getFirstName().' '.$this->getLastName();
}
askeet/frontend/modules/question/templates/showSuccess.php
posted by <?php echo $answer->getUser()->getFirstName().' '.$answer->getUser()->getLastName() ?>
という部分を下記に変更する
posted by <?php echo $answer->getUser() ?>
__toString というマジックメソッドにすることによりビューでは User クラスのインスタンスを echo するだけでフルネームが表示できるようになりました。
マジックメソッドに関しては過去のエントリを参照
PHP5 マジックメソッド
リファクタリング
ビューの showSuccess.php と listSuccess.php には重複している部分があります。
<div class="interested_block">
<div class="interested_mark">
<?php echo count($question->getInterests()) ?>
</div>
</div>
上記コードを askeet/apps/frontend/modules/question/templates/_interested_user.php というファイル名で作成して、
showSuccess.php と listSuccess.php の該当部分を下記コードに修正します。
<?php include_partial('interested_user', array('question' => $question)) ?>
この _interested_user.php のようなファイルをパーシャルといい、ファイル名の先頭はアンダースコアにして、ビューからインクルードするときはアンダースコアを入れずに指定します。第2引数にパーシャルに渡す引数を指定できます。パーシャルは HTML の共通化をするときに用いられます。
モデルの変更(テーブルにカラムを追加)
schema.yml の ask_question テーブルに下記の行を追加
interested_users: { type: integer, default: '0' }
下記コマンドを実行してテーブルを再作成
symfony propel-build-all
データを再度挿入
symfony propel-load-data frontend
(このやり方でいいのかな?間違っていたらコメントで教えてください)
追加したカラムに Interest テーブルにレコードが追加される度に更新されるようにする
askeet/lib/model/Interest.php
public function save($con = null)
{
$con = Propel::getConnection();
try
{
$con->begin();
$ret = parent::save($con);
// update interested_users in question table
$question = $this->getQuestion();
$interested_users = $question->getInterestedUsers();
$question->setInterestedUsers($interested_users + 1);
$question->save($con);
$con->commit();
return $ret;
}
catch (Exception $e)
{
$con->rollback();
throw $e;
}
}
上記コードはトランザクションを使っています。
テンプレートの変更
_interested_user.php
<?php echo count($question->getInterests() ?>
を
<?php echo $question->getInterestedUsers() ?>
に変更する
このままで質問を再表示させると interested_users カラムには何も入っていないので関心数が表示されません。そこで再度データを挿入しなおします。
symfony propel-load-data frontend
回答モデルにも同じことをする
これは繰り返しなので省略
関連する投稿
One comment
コメントをどうぞ
Additional comments powered by BackType
2astuteness…
…