6

我正在拿起 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:创建新对象(查找类)

所以我的代码目前看起来像:

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

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

上面的代码没有将新皮肤与数据库或代码中的单元相关联,尽管它 /is/ 在数据库中放置了一个新皮肤记录(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 中完成的方式,而我的期望是错误的。但是我希望有一种方法可以通过不需要先通过显式调用将父级保存到数据库的对象来实现。例如,“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());
?>

你必须初始化数据库才能做到这一点ActiveRecord\Config::initialize

于 2014-04-30T10:50:49.030 回答
1

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

这些文档不是很有帮助,因为它们建议您尝试避免显式保存。

@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 框架的 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 并尝试添加子视图时,在我将父子视图持久化到数据库之前也有空值)。我认为 phpactiverecord 没有这个功能,所以我建议的解决方案 - 在模型中手动创建方法,比如 Unit::addSkin(Skin $skin),里面会有这样的东西:

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

基本上就是这样的逻辑。但我不能说这种方法是好的,甚至是中立的实践。这就是你可以在 Doctrine 中做这些事情的方式。

另外,您尝试过 Propel 吗?如果你喜欢主动记录,我想你会觉得它很有趣。

于 2014-04-29T10:28:19.183 回答