FuelPHPのORMパッケージを使用するとき、forgeメソッドでレコードの値を設定するとプライマリキーが消されていることがあったのでメモしておきます。
対象のOrmパッケージは1.9/developです。(コードは現時点の最新コミットを参照しています)
目次
forgeで設定したあと消えるようになっていた
Ormパッケージの Orm\Model は、forgeメソッドを用いてモデルオブジェクトを作成し、同時にレコードの値も設定できるようになっています。
ですがOrmパッケージをアップデートした後で、これを行っていたところでなぜかプライマリキーの値が消えている問題が発生しました。
調査していくとコンストラクタでプライマリキーが消されるようになっていました。
// wipe any PK values present in the input if not allowed if (static::$block_set_pks) { // make sure the primary keys are reset foreach (static::$_primary_key as $pk) { $this->_data[$pk] = null; } }
おうふ。。
$block_set_pksで一応制御されるようになってた
で、今見ているとどうやら直近で修正が入ったようで、$block_set_pksを見て消さないようになっていました。
added option to disable blocking PK's being set
たぶんいろいろ議論になったんじゃないかなと勝手に思います…そらそうやろって感じですが…
でもprotectedだしデフォルトtrueだしデフォルトの挙動は変わりませんね。今更デフォルトの挙動をまた替えると混乱するってのもあるのでしょう。
回避策について
setメソッドを使う
Orm\Modelにはforgeとは別に値をセットできるsetメソッドがあるので、forgeはインスタンスを作るだけにしてsetのほうで値を設定すると上手くいきました。
ただこちらもコードを読んでいると、プライマリキーの値が一度設定されていた場合はエラーになるようなところがあるので注意する必要があります。これは事故を防止するためには仕方ないか…
$block_set_pksを設定する
最新コミットでは$block_set_pks でフラグを立てられるようなので、モデルクラスの継承先でこれをオフにしても良いと思います。
class Model_Article extends Orm\Model { protected static $block_set_pks = false; }
こんな感じですね。
from_arrayメソッドのほうも$block_set_pks の影響受けるように修正されているみたいなので、こちらを使用してる場合も$block_set_pksを調整する必要があるでしょう。
static変数を変更する場合は、継承先のクラスでstatic変数を再定義しないと継承元のクラスにあるstatic変数まで変更されてしまいますので注意が必要です。
ですので、例えば次のようにしてインスタンスのinitメソッドを呼び出したりするとOrm\Modelを使用しているすべてに影響してしまいます。
class Model_Article extends Orm\Model { public function init() { self::$block_set_pks = false; } }