PHP ActiveRecord通过Has_Many关联创建子模型

时间:2012-08-02 00:05:44

标签: php phpactiverecord

我正在接受PHP Active Record并处理关联。我有两个相关的对象使用“Has_Many”和“Belongs_to”(父/子)并尝试在创建新的父记录时创建子记录(在这种情况下为我的“单位”创建“皮肤”)。

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 个答案:

答案 0 :(得分: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());
?>

您必须使用init DB执行此操作ActiveRecord\Config::initialize

答案 1 :(得分:1)

根据您的键,您是否应该自动递增(不使用NULL作为deafult值)。我将查看db key defualt值并调整自动增量或unit_id的默认值(如果它适合您的模式)。你说该协会正在与两步保存。 unit_id是否在两步保存中正确保存?

文档不是很有帮助,因为他们建议明确保存您尝试避免。

@outrightmental有一些关于使用钩子设置unit-&gt; id的有趣内容,但是它不需要是一个before_create回调,你不想在没有关联工作的情况下插入记录。见this active record callbacks doc

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

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

?回调文档提供了其他建议

答案 2 :(得分:1)

我建议在父模型类中的afterSave()挂钩中或在自定义模型方法createChild($data)中实现该方法。

然而(例如Yii Framework's 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的粉丝,可以快速搭建脚手架,虽然要小心依赖它,并且神奇地&#34;适用于大型应用。顺便说一句,在Rails中也非常好;)它起源于哪里。

答案 3 :(得分:-2)

我对php活动记录并不是很熟悉,但根据我的经验(同样的问题是当我使用Doctrine并试图添加子视图时,还有null,在我将父和子持久化到数据库之前) 。我认为phpactiverecord没有这个功能,所以我建议的解决方案 - 在模型中手动创建方法,比如Unit :: addSkin(Skin $ skin),里面会有这样的东西:

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

基本上就是这样的逻辑。但我不能说这种方法很好甚至是中性的。这就是你在Doctrine中做这些事情的方式。

另外,你试过Propel?如果你喜欢积极的唱片,我觉得你会发现它非常有趣。