Торт php: открытое виртуальное поле не включено в запрос - PullRequest
0 голосов
/ 02 февраля 2020

Я читал некоторые другие вопросы, но они очень старые. Я использую Cake PHP 3.7.9. Я читаю документацию о виртуальных полях, здесь и здесь .

Пока:

Проформа. 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. Чтобы выставить виртуальные поля, вам нужно сделать их видимыми. При определении класса сущности вы можете предоставить список виртуальных полей, которые должны быть выставлены

Таким образом, предоставление виртуальных полей должно позволить мне использовать их в находках.

1 Ответ

1 голос
/ 03 февраля 2020

К сожалению, виртуальные поля не рассчитываются в момент выполнения запроса. Вот несколько альтернативных подходов, которые могут оказаться полезными.

  • Создать представление фактической таблицы (обработать сумму на уровне БД)
  • Создать событие beforeFind в модели таблицы.
...