在Phalcon中附加一个相关的模型


append a related Model in Phalcon

我用PHP中的Phalcon编写了一个vcard类。vCard模型的初始化方式如下。

// Inside the BS_VCard class
public function initialize(){
    $this->hasMany("id","BS_VCardElement","vCardId",array(
        "alias" => "elements",
        'foreignKey' => array(
            'action' => Phalcon'Mvc'Model'Relation::ACTION_CASCADE
        )
    ));
}

它的元素被初始化为这样的

// Inside the BS_VCardElement class
public function initialize(){
    $this->belongsTo("vCardId","BS_VCard","id",array("alias" => "vCard"));
    ...
}

如果用户读取一个vCard并添加另一个元素,它将无法按预期工作。为了简化使用,我添加了一些类似的fascade方法

public function addDateOfBirth($date){
    $element = new BS_VCardElement();
    $element->setName("BDAY");
    $element->addValue($date);
    // This doesn't work
    $this->elements[] = $element;
}

文档/存储相关记录没有解释如何将这样的新数据附加到相关表中。

我也试过这个

$this->elements[] = array_merge($this->elements,array($element));

但是save方法似乎忽略了添加的元素。Save()返回true。

几个月前就有人问过这个问题,但由于遇到了类似的问题,我决定无论如何都分享我的结果。

以下是我的发现。小写别名('elements')似乎不起作用,而大写别名('lements')起作用。

要添加一个元素,可以这样做;

$this->Elements = $element;

要添加多个元素,可以这样做;

$elements = array($element1, $element2);
$this->Elements = $elements;

之后,在再次访问元素之前,您必须保存vcard。如果不这样做,phalcon将只返回一个结果集,其中只有数据库中已经存在的元素。(不确定这是否可以以某种方式改变。)

以下是文档(其中没有提及所有这些):http://docs.phalconphp.com/en/latest/reference/models.html#storing-相关记录

根据Phalcon源代码,Resultset对象是免疫的。

/**
 * Resultsets cannot be changed. It has only been implemented to 
 * meet the definition of the ArrayAccess interface
 *
 * @param int index
 * @param 'Phalcon'Mvc'ModelInterface value
 */
public function offsetSet(var index, var value)
{
    throw new Exception("Cursor is an immutable ArrayAccess object");
}

用数组替换元素似乎是实现结果集的"追加"或修改(is支持的删除除外)的唯一方法。

当然,这会破坏'Phalcon'Mvc'Model::_preSaveRelatedRecords(),因为函数会忽略类属性,并从模型管理器中重新获取相关属性(并在最后重置model::$element属性)。

我对此感到沮丧,因为将对象附加到集合似乎是一项非常常见的任务,而没有一个明确的方法向父对象添加新项似乎是一个设计缺陷。

我认为在设置属性时,相关元素可能会调用一些神奇的功能,所以简单地使用$this->elements[](显然)是行不通的。也许可以尝试重新设置整个变量:

public function addDateOfBirth($date){
    $element = new BS_VCardElement();
    $element->setName("BDAY");
    $element->addValue($date);
    $elements = $this->elements;
    $elements[] = $element;
    $this->elements = $elements;
}