がるの健忘録 このページをアンテナに追加 RSSフィード

2018-02-18

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

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


「もう一度使う知識」かどうかは限りなく謎ですが。

まぁせっかく得た知見なので、共有まで。


……いやぶっちゃけもう結構「泥臭い力技」を覚悟してたので。

まぁどうにかなってよかったですだす。

ndxbnndxbn 2018/02/19 01:49 `protected string $primaryKey` https://laravel.com/api/5.6/Illuminate/Database/Eloquent/Model.html っていってるんだから、 `protected $primaryKey = ['id', 'parent_id'];` は完全にアウト。

Database\Eloquent\Model の `getKeyName()` メソッドを使っている箇所を簡単に調べたけれど
https://github.com/laravel/framework/search?utf8=✓&q=getKeyName&type= 、どこも String 以外が帰ってきたらエラーになりそうに見える。

マイナーバージョンアップですらぶっ壊れる可能性ありそうに見えるし、バッドノウハウだし、わりとヤバイ感じの負の遺産になるのを覚悟した上でやる、くらいの感じかなって個人的には思うです。
万が一にもこんなコードのある現場に出くわしたら、俺なら逃げる。


Laravel で複合主キーのテーブルを扱う場合はどうするかというと、素直に QueryBuilder https://readouble.com/laravel/5.5/ja/queries.html を使えばいいかなって思う。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/gallu/20180218/p1