SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

symfony入門

symfony入門(2):掲示板アプリケーション作成でsymfonyを理解しよう(前篇)

symfonyによる実践的なPHPアプリケーション開発


掲示板作成:データベースとの連携(3/3)

各種機能の実装:返信機能

 ここから、各種機能を実装していきます。今回は返信機能を追加します。

 返信機能を実装する際、リスト画面で親記事の配下に、返信記事を昇順で表示するために、やや処理が多くなります。

返信用ボタン:listSuccess.php

 親記事のID/TITLE/BODYフィールドの各値を、それぞれ「oya_id」「oya_title」「oya_body」としてフォームからcreateアクションへ送ります。これらを使用し、返信記事を作成します。「oya_id」には親記事のIDが渡されます(新規書き込み時は0でした)。

listSuccess.php(抜粋)
<div align="right">
<?php echo form_tag('bbsdata/create') ?>
<?php echo input_hidden_tag('oya_id', $bbsdata->getId()) ?>
<?php echo input_hidden_tag('oya_title', $bbsdata->getTitle()) ?>
<?php echo input_hidden_tag('oya_body', $bbsdata->getBody()) ?>
<?php echo submit_tag('返信') ?>
</form>
</div>

返信用フォーム:editSuccess.php

 parent_idにはhiddenでoya_idが渡されています。さらにタイトルと書き込み本体に親記事の内容が反映されるようにします。

editSuccess.php(抜粋)
<tr>
  <th>タイトル:</th>
<td>
<?php if ($sf_params->get('oya_title')): ?>
  <?php echo input_tag('title', 'Re: '.$sf_params->get('oya_title'), array (
  'size' => 20,
)) ?>
<?php else: ?>
  <?php echo object_input_tag($bbsdata, 'getTitle', array (
  'size' => 20,
)) ?>
<?php endif; ?>
</td>
</tr>
...
<tr>
  <th>内容:</th>
<td>
<?php if ($sf_params->get('oya_body')): ?>
  <?php echo textarea_tag('body', "> ".str_replace(
    "\n", "\n> ", $sf_params->get('oya_body')), array (
  'size' => '30x15',
)) ?>
<?php else: ?>
  <?php echo object_textarea_tag($bbsdata, 'getBody', array (
  'size' => '30x15',
)) ?>
<?php endif; ?>
</td>
</tr>

 また、「oya_title」が存在すれば(つまり返信の場合)タイトルに「Re: 」を、「oya_body」が存在すれば書き込みの改行文字後に引用符を付加してフォームに表示させています。

返信記事表示準備:executeListアクション

 当初決めたように、テーブルから特定の親記事ごとに関連づいた返信記事をまとめて持って来られるように、Criteriaオブジェクトを別個に設定しています。

actions.class.php(抜粋)
public function executeList ()
{
  $c = new Criteria();
  $c->add(BbsdataPeer::PARENT_ID, 0);
  $c->addDescendingOrderByColumn(BbsdataPeer::ID);
  $this->parent_bbsdatas = BbsdataPeer::doSelect($c);

  foreach($this->parent_bbsdatas as $parent)
  {
    $c_reply = new Criteria();
    $c_reply->add(BbsdataPeer::PARENT_ID, $parent->getId());
    $c_reply->addAscendingOrderByColumn(BbsdataPeer::ID);

    $no = 'threads'.$parent->getId();
    $this->{$no} = BbsdataPeer::doSelect($c_reply);
  }
}

 親記事用の$cの他に、返信記事用に$c_replyを設定しています。$c_replyでは、foreachループ内で親記事のIDを「parent_id」に持つ記事を昇順に抽出しています。また、テンプレートに返信記事オブジェクト「threads<親記事ID>」を渡しています(このオブジェクト名を設定するため、いったん変数名として$noを定義し、可変変数$this->{$no}を使用しています)。いささか長めのコードになりましたが、本来これはMVCの中のモデルが担当する部分であり、コントローラーに過ぎないアクションクラス内にあるべきものではありません。今はそのままアクション内に記述しましたが、後でまとめてモデルクラス内に移動します。

 Criteriaオブジェクトの詳細はPropelのマニュアルに記述されていますが、代表的なものを挙げておきます。

criteriaオブジェクトの操作
メソッド 意味
->add(<テーブル名>Peer::<大文字フィールド名>, 値, Criteria::<比較演算子記述(LIKE, EQUAL等)>) データの抽出条件を設定
->addAnd(Criteriaオブジェクト) 条件をandで追加
->addOr(Criteriaオブジェクト) 条件をorで追加
->addAscendingOrder(<テーブル名>Peer::<大文字フィールド名>) 対象となるフィールドで昇順にソート
->addDescendingOrder(<テーブル名>Peer::<大文字フィールド名>) 対象となるフィールドで降順にソート
->addGroupByColumn(<テーブル名>Peer::<大文字フィールド名>) 対象となるフィールドでグループ化

親記事と返信記事の表示:listSuccess.php

 親記事オブジェクト「parent_bbsdatas」と返信記事オブジェクト「threads<親記事ID>」を受け取り、foreachの2重ループで返信記事を親記事の下にまとめて表示します。返信記事はインデントして表示しています。

listSuccess.php(抜粋)
<?php foreach ($parent_bbsdatas as $bbsdata): ?>
…
<p><?php echo simple_format_text($bbsdata->getBody()) ?></p>
<br /><br />

<div align="right">
<?php echo form_tag('bbsdata/create') ?>
<?php echo input_hidden_tag('oya_id', $bbsdata->getId()) ?>
<?php echo input_hidden_tag('oya_title', $bbsdata->getTitle()) ?>
<?php echo input_hidden_tag('oya_body', $bbsdata->getBody()) ?>
<?php echo submit_tag('Reply') ?>
</form>
</div>

<?php $th = 'threads'.$bbsdata->getId() ?>

  <div style='margin-left: 20px'>
  <?php foreach ($$th as $reply): ?>
  <table>
  <thead>
  <tr>
    <th>Id</th><p><?php echo simple_format_text($reply->getBody()) ?></p>
  <br /><br />
  <?php endforeach; ?>
  </div>

<hr>

<?php endforeach; ?>

 これで、リスト画面は下図のような感じになります。

返信機能を追加したリスト画面
返信機能を追加したリスト画面

今回のまとめ

 ここまでで既に結構な量になってしまいましたが、今回はsymfonyとデータベースとの連携、scaffolding機能を紹介し、これを利用して掲示板アプリケーションをある程度の形まで整えました。次回は続けて掲示板にページャーや削除/検索機能を実装していき、また入力値の検証やセキュリティ対策、リファクタリング、不要な要素の整理、ビューの設定などを行う予定です。

参考文献(前回挙げたもの以外)

 Propelガイドの、Criteriaオブジェクトや関連するメソッドについての部分です。SQLを直接記述する方法なども載っています。

修正履歴

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
symfony入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 川北 季(カワキタ ミノル)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/837 2008/08/19 20:47

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー