ネット大喜利 ODON – Ogiri Dynamic Operation Network

實松アウトプット: 作るもの Ogiri Dynamic Operation Network http://sane.justblog.jp/blog/2007/09/ogiri_dynamic_o_666f.html
で書いたネット大喜利のシステムが動くようになりました。

ODON – Ogiri Dynamic Operation Network
http://odon.zapto.org/

まだ実用には程遠いですがCakePHPで作った一つ目のアプリということでリリース。

ボケましーんと比較した特長

  • 名前欄にトリップ実装
  • 自分の投稿したボケ、投票したボケを見て修正できる(現在はクッキーあり限定)
  • お題とお題の間のインターバルを管理人が設定可能
  • 不正なフォームからの投稿を拒否
  • 過去ログが読みやすい

実用するには要改善な点

  • IPアドレスで多重投稿規制しているのでDocomoは投稿投票し放題
  • 文字コードがUTF-8なので読めない携帯が多い
  • 残り時間はカウントダウンしたい
  • 無造作にSQLを投げまくってるので必要なものを必要なだけとってくるようにする
  • 現状毎回すべて動的にDBから生成しているのでキャッシュを有効活用したい
  • 過去ログ検索機能
  • 結果をxmlやjson等で出力
  • クッキーを受け入れない場合のセッションIDの扱いについて理解不足

これから数回にわたって間違って理解していたことや自分なりのCakephpやBakeの使い方を書いてみます。1.2系です。

広告

アソシエーション確認のコントローラとビュー

テストデータを作ったあとに、コントローラとビューを作りました。関連テーブルからちゃんと引っ張れているかどうかの確認です。

controllers/subjects_controller.php

<?php
loadModel("Subject");
class SubjectsController extends AppController{
       public $uses = null;
       function view($id = null) {
               $dao = new Subject();
               $this->set('subject', $dao->findById($id));
       }
}

views/subjects/view.thtml

<?php print_r($subject);?>

ボケ、コメント、投票にも同様に暫定のコントローラとビューを作りました。

http://path/to/subjects/view/2
等のURLを叩くと、関連付けたテーブルからきちんとデータを引っ張れていました。よしよし。

ただ、お題とボケ、ボケと投票、お題とコメントは全て1対多で紐付けてありますが、お題と投票が1対多になるのは二段階での紐付けなのでデフォルトだと引っ張れてきていません。逆もまた然りでこのままだとお題テーブルしか必要ないときでも一段階掘り進んじゃうのかもしれません。ここはあとで要見直しです。

また、イマイチわかっていなかったところ、コントローラーからビューにデータを受け渡す際どうするのか、についてのマニュアルの記述
> set() で1度設定すると、ビューの中で変数が使用できるようになります。コントローラで set(‘color’, ‘blue’) を実行すると、ビューの中で、 $color 変数が使用できるようになります。
この記述がようやくピンと来ました。コントローラでセットした変数をペタペタ貼るなり展開するなりのイメージを持てばいいのね、ビューで。

モデルにリレーションだけ入れた

これでいいはず、といってもテストデータもコントローラもビューもないのでデータをちゃんと引っ張り出せているかどうかわかりません。そもそもphp的にエラーがあるかどうかすらわかりません。

動かしてみてもし一発で動けば問題はないものの、そんなことあるわけありません。むしろ一発OKを想定してはいけないはずです。切り分け出来ないから。

というわけで次の作業はテストデータ作成にします。

models/subject.php

<?php
class Subject extends AppModel {
public $name = 'Subject';
//answer(ボケ),Comment(コメント)をhasMany
public $hasMany = array('Answer' =>
array('className'  => 'Answer',
'foreignKey' => 'subject_id',
),
'Comment' =>
array('className'  => 'Comment',
'foreignKey' => 'subject_id',
),
);
}

models/answer.php

<?php
class Answer extends AppModel {
public $name = 'answer';
//vote(投票)をhasMany
public $hasMany = array('Vote' =>
array('className'  => 'Vote',
'foreignKey' => 'answer_id',
),
);
//subject(お題)にbelongsTo
public $belongsTo = array('Subject' =>
array('className'  => 'Subject',
'foreignKey' => 'subject_id',)
);
}

models/vote.php

<?php
class Vote extends AppModel {
public $name = 'Vote';
//answer(お題)にbelongsTo
public $belongsTo = array('Answer' =>
array('className'  => 'Answer',
'foreignKey' => 'answer_id',)
);
}

models/comment.php

<?php
class Comment extends AppModel {
public $name = 'Comment';
//subject(お題)にbelongsTo
public $belongsTo = array('Subject' =>
array('className'  => 'Subject',
'foreignKey' => 'subject_id',)
);
}

お題以外のテーブルのSQL(ボケ、投票、コメント)

CREATE TABLE 'answers' (
   id INTEGER PRIMARY KEY UNIQUE NOT NULL,
   name TEXT NOT NULL,
   answer TEXT NOT NULL,
   host TEXT NOT NULL,
   mobilenum TEXT DEFAULT '',
   created TEXT NOT NULL,
   modified TEXT NOT NULL,
   subject_id INTEGER NOT NULL
)
CREATE TABLE 'votes' (
   id INTEGER PRIMARY KEY UNIQUE NOT NULL,
   answer_id INTEGER NOT NULL,
   host TEXT NOT NULL,
   mobilenum TEXT DEFAULT '',
   created TEXT NOT NULL,
   modified TEXT DEFAULT ''
)
CREATE TABLE 'comments' (
   id INTEGER PRIMARY KEY UNIQUE NOT NULL,
   subject_id INTEGER NOT NULL,
   comment TEXT NOT NULL,
   host TEXT NOT NULL,
   mobilenum TEXT DEFAULT '',
   created TEXT NOT NULL,
   modified TEXT DEFAULT ''
)

テストデータ作らないと何がなんだか。

RewriteBaseをきちんと設定

/webroot の.htaccessがブログチュートリアルのままでおかしかったのでapacheのrootからのパスにきちんと変えました。具体的には /path/to/apacheroot/odon/.htaccess のRewriteBase を

RewriteBase /odon

にしました。このエントリ、順序的にはMVCのエントリの前に入ります。

参考
【PHP】フレームワーク CakePHP
http://pc11.2ch.net/test/read.cgi/php/1163850802/21
> 21 nobodyさん sage 2006/11/27(月) 09:17:16 ID:???
> http://localhost/cake_blog_tutorial/にCakePHP入れてチュートリアルやってたんだけど、無効なURL〜みたいなエラーが発生。
> mod_rewriteが悪いのかな?と思いつつ調べてみたら.htaccessのRewriteBaseを設定しないといけないと書いてあった。
>
> /.htaccess
> RewriteBase /cake_blog_tutorial
>
> /app/.htaccess
> RewriteBase /cake_blog_tutorial/app
>
> /app/webroot/.htaccess
> RewriteBase /cake_blog_tutorial/app/webroot
>
> これで動作した。同じ事で初っ端から躓く人が居るかもしれないからここに書き残しておく。
> (躓いたおかげでチュートリアルに1時間半かかったw)
>
> 参考:orihasam’s log
> ttp://d.hatena.ne.jp/orihasam/20060809

作るもの Ogiri Dynamic Operation Network

今作っているものはweb大喜利のシステム Ogiri Dynamic Operation Network です。早い話が
ボケましーん
http://bok-1.presen.to/labo/index.html
のパチものです。

  • この配布スクリプトにいくつか不満があること
  • ライセンスが改造OK再配布NGであること
  • なによりCakePHPを使ってみたいこと

この理由から、手を入れるのではなく1から作り始めることにしました。

システムの流れとしては お題→回答→投票+コメント→結果 を繰り返しで表示します。DBテーブル的にはお題、ボケ、投票、コメント、規制の5つがあればいいはずです。

システムの基本部分は簡単に出来そうです、がそこを作るのにもモタモタしている次第です。そしておそらく山場は携帯対応(SJIS←→UTF-8)になりそうです。

ログインシステムと携帯対応はwebアプリ作る上で避けて通れません。というか今まで自分が携帯からほとんどweb利用しないこともあって携帯対応は避けてきたんですが、そろそろ覚えておいたほうが便利そうなのでやってみます。

以下断片的にお題subject、ボケanswer、投票vote、コメントcomment、で表記が揺れますがそこは適宜読み替えてください。

MVCのひな型

models/subject.php

<?php
class Subject extends AppModel {
}

controllers/subjects_controller.php

<?php
loadModel("Subject");
class SubjectsController extends AppController{
       public $uses = null;
       function index() {
               $dao = new Subject();
               $this->set('subjects', $dao->findAll());
               }
}

views/subjects/index.thtml

<h1>投稿</h1>
<table>
   <tr>
       <th>Id
       <th>名前</th>
       <th>お題</th>
   </tr>
  <!-- ここで、 $subjects 配列のループをまわして、投稿情報を printing out します。 -->
   <?php foreach ($subjects as $subject): ?>
   <tr>
       <td><?php echo $subject['Subject']['id']; ?></td>
       <td>
           <?php echo $html->link($subject['Subject']['name'],
"/subjects/view/".$subject['Subject']['id']); ?>
       </td>
       <td><?php echo $subject['Subject']['subject']; ?></td>
   </tr>
   <?php endforeach; ?>
</table>

MVCを一気に。ただ、subjectにコントローラやビューって必要なのかな?お題一覧のテーブルを出してそこを表示したり変更したりするような機能は要らない気がするんだなあ。何に何が必要なのかがイマイチよくわかってません。余計なものを作ってしまった分には後で消すのは簡単なのでとりあえずそういうことで。

この辺を参考にしました。
Blog-side CakePHP わかりずらい3点
http://blog.takeda-soft.jp/blog/show/190
Blog-side CakePHP わかりずらい+2点
http://blog.takeda-soft.jp/blog/show/192

セットアップとDBの準備

xreaにワラワラwebアプリ置くことを考えると

  1. CakePHP のコアライブラリ – /cake
  2. アプリケーションコード(コントローラ、モデル、レイアウト、ビューなど。) -/app
  3. アプリケーションの webroot ファイル(画像、javascript, CSS など) -/app/webroot

1はすべて共通でpublic_html外
2はアプリごとにpublic_html外
3はアプリごとに(ドメインごとに)public_html内

にそれぞれ置く必要があります。

3.4.?CakePHP のセットアップ
http://cakephp.jp/doc/ch03s04.html
の日本語マニュアルにそのまんまの記述があるので指示通りに設定しました。

次はDBの暫定テーブルです。

CREATE TABLE 'subjects' (
   id INTEGER PRIMARY KEY UNIQUE NOT NULL,
   name TEXT NOT NULL,
   subject TEXT NOT NULL,
   status TEXT NOT NULL,
   host TEXT NOT NULL,
   mobilenum TEXT DEFAULT '',
   answersec INTEGER NOT NULL,
   votesec INTEGER NOT NULL,
   created TEXT NOT NULL,
   modified TEXT DEFAULT ''
)

今のところDBはこんな感じにしておきます。

次にデータベース接続の設定config/databaseです。

class DATABASE_CONFIG {
       var $default = array(
               'driver' => 'sqlite',
               'persistent' => false,
               'host' => '',
               'login' => '',
               'password' => '',
               'database' => '../../path/to/database.db',
               'prefix' => ''
       );
}

webroot/indexの中で設定した定数をDBのパスに使おうとしてダメだったので、とりあえず相対パスで指定しました。

ブログチュートリアル設定の名残(config/routes.phpがそのまま)だからpostsコントローラがないぞ!って怒られますが、これは次以降のエントリで。

追記 2007.09.23

データベースのパスをフルパスに変えました。

class DATABASE_CONFIG {
public $default = array(
'driver' => 'sqlite',
'persistent' => false,
'host' => '',
'login' => '',
'password' => '',
'database' => 'c:/path/to/database.db',
'prefix' => ''
);
}