
こちらの記事ですが、以下の記事の内容を行うと、insert等ができなくなるようになってしまいました・・・。
どうやら最後のIDが取得出来ないからこうなってしまうようです。目次
互換性などの点からもIDは付けるようにしましょう。複合ユニークキーとインデックスをつければそれなりにちゃんと速くなるはず
こんにちは。ファガイです。
先日から個人的にサイトを制作していたのですが、衝撃の事実がわかりまして・・・
Eloquent ORMは複合主キーに対応していない!
うん、複合主キーに対応していない。
皆見たらわかると思うんだ、Illuminate\Database\Eloquent\Builderのfindメソッドを見てみよう。
public function find($id, $columns = array('*'))
{
$this->query->where($this->model->getKeyName(), '=', $id);
return $this->first($columns);
}
あとは、Illuminate\Database\Eloquent\Modelとかも。
public static function find($id, $columns = array('*'))
{
$instance = new static;
if (is_array($id))
{
return $instance->newQuery()->whereIn($instance->getKeyName(), $id)->get($columns);
}
return $instance->newQuery()->find($id, $columns);
}
そもそも、primaryKeyは1つであると確定しているのも問題じゃないのかと思ってる。
リレーションを組もうとしたが、この仕様だと、primaryKeyは1つでなければいけない。複合主キーで組もうと思ったらリレーションが組めない。結構大問題だった。
大問題でも無かった。Query Builderで取ってきてくっつければ普通に取得できた。
Eloquent Modelのfindメソッドの動き的にid複数を取得して来れる的な仕様と見れる。だがQuery Builderには実装されていない。まだ粗はありそう。
対処方法
上記で出したメソッドにidがarrayで来たとかprimaryKeyがarrayだったとか判定が必要。
あと、コアとなっているEloquent\Relations\BelongsTo等のaddConstrationsをいじる必要がある。
これを修正しないと、リレーションを組むことが出来ませんでした。
自分の場合はこのような形に変更しています。例えば、BelongsToの場合。
public function addConstraints()
{
if (static::$constraints)
{
$key = $this->related->getKeyName();
$table = $this->related->getTable();
$count = count($key);
if($count > 1) {
for($i = 0; $i < $count; ++$i) {
$this->query->where($table.'.'.$key[$i], '=', $this->parent->{$this->foreignKey[$i]});
}
}else{
$this->query->where($table.'.'.$key, '=', $this->parent->{$this->foreignKey});
}
}
}
コアとなっている部分をいじってしまっているので、composer updateをやってしまうともう一度直さなきゃいけなさそうですね。
Eloquent Modelの方は一つBaseEloquentとかモデルを用意して、それを継承させる形にすればよいでしょう。
ではではー。
2013-09-08追記
複合主キーは拡張性が無くなったり、変更に強くないため主キーが1つなのかもしれませんね・・。しかしながらスキーマビルダーは複合主キーが定義出来る・・・なんだろうこの矛盾
コメント