PHP ActiveRecord通过创建子模型有很多关联

PHP ActiveRecord通过创建子模型有很多关联,php,phpactiverecord,Php,Phpactiverecord,我正在学习PHP活动记录并处理关联。我有两个相关的对象,它们使用“Has_Many”和“belish_to”(父/子)并在创建新父记录时尝试创建子记录(在本例中,为我的“单元”创建一个“皮肤”) 我在这里找到了这两个线程: 因此,我认为我的代码目前看起来像: $unit = new Unit(); $unit->name = 'somename'; $unit->description = 'somedescription'; $skinArray = array('name'

我正在学习PHP活动记录并处理关联。我有两个相关的对象,它们使用“Has_Many”和“belish_to”(父/子)并在创建新父记录时尝试创建子记录(在本例中,为我的“单元”创建一个“皮肤”)

我在这里找到了这两个线程:

因此,我认为我的代码目前看起来像:

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

$skinArray = array('name' => $unit->name.' Default Skin');
$unit->create_skins($skinArray);
$unit->save();
上面的代码没有将新的皮肤与数据库或代码中的单位相关联,尽管它/正在/正在/在数据库中放置新的皮肤记录(单位id为NULL)。使用“构建皮肤”不会将皮肤记录放入数据库中

我希望有一种方法可以像其他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。例如,“休会”PHP框架对单元的简单调用如下:$unit->addSkin($skin)

我不太熟悉php活动记录,但根据我的经验(同样的问题是,在我将父视图和子视图持久化到数据库之前,我在使用Doctrine并尝试添加子视图时出现了null)。我认为phpactiverecord没有此功能,因此我建议的解决方案是在模型中手动创建方法,如Unit::addSkin(Skin$Skin),其内部将包含以下内容:

$skin->unit_id = $this->id;
$skin->save();
基本上是这样的逻辑。但我不能说这是好的,甚至是中性的实践。这就是你在教义中做这些事情的方式


还有,你试过推进吗?如果您喜欢active record,我想您会发现它非常有趣。

您是否配置了数据库连接? 看看例子

<?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());
?>


如果不是自动递增(没有NULL作为deafult值),则必须初始化DB才能执行此操作
ActiveRecord\Config::initialize

。我将查看db key defualt值,并调整auto increment或unit_id的默认值(如果它符合您的模式)。你说协会正在进行两步保存。在两步保存中是否正确保存了设备id

这些文档没有太大帮助,因为它们建议您尝试避免的显式保存

@AbroughtMetal有一些有趣的东西,关于使用钩子设置unit->id,但是它不需要是一个在创建回调之前的回调,您不希望在关联不起作用的情况下插入记录。看


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

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

但是(例如)下面这样的东西很好:

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();
        }
    }  
 ...   
}
如果事实上特定的行为是控制器独有的,那么可能使用以下替代方法(从控制器传入的数据以创建子对象):


希望有帮助。我是ActiveRecord快速搭建的粉丝,不过要注意,在更大的应用程序中过于“神奇地”依赖它。顺便说一句,iz在Rails中也很不错;)它起源于哪里。

我也想知道这一点。我的业务规则验证需要该对象以及所有子对象,但如果业务规则失败,我宁愿不将其放入数据库。该库具有4年前发布的最后一个稳定版本(和唯一版本)。上次网站更新是在3年前。通常ORM是安全缺陷的一个重要焦点。也许你应该考虑切换到其他库。我已经完成了所有的数据库配置。我的网站不是这样的。所有协会都在正常运作。但创建关联需要两个步骤。在Rails ActiveRecord中,在现有对象上创建关联模型时,会暗示链接关联模型。然而,在PHP ActiveRecord中,这两个步骤的过程对于开发人员来说并不明显;特别是那些来自Rails的。外键在两步保存中被正确保存。unit->id的隐式设置似乎与创建\u皮肤或构建\u皮肤方法有关。你能展示一下吗?我还想指出,这突出了原方案设计中的一个缺陷。如果有两个记录的外键相互关联,则总是会造成关系“鸡和蛋”死锁。在我上面发布的例子中,我们已经确定“皮肤”只存在于“单位”中,因此正确的关系是皮肤属于单位。如果
Skin
仅用于保存外键,这将起作用。但是当有额外的信息要存储在
皮肤中时
这个解决方案就不够了,因为模型钩子的范围是单位。我们如何将控制器中的信息传递到Unit model类中,以便在钩子中使用?我已将其更新为包含新的皮肤名称,但我将提供以下内容:此方法应仅用于默认行为-它们可以基于输入父模型的数据,但范围将始终关闭。这个闭包确保了你的代码是好的、枯燥的和可重用的。你只需按照它应该的方式重写
Model->create\u association()
方法。但这将意味着按照每个模型的关联进行
$after_create = array('validate association and assign unit_id if NULL'); 
$before_create = array('explcitly assign unit_id');
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();
    }  
 ...   
}