6

私は PHP Active Record を取り上げ、関連付けを扱っています。「Has_Many」と「Belongs_to」(親/子) を使用する 2 つの関連オブジェクトがあり、新しい親レコードを作成するときに子レコードを作成しようとしています (この場合、「ユニット」の「スキン」を作成します)。

class Unit extends ActiveRecord\Model 
{  
   static $has_many = array(
       array('skins')
   );
}

class Skin extends ActiveRecord\Model 
{
    static $belongs_to = array(
       array('unit')
    ); 
}

ここでこれらのスレッドの両方を見つけました: http://www.phpactiverecord.org/boards/4/topics/153 Activerecord-association: create new object (find class)

したがって、私のコードは現在次のようになっています。

$unit = new Unit();
$unit->name = 'somename';
$unit->description = 'somedescription';

$skinArray = array('name' => $unit->name.' Default Skin');
$unit->create_skins($skinArray);
$unit->save();

上記のコードは、新しいスキンをデータベースまたはコード内のユニットに関連付けていませんが、データベースに新しいスキン レコードを配置しています (unit_id が NULL です)。「build_skins」を使用しても、スキン レコードはデータベースに追加されません。

他のORMのように、モデル自体を介して親モデルに「子」を追加する方法があることを望んでいました。これを行う唯一の方法は、明示的に行うことです。

$unit = new Unit();
$skin = new Skin();

$unit->name = 'somename';
$unit->description = 'somedescription';
$unit->save();

$skin->unit_id = $unit->id;
$skin->name = $unit->name.' Default Skin';
$skin->save();

おそらくそれが PHP ActiveRecord で行われるはずの方法であり、私の期待は間違っています。しかし、最初に明示的な呼び出しで親をDBに保存する必要のないオブジェクトを介してそれを行う方法を望んでいました。たとえば、"Recess" PHP フレームワークは、次のような単純なユニット呼び出しを行います。 $unit->addSkin($skin);

4

4 に答える 4

1

データベース接続を設定していますか? gihubの例を見てください。

<?php
require_once __DIR__ . '/../../ActiveRecord.php';

class Book extends ActiveRecord\Model
{
// explicit table name since our table is not "books"
static $table_name = 'simple_book';

// explicit pk since our pk is not "id"
static $primary_key = 'book_id';

// explicit connection name since we always want production with this model
static $connection = 'production';

// explicit database name will generate sql like so => db.table_name
static $db = 'test';
}

$connections = array(
'development' => 'mysql://invalid',
'production' => 'mysql://test:test@127.0.0.1/test'
);

// initialize ActiveRecord
ActiveRecord\Config::initialize(function($cfg) use ($connections)
{
    $cfg->set_model_directory('.');
    $cfg->set_connections($connections);
});

print_r(Book::first()->attributes());
?>

これを行うには DB を初期化する必要がありますActiveRecord\Config::initialize

于 2014-04-30T10:50:49.030 に答える
1

キーによっては、自動インクリメントしないでください (デフォルト値として NULL を使用しないでください)。db キーのデフォルト値を確認し、スキーマに適合する場合は auto-increment または unit_id のデフォルト値を調整します。関連付けは 2 段階の保存に取り組んでいるとおっしゃいました。unit_id は 2 段階保存で正しく保存されていますか?

ドキュメントは、回避しようとしている明示的な保存を推奨しているため、あまり役に立ちません。

@outrightmental にはフックを使用して unit->id を設定することについて興味深いことがありますが、before_create コールバックである必要はないでしょう。関連付けが機能しないままレコードを挿入する必要はありません。このアクティブ レコード コールバック ドキュメントを参照してください。

$after_create = array('validate association and assign unit_id if NULL'); 

また

$before_create = array('explcitly assign unit_id');

? コールバック ドキュメントは他の提案を提供します

于 2014-05-01T19:02:41.237 に答える
1

afterSave()メソッドを親モデル クラス内のフックに実装するか、カスタム モデル メソッドに実装することをお勧めしますcreateChild($data)

ただし ( Yii Framework の CActiveRecordなど)、次のようなものは便利です。

class Unit extends ActiveRecord\Model 
{  
 ...
    public function afterSave() {
        if ($this->isNewRecord) {                
            $firstSkin = new Skin();
            $firstSkin->unitId = $this->id;
            $firstSkin->name = $this->name . ' Default Skin';
            $firstSkin->save();
        }
    }  
 ...   
}

実際に特定の動作がコントローラーに固有のものである場合は、おそらく次の代替手段を使用します (コントローラーから渡されたデータで子を作成します)。

class Unit extends ActiveRecord\Model 
{  
 ...
    public function createSkin($data) {
        $firstSkin = new Skin();
        $firstSkin->unitId = $this->id;
        $firstSkin->setAttributes($data);
        $firstSkin->save();
    }  
 ...   
}

それが役立つことを願っています。私は迅速なスキャフォールディングのために ActiveRecord のファンですが、大規模なアプリケーションでは「魔法のように」それに頼りすぎないように注意してください。ところで、Railsでもとてもいいです;)それが生まれた場所。

于 2014-05-01T22:35:39.220 に答える
-2

私はphpのアクティブレコードにあまり詳しくありませんが、私の経験では(Doctrineを使用していて子ビューを追加しようとしたときに同じ問題が発生し、親と子をデータベースに永続化する前にnullもありました)。phpactiverecord にはこの機能がないと思うので、私が提案する解決策は、Unit::addSkin(Skin $skin) のようなモデルで手動でメソッドを作成することで、内部に次のようなものがあります。

$skin->unit_id = $this->id;
$skin->save();

基本的にはそのようなロジックです。しかし、このアプローチが良いとか中立的な実践であるとは言えません。Doctrine ではこのようなことを行うことができます。

また、プロペルを試しましたか?アクティブレコードが好きな人なら、かなり面白いと思うと思います。

于 2014-04-29T10:28:19.183 に答える