gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

複合主キーの扱い方(一部)

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


「もう一度使う知識」かどうかは限りなく謎ですが。
まぁせっかく得た知見なので、共有まで。


……いやぶっちゃけもう結構「泥臭い力技」を覚悟してたので。
まぁどうにかなってよかったですだす。