【问题标题】:Cakephp: exposed virtual field are not included in queryCakephp:查询中不包含暴露的虚拟字段
【发布时间】:2020-05-18 11:09:15
【问题描述】:

我阅读了其他一些问题,但它们已经很老了。我正在使用 CakePHP 3.7.9。 我阅读了有关虚拟字段的文档,herehere

到目前为止:

Proforma.php

class Proforma extends Entity
{
    protected $_accessible = [
        'customer_id' => true,
        'proforma_number' => true,
        'proforma_date' => true,
        'payment_date' => true,
        'proforma_state_id' => true,
        'customer' => true,
        'proforma_state' => true,
        'item_proformas' => true
    ];

    protected  $_virtual = [
        'total'
    ];

    protected function _getTotal()
    {
        $q = TableRegistry::getTableLocator()->get('item_proformas')->find();
        $v = $q
            ->select(['total' => $q->func()->sum('total')])
            ->where(['proforma_id' => $this->id])
            ->first()['total'];
        if ($v == null) $v = 0;
        return $v;
    }
}

在视图中我可以轻松访问该字段:

<td class="text-right"><?= $proforma->item_proformas ? $this->Number->currency($proforma->total) : '' ?></td>

但是当我尝试在 Controller 中进行查询时,即:

$query = $this->Proformas->find();
debug($query);
$query->select(['value' => $query->func()->sum('total')]);

找不到字段total。这里是调试的输出:

object(Cake\ORM\Query) {

    '(help)' => 'This is a Query object, to get the results execute or iterate it.',
    'sql' => 'SELECT Proformas.id AS `Proformas__id`, Proformas.customer_id AS `Proformas__customer_id`, Proformas.proforma_number AS `Proformas__proforma_number`, Proformas.proforma_date AS `Proformas__proforma_date`, Proformas.payment_date AS `Proformas__payment_date`, Proformas.proforma_state_id AS `Proformas__proforma_state_id` FROM proformas Proformas',
    'params' => [],
    'defaultTypes' => [
        'Proformas__id' => 'integer',
        'Proformas.id' => 'integer',
        'id' => 'integer',
        'Proformas__customer_id' => 'integer',
        'Proformas.customer_id' => 'integer',
        'customer_id' => 'integer',
        'Proformas__proforma_number' => 'string',
        'Proformas.proforma_number' => 'string',
        'proforma_number' => 'string',
        'Proformas__proforma_date' => 'date',
        'Proformas.proforma_date' => 'date',
        'proforma_date' => 'date',
        'Proformas__payment_date' => 'date',
        'Proformas.payment_date' => 'date',
        'payment_date' => 'date',
        'Proformas__proforma_state_id' => 'integer',
        'Proformas.proforma_state_id' => 'integer',
        'proforma_state_id' => 'integer'
    ],
    'decorators' => (int) 0,
    'executed' => false,
    'hydrate' => true,
    'buffered' => true,
    'formatters' => (int) 0,
    'mapReducers' => (int) 0,
    'contain' => [],
    'matching' => [],
    'extraOptions' => [],
    'repository' => object(App\Model\Table\ProformasTable) {

        'registryAlias' => 'Proformas',
        'table' => 'proformas',
        'alias' => 'Proformas',
        'entityClass' => 'App\Model\Entity\Proforma',
        'associations' => [
            (int) 0 => 'customers',
            (int) 1 => 'proformastates',
            (int) 2 => 'invoices',
            (int) 3 => 'itemproformas'
        ],
        'behaviors' => [],
        'defaultConnection' => 'default',
        'connectionName' => 'default'

    }
}

为什么即使暴露了虚拟字段也没有插入到查询中?

上面链接的文档说:

请记住,虚拟字段不能用于查找。如果您希望它们成为实体的 JSON 或数组表示的一部分,请参阅公开虚拟字段。

然后:

默认情况下,将实体转换为数组或 JSON 时不会导出虚拟字段。为了公开虚拟字段,您需要使它们可见。在定义实体类时,您可以提供应公开的虚拟字段列表

所以公开虚拟字段应该让我在查找中使用它们。

【问题讨论】:

  • 我不确定“请记住虚拟字段不能在查找中使用”的哪一部分不清楚。看看你是如何在 PHP 中编写一个特殊的函数来进行计算的?您对将其转换为 SQL 代码以使其成为查询的一部分的期望是什么?
  • “公开”一个虚拟字段是指在您将实体(已从 SQL 读取)转换为替代表示时使该字段可用。
  • 因为英语不是我的主要语言,我知道公开虚拟字段会使它们可用于 JSON 和数组(如查询)。在“不能用于查找”之后的“如果你愿意”对我来说听起来像是使用的解决方案!
  • JSON 和数组是输出格式,通过在查询结果上运行 PHP 代码生成。该代码可以使用您的函数添加虚拟字段。但这一切都是在查询运行完成后发生的。
  • 这里肯定有误会。虚拟字段用于对单个实体进行计算。 _getTotal 对订单记录有意义,例如,列包括 pricetaxshipping,并将这三者相加得出该订单的总金额。如果您想对多行进行总计,那是 query functionscustom finder 的工作。

标签: mysql database cakephp


【解决方案1】:

遗憾的是,在运行查询时未计算虚拟字段。以下是一些您可能会觉得有用的替代方法。

  • 创建实际表的视图(在数据库级别处理总和)
  • 在表模型中创建一个 beforeFind 事件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-13
    • 2021-06-18
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多