はい、やってまいりました。へろへろaskeetのお時間です。
今日は「symfony advent calendar day four Refactoring」です。
さっそくチュートリアルに習ってレッツリファクタリングです。
さて、さくさく進めてまいりましょう。
質問に対しての回答の表示
http://askeet/frontend_dev.php/question/show/id/1
にアクセスすると質問の詳細が表示されます・・・と。
で、ここを質問に対する答えを追加するところにするわけですね。
ちなみに前にテンプレートをいぢっているので、チュートリアルにある画像とは違う画面になってると思います。
このアクションについて少し
apps/frontend/modules/question/actions/actions.class.phpのexecuteShowメソッドの説明ですね。
public function executeShow()
{
$this->question = QuestionPeer::retrieveByPk($this->getRequestParameter('id'));
$this->forward404Unless($this->question);
}
- $this->getRequestParameter('id')は、GET/POSTにかかわらずidという引数をとることができる。
- QuestionPeer::retrieveByPk()は、Questionsテーブルから、引数をPKとしてユニークなレコードを取得する。
- forward404Unless()は、取得したレコードが存在しない場合には404とする。
これだけのことを2行でできるなら楽なものですね。
showSuccess.php テンプレートの変更
じゃあテンプレートを変えてみましょうということで、チュートリアルに習って変更です。
注意のところに->getRelevancys()がうんちゃらとかありますが、チュートリアルのテンプレートにはないです。
で、ここが上の辺りで言ってる、
>訳注:「信頼性の合計」はコード中にないと思う SVNを見るとある
というあたりですね。
ひとまず、ここはそのまま進めておきましょう。
テストデータの追加
書いてあるとおりに、data/fixtures/test_data.ymlを編集するのですが、
内容を上書きじゃなくって追記です。注意しましょう。
モデルの変更 パート1
Userモデルにフルネームを取得するメソッドを実装しましょうね。
なるべく無駄がないように__toString()メソッドをオーバライドしましょう、ということです。
askeet/lib/model/User.phpに__toString()を実装したら、
apps/frontend/modules/question/templates/showSuccess.phpテンプレートがシンプルにできますよ、ということです。
メソッドを実装したら、テンプレートを編集いたしましょう。
同じことは繰り返さない
listSuccess.phpとshowSuccess.phpでコードが重複している部分があるので、ここをフラグメント(_interested_user.php)ととして定義して、再利用しましょう。
定義したフラグメントはデータアクセスをするので、呼び出す時にはinclude_partial()メソッドを使いましょうね、とふむふむ。
モデルの変更 パート2
新しく作ったフラグメントは$question->getInterests()を使うけど、これって人数を数える為だけならちょっとおおげさなので、質問に対する人数を表すカラムをテーブルにつけちゃいましょう。ということですね。
お手本に習って進めていきましょう。
config/schema.xmlの<table name="ask_question" phpName="Question">要素に以下を追加。
<column name="interested_users" type="integer" default="0" />
これでinteger型で初期値0のinterested_usersカラムを定義しているわけですね。
後は以下のコマンドを実行。
$ symfony propel-build-model $ symfony propel-build-sql $ mysql -u youruser -p askeet < data/sql/lib.model.schema.sql $ php batch/load_data.php
順に、モデルの生成、DDLの生成、DDLの実行、データのロードです。
ここまで行って、サイトを表示しても見た目は何も変わりません。念の為。
Interestオブジェクトのsave()メソッドの変更
Interestオブジェクトが保存される時に呼ばれるメソッド内でask_questionテーブルのinterested_usersの更新もさせましょうということですね。
チュートリアル通りにすすめます。
トランザクションで更新を安全に
を、きました。トランザクション処理です。
どんどん実用的になってきますね。
- $con = Propel::getConnection()でconnectionを取得
- $con->begin()でトランザクションを開始
- 例外が発生しなかったら$con->commit()、発生したら$con->rollback()
テンプレートの変更
ここまで実装できたらテンプレートを更新。
さっき作ったフラグメントを編集するだけですむから、変更忘れの可能性も少ないですね。という理にかなったお話です。
で、テンプレートを変更したなら、さっそく結果を表示してみたいところですが、ちょっと待って次を実践してからです。
変更点の正当性テスト
バッチを使ってデータをロードしなおしてみて、実装したInterest->save()メソッドがちゃんと動作しているかどうか確認しておきましょう。
ということでチュートリアルに習ってデータをロードしたら、ブラウザからaskeetを表示してみましょう。
何も変わってないみたいですけど、動作がちょっぴり合理的になったaskeetが表示されますね。
(ちなみにデータをロードしなおすとQuestionのIDが変わりますから注意です。)
回答にも同じ事を
じゃあcount($answer->getRelevancys())にも同じことすれば、もっと合理的ですよね。
あーなるほどねぇ、で$answer->getRelevancys()って何?ということなのですが、
ここがどうも先ほどSVNにはあるとか言ってた部分のようです。
何気に質問に対する投票の機能まで、あるってことです。高機能ですね。
ということなので、せっせとソースを変更です。
・・・で、ここまでやってみて何か不思議なことに気づいたんですが
lib/modelディレクトリに生成されたDTOに<?phpの閉じタグ?>がないですね・・・。
これってバグなのかな。怒られてはいないみたいですが。
ルーティング
質問の詳細を表示するのに使用するURLをidを使わないで質問のタイトルを使うようにしよう、ということです。
タイトルの別バージョンを作る
パラメタとして使用するタイトルを表現するカラムをQuestionモデルに追加します。
カスタムクラス
タイトルをパラメタとして使用できるように返還する為のメソッドを実装したクラス(myTools)を使って、違うモデルとかにも便利に使いまわしましょう。
libディレクトリに作ったクラスは必要なときに自動的に読み込まれますから、特にrequireする必要もないんですよ、ということです。
どんどんすすめます。
show アクションへのリンクを変更
チュートリアルにならって、テンプレートとアクションクラスを変更すると確かにURLがかわっています。
でも、これだとURLが<ルートディレクトリ>/question/stripped_title/<タイトル>となっているので、ここから/question/stripped_titleをとりたいのです。
ルーティングルールの変更
そして最後に
http://askeet/frontend_dev.php/question/show/stripped_title/what-shall-i-do-tonight-with-my-girlfriend
から
http://askeet/frontend_dev.php/question/what-shall-i-do-tonight-with-my-girlfriend
とする為の作業です。
apps/frontend/config/routing.ymlをチュートリアルに習って編集すると、URLが変わっています。
それではまた明日
今までに比べると結構濃い内容でした。
どんどんリファクタリングを進めて、モデルを変更していってもコマンドラインからモデルの変更、DDLの生成ができてしまうあたりとても便利ですね。
普通にソースを書いてとかやってるともっと時間がかかっているはずです。
他にもトランザクション制御やルーティング等、実践的な内容が増えてきました。
一応今日やったことは、
- 質問の詳細に、回答を表示するようにした。
- ユーザのフルネームを取得するメソッドを実装した。
- 質問に対する答えの数を取得する機能を合理的に動作するようにした。
- 回答に対する投票も同様に合理的に動作するようにした。
- 質問の詳細を表示するURLに質問のタイトルを使うようにした。
です。チュートリアルに習って今日の作業内容をコミットしたらタグをうっておきましょう。