我用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;
}