movies(作品情報群),genres(movieID,mgenreID,(映画とジャンルを結びつける)),mgenres(ジャンル一覧群)3つのテーブルを使います。Movie,Genre,Mgenreの3モデルを作成。
_________________________
Genreモデルを使い他のテーブルとリレーション。
public $belongsTo = array(
'Movie' => array(
'foreignKey' => 'movie_id'
),
'Mgenre' => array(
'foreignKey' => 'mgenre_id'
)
);
_________________________
MoviesController.phpをメインに作業をしていきます。
class MoviesController extends AppController {
public $uses = array('Movie','Genre','Mgenre');
public function add() {
$genre_list = $this->Mgenre->find('list');
$this->set('mgenres',$genre_list);
__________}_____________
add.ctpにcheckbox作成
echo $this->Form->create();
echo $this->Form->input('mgenre_id', array('multiple' => 'checkbox'));
echo $this->Form->end('追加');
______________________________________________________
checkboxのname属性はdata[Movie][mgenre_id][]。
なんとかcheckboxを作成できたのですが、チェックした値全てをgenresテーブルに追加する方法が分かりません。
コメント(12件)
>||
public $hasAndBelongsToMany = array(
'Tag' => array(
'className' => 'genre',
'joinTable' => 'mgenre',
'foreignKey' => 'movie_id',
'associationForeignKey' => 'mgenre_id',
'fields' => array('id','name'),
'unique' => true
),
);
||<
を書きました。
といったテーブル構成になっています。
ぜひ参考にしてください。
Movie hasAndBelongsToMany Mgenre
な訳ですから、Movieモデルの記述には、
public $hasAndBelongsToMany = array(
'Mgenre' => array(
'className' => 'Mgenre',
'joinTable' => 'genres',
'foreignKey' => 'movie_id',
'associationForeignKey' => 'mgenre_id',
・・・
),
);
という風にならないとダメですね。
MovieとhasAndBelongsToMany な関係にあるモデルはGenreではなくて、Mgenreですよね?
関連テーブルはgenresですよね?
またまた一般論になりますが、一般的には、
moviesとgenresというテーブルに対して、genres_moviesという関連テーブルを用意するのが一般的です。
今回は、テーブル名もなぜ、関連テーブル名をgenresにしたのかよく分かりませんが、この辺りが意識とコードの間違いを生んでいる原因のような気もします。
ちなみに、規約に基づいた名前でテーブルを作成した上で、bakeしただけでどんなコードが生成されるのかを一度みた方がよいかと思います。
それ以前に、bakeってしたことあります?
・mgenresテーブルをgenresテーブル、genresテーブルをmovies_genresテーブルに変更しました。
・bakeについて
手打ちで入力しながら作業の流れを学んでいこうと思ったのでしていないです。
・CakePHPの基本的なことについて
基本的なサンンプルは作成したのですが、まだまだ理解不足だったようです。
特にアソシエーション。
まず、genresテーブルに入っているデータでチェックボックスを作ることを頑張ってみます。
少なくとも、Cakeの作法がなんとなくわかるまでは、その方が学習効率がよいかと。
DBだけ定義して、ModelとControllerとViewを適当に作成すれば、基本操作が出来るものが出来上がります。
hasAndBelongsToManyのアソシエーションも、bakeしただけでアソシエーションを保存してくれるものが出来上がります。
ただし、bakeしたものは、チェックボックスではなく、リストボックスで複数選択させるようになってますが。
それを元に、その意味を考えながら手直しすれば、標準的な書き方を学べる上に、作業効率も上がるんじゃないかと。
なお、関連テーブルは、genres_moviesが標準です。テーブル名をつなげる際はアルファベット順が基本です。
ひょっとしたら標準とか、規約とか、面倒と思われているかもしれませんが、それがCakePHPです。
場合によってはそれが足枷になることもありますが、それに基づいているからこそ、自動化できたり、他の開発者が状況をすぐにつかめたりする訳です。
そのうえ、チェックボックスで複数選択ても全てのデータがテーブルに追加されています。
bakeが予想以上に便利でとても驚いています。
今は、
genres_moviesテーブルに「genre_id」に一致した「genre_name(ジャンル名)」のデータを追加しようと考えています。そうした方が、映画のジャンル検索をする際にgenresテーブルとgenres_moviesテーブルを参照しなくても、genres_moviesテーブルだけを参照すればいいだけです。
genres_moviesテーブルに入力する「genre_name(ジャンル名)」を取得するには、genresテーブルから「select name from genres where genre_id 」で検索する必要があります。
しかし、この方法が効率的なのか疑問に思うようになりました。
大規模のデータベースで開発する際の関連テーブルにはお互いの「id」のみを登録するのでしょうか?
場違いな質問かと思いますが、ご返答をお待ちしております。
これに関しては、データベースの正規化とかの話を一度勉強されるといいと思います。
必ずしもYESではないですが、明確な理由がなければ、idのみで管理した方が都合がいいでしょう。
という前置きをした上で、実際、どういう検索をしたいのですか?
ジャンル名で検索するケースというのがよく分かりませんでした。
どんなシステムか想像になりますが、ユーザが映画を検索するサービスだとして、どういった検索の際にジャンル名で検索する必要があるのかなと。
何も考えなければですが、ジャンルに関してはセレクトボックスや、チェックボックスなどで選ばせるのではないでしょうか?
だとすれば、実際の検索は、ジャンルIDによる検索となるでしょう。
ジャンル名の部分一致などが必要ということであれば、ジャンル名検索が必要だとは思いますが、それならば、GenresMovieモデルを用意すれば十分じゃないかなと。
そうなるとジャンルIDで検索した方がよさそうです。
なんか難しく考えていたようで頭がごちゃごちゃしていました。
>ジャンル名の部分一致などが必要ということであれば・・・・
この部分は人物名で出演作品を検索する際に使えそうだと思いました。
利用させていただきます。
>データベースの正規化
についてもまた勉強し直します。ありがとうございます。
・ついでにご質問があります。
パーフェクトPHPを含めた最近の参考書を読んでいるとMVCで書かれていないコードが衰退し、これからはcakephp等のフレームワークで書かれたコードが主流になってくると書かれていました。
そのことを知ったので、cakephpでWEBサイトを作成することにしました。
そのような時代になってくると例えば以下のようなコードは使わなくなり、フレームワークでしかコードを書かなくなるのでしょうか?
_________________________________________
//名前が存在しないか、または名前が空であるなら
if(!isset ($_POST['name']) || !strlen($_POST['name'])) {
//エラー変数の配列にメッセージを格納
$errors['name']='名前を入力してください';
//文字数が40文字以上なら
} else if (strlen($_POST['name']) >40) {
//エラー変数の配列にメッセージを格納
$errors['name']='名前は40文字以内で入力してください';
//どれでもないなら
} else {
//名前を代入
$name=$_POST['name'];
}
>フレームワークでしかコードを書かなくなるのでしょうか?
あくまで個人的な意見ですが、多くの、特に業務として開発を行う人ならば、なんらかのフレームワークを使うことは増えてくると
は思います。ただし、規模が小さかった場合にはこの限りではないでしょうし、開発チームの習熟度によっては、フレームワークに手を出せない場合もあるかもしれません。
僕自身は、CakePHPが好きですし、スマートに書けると思っています。
ただ、それは全員に対してそうではないと思っています。実際、kyouryuさんはその移行で今、苦労されているのかと思います。
実際に大事なのは、今、苦労している基本的なことができることではなく、基本的なことが出来た上で、今目の前の問題に対して解決策を提示できるかどうかです。
プログラムを記述する以上、コンピュータにできないことはできません。
では、ある問題をどのようにコンピュータにさせるか?ということと、どのようにその記述を表現するかは別のことです。
例えば、挙げてもらったコードも、同じ内容の記述はCakePHPで開発しても必要です。
Model::validateに記述することで実現するのか、
Model::validatesメソッドをオーバーライドするのか、
Behaviorを記述するのか、
Controllerでチェックするのか、
などなど記述の仕方は考えられます。
これは、対象とする状況によってどれが最適とは言えません。
なので、こういった書き方は使われなくなるとかを気にする前に、何故、今、自分はこういう書き方をしているのか?を気にするようにしてみてはいかがでしょうか?
こんなこと気にしなくてもコードは書けますが、フレームワークというものに対する理解は少し深まるのではないかなと。
ところで、kyouryuさん自身、CakePHPを使って開発が簡単になったと感じてるのでしょうか?
最初は命名規則に困惑してましたが、bakeの使い方を知ってからは明らかに楽になりましたね。
tdoiさんの開発思考といいますかそれはとても参考になりました。
ただ漠然とWEBサイトを作ることだけを考えていたのですが、そのような意識は全く持っていなかったです。これからは、少しずつ意識しながら開発していきます。