symfony askeet Day 9
- 質問と答えにリッチテキストを使えるようにする
- すべてのIDを隠す
- ルーティング
質問と答えにリッチテキストを使えるようにする
MarkdownというものはマークアップフォーマットをHTMLに変換するものらしい…
wikiとかはてな文法のようなものでしょうか。
それを使うためにはPHP Markdownを入れろとのことなので入れる。
http://www.michelf.com/projects/php-markdown/
zipファイルを解凍してmarkdown.phpを取り出して
askeet/libに入れる。
これで、後はrequire_onceで呼び出せばおk。
ただ、その都度markdown.phpで変換するとサーバに負荷が掛かるので
変換したものをDBに保存することにする。
ということでschema.ymlに追加する。
html_body: { type: longvarchar }
追加するとこうなる。
ask_question: _attributes: { phpName: Question, idMethod: native } id: { type: integer, required: true, primaryKey: true, autoIncrement: true } user_id: { type: integer, foreignTable: ask_user, foreignReference: id } title: { type: longvarchar } body: { type: longvarchar } interested_users: { type: integer, default: 0 } html_body: { type: longvarchar } stripped_title: { type: varchar(255) } _uniques: unique_stripped_title: [stripped_title] created_at: ~ updated_at: ~
追加したら、モデルを再構築して
symfony propel-build-model
SQL文作って
symfony propel-build-sql
SQLを更新する
symfony propel-insert-sql
setBodyが呼ばれたら問答無用で変換する。
askeet/lib/model/Question.phpにこれを追加する。
public function setBody($v)
{
parent::setBody($v);
require_once('markdown.php');
// HTMLタグを外す
$v = htmlentities($v,ENT_QUOTES,'UTF-8');
$this->setHtmlBody(markdown($v));
}
これでXSS対策もしつつ変換も行える。
すべてのIDを書く
IDとnicknameは対になっているんだから
http://askeet.localhost/user/show/id/8
じゃなくて
http://askeet.localhost/user/crazyup
にしたいという話です。
まずはアクションを変更する
場所:askeet/apps/frontend/modules/user/
public function executeShow() { $this->subscriber = UserPeer::retrieveByNickname($this->getRequestParameter('nickname')); $this->forward404Unless($this->subscriber); $this->interests = $this->subscriber->getInterestsJoinQuestion(); $this->answers = $this->subscriber->getAnswersJoinQuestion(); $this->questions = $this->subscriber->getQuestions(); }
モデルも修正する
場所:askeet/lib/model/UserPeer.class.php
public static function retrieveByNickname($nickname)
{
$c = new Criteria();
$c->add(self::NICKNAME,$nickname);
return self::doSelectOne($c);
}
リンクも直す
リンクを直すためにテンプレートを変更する。
場所:askeet/apps/frontend/modules/question/templates/showSuccess.php
<div>asked by <?php echo link_to($question->getUser(), 'user/show?nickname='.$question->getUser()->getNickname()) ?> on <?php echo format_date($question->getCreatedAt(), 'f') ?></div>
場所:askeet/apps/frontend/modules/question/templates/_list.php
<div>asked by <?php echo link_to($question->getUser(), 'user/show?nickname='.$question->getUser()->getNickname()) ?> on <?php echo format_date($question->getCreatedAt(), 'f') ?></div>
場所:askeet/apps/frontend/modules/answer/templates/recentSuccess.php
posted by <?php echo link_to($answer->getUser(),'user/show?nickname='.$answer->getUser()->getNickname()) ?> on <?php echo format_date($answer->getCreatedAt(),'p') ?>
ほげっとなおしたら次。
ルーティング
いい機会だから全部設定しちゃおうぜとaskeetが言っているのでやることに。
場所:askeet/apps/frontend/config/routing.yml
# question question: url: /question/:stripped_title param: { module: question, action: show } recent_questions: url: /question/recent/:page param: { module: question, action: recent, page: 1 } popular_questions: url: /index/:page param: { module: question, action: list } add_question: url: /add_question param: { module: question, action: add } # user login: url: /login param: { module: user, action: login } logout: url: /logout param: { module: user, action: logout } user_profile: url: /user/:nickname param: { module: user, action: show } # default rules homepage: url: / param: { module: question, action: list } default_symfony: url: /symfony/:action/* param: { module: default } default_index: url: /:module param: { action: index } default: url: /:module/:action/*
ルーティングをするといいことがあって
そうすると
posted by <?php echo link_to($answer->getUser(),'@user_profile?nickname='.$answer->getUser()->getNickname()) ?> on <?php echo format_date($answer->getCreatedAt(),'p') ?>
こんな風に呼び出せる。
user/showが@user_profileで呼び出せる。
これは確かに便利。