LaravelのModelである「Eloquent ORM」で、複合主キーを扱う時の知見を得たので、備忘録的に。
Laravel5.5でやってます。それ以外のバージョンでどうなるかは不明です。
前提として。
おいちゃんは基本「サロゲートキー基本的にお好まない」一派です。
http://d.hatena.ne.jp/gallu/20160210/p1
この辺は議論がまだ色々ホットだと思うのですが、とはいえつまり「ホット」な程度に「どっちかは微妙」で。
なので基本的には「使えるもんなら使いたい」というスタンスです。
「複合主キーが、ちゃんとした理由でお好まないからサロゲートキー」ならよいのですが。
「フレームワークの都合」だけでサロゲートキーを押しつけられるのは、どうにもお好まないのですだよねぇ。それをされると「じゃぁそのフレームワークを使わない、って選択肢」を考えてしまうので。
なので「使ってみました」的なエントリーでございます。
初手として。
マイグレーションファイルでの「複合主キーを含むテーブルの作成」は、簡単にできます。
$table->primary(['id', 'parent_id']);
Modelでは
protected $primaryKey = ['id', 'parent_id']; public $incrementing = false;
でOK。下のは「なくても動いた」んだけど、何となく書いておきたいかなぁ、程度に。
keyType とかどうなるんじゃらほい? とか思うんだけど、そもこのModelに「::find(key)」とかやらないと思われるので、一旦気にしない。
んで。
例えば「データが欲しい」とか「key指定してupdateしたい」とかあるわけなのですが。
これで
$data = HogeModel::where('id', $id)->where('parent_id', $parent_id)->get()->toArray();
とか
$data = HogeModel::where('id', $id)->where('parent_id', $parent_id)->update($data);
とかやると、「Illegal offset type」とか怒られます。
結論から書くと「個別にwhereするとNGで、まとめてwhereするとOK」になります。
$data = HogeModel::where([ ['id', $id], ['parent_id', $parent_id] ])->get()->toArray();
$data = HogeModel::where([ ['id', $id], ['parent_id', $parent_id] ])->update($data);
あと、upsert的な事を(Modelクラスの中で)やるときは
$obj = $this->where([ ['id', $id], ['parent_id', $parent_id] ]); if (null === $obj->first()) { // insert処理 $this->insert($data); } else { // update $obj->update($data); }
ってな感じをベースにコネコネしていくと、まぁどうにかなるんじゃないかなぁ、と思われるです。
……これにちょっとはまった orz
「もう一度使う知識」かどうかは限りなく謎ですが。
まぁせっかく得た知見なので、共有まで。
……いやぶっちゃけもう結構「泥臭い力技」を覚悟してたので。
まぁどうにかなってよかったですだす。