Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在Phalcon模型中返回虚拟列_Php_Model_Phalcon - Fatal编程技术网

Php 在Phalcon模型中返回虚拟列

Php 在Phalcon模型中返回虚拟列,php,model,phalcon,Php,Model,Phalcon,我有一个(简化)表格的模型leads\u contents\u interactions: 我想选择这些,除了id、lead\u content\u id和created\u on列之外,我还想让它返回一个列is\u new,其中类似以下内容: SELECT id, lead_content_id, created_on, IF(created_on > DATE_SUB(NOW(),INTERVAL 1 DAY), 1, 0) AS is_new FRO

我有一个(简化)表格的模型
leads\u contents\u interactions

我想选择这些,除了
id
lead\u content\u id
created\u on
列之外,我还想让它返回一个列
is\u new
,其中类似以下内容:

SELECT 
    id,
    lead_content_id,
    created_on,
    IF(created_on > DATE_SUB(NOW(),INTERVAL 1 DAY), 1, 0) AS is_new
FROM leads_contents_interactions;
现在我知道我可以用PHQL实现这一点,但是
leads\u contents\u interactions
最好不要直接查询,我希望在自然查询时返回这个额外的列,如:

$leads = $user->getRelated(
    'leads',
    array(
        'Lead.deleted_by IS NULL',
        'limit'=>1000
    )
);

foreach($leads as $lead) {
    foreach($lead->interactions as $interaction) {
        echo $interaction->id."\t".$interaction->is_new.PHP_EOL;
    }
}
铅的型号(简化)

领导内容模型(简化)

领导内容交互模型(简化)


如果要添加表中不存在但作为业务规则存在的列(创建日期>日期子(NOW(),间隔1天),1,0),则需要在模型本身的afterFetch方法中添加该规则:

但是,应该注意的是,如果在记录集上使用toArray()方法,那么它将只使用表本身上存在的列

重写虚拟字段的toArray()方法。 针对David Duncan所说的话:

但是,应该注意的是,如果使用toArray()方法 在记录集上,它将只使用 桌子本身

为了规避这种Phalcon的“限制”,我创建了以下方法覆盖

第一步 基本上,创建一个BaseModel.php并将下一个代码放在那里

/**
 * Method override.
 *
 * This method is inherited from Model::toArray()
 * https://docs.phalconphp.com/en/3.2/api/Phalcon_Mvc_Model
 *
 * We override it here to circumvent a Phalcon limitation:
 * https://stackoverflow.com/a/27626808/466395
 *
 * Basically, the limitation consists that, when one adds 'virtual fields' to a model (for example,
 * by way of callback methods like afterFetch()), then using toArray() on that model only returns
 * the fields in the database table but not the virtual fields.
 *
 * @access public
 * @param array $columns As per the Model::toArray() method.
 * @return array The data of the model, including any custom virtual fields.
 */
public function toArray($columns = null) {
    // calls the regular toArray() method
    $data = parent::toArray($columns);

    // then gets the model's virtual fields, if any
    $virtual_fields = [];
    if (!empty($this->list_virtual_fields)) {
        // iterates, to get the virtual field's name, value, and getter
        foreach ($this->list_virtual_fields as $name) {
            $getter_name = 'get' . \Phalcon\Text::camelize($name);
            $virtual_fields[$name] = $this->{$getter_name}();
        }
    }

    // merges the model's database data with its virtual fields
    $data = array_merge($data, $virtual_fields);

    return $data;
}
步骤2 然后,在任何应用程序模型中,定义将包含在上述方法覆盖中的虚拟字段列表。例如:

public $list_virtual_fields = [
    'status_label'
];
您还应该为这些虚拟字段定义类属性、setter和getter。举个例子:

protected $status_label;
public function getStatusLabel() {
    return $this->status_label;
}
public function setStatusLabel(string $status_label) {
    $this->status_label = $status_label;
    return $this;
}
public function afterFetch() {
    $this->setStatusLabel('pending');
}
步骤3 最后,设置整个应用程序中虚拟字段的值。例如:

protected $status_label;
public function getStatusLabel() {
    return $this->status_label;
}
public function setStatusLabel(string $status_label) {
    $this->status_label = $status_label;
    return $this;
}
public function afterFetch() {
    $this->setStatusLabel('pending');
}

注意,我的代码使用getter和setter。如果你愿意,你可以改变它。

这正是我想要的。谢谢你非常详尽的回答。非常感谢。b、 为了避免在toArray()中不包含虚拟字段的这种Phalcon“限制”,我在这里提供了一个解决方案:
public $list_virtual_fields = [
    'status_label'
];
protected $status_label;
public function getStatusLabel() {
    return $this->status_label;
}
public function setStatusLabel(string $status_label) {
    $this->status_label = $status_label;
    return $this;
}
public function afterFetch() {
    $this->setStatusLabel('pending');
}