2012-03-28 3 views
0

Возможно ли, что virtualFields var является суммой поля из связанной таблицы?Может ли виртуальное поле основываться на связанных данных в cakephp?

Например, в, скажем, модель счета-фактуры, вы могли бы иметь

public $virtualFields = array(
    'invoiceNett' => 'SUM(InvoiceLine.nett)' 
); 

но, очевидно, только суммированием строк, которые принадлежат к этому счету?

Спасибо.

== Использование CakePHP 2.0

+0

Спасибо за все ответы. Полагаю, теперь это сводится к «должен ли я?», А не «я могу?». Это, как сказано, означает, что это зависит от каждого приложения. – khany

ответ

0

Вы можете использовать обратный вызов afterFind, чтобы получить сумму. Это позволяет избежать сохранения вычисленных значений, которых следует избегать, когда это возможно.

function afterFind($results) 
{ 
    foreach($results as &$result) 
    { 

     /* 
     Use something like: 

     $this->InvoiceLine->find('all', array('fields'  => array('SUM(InvoiceLine.nett) as total'), 
               'conditions' => array('invoice_id' => $result['Invoice']['id']))); 
     */ 
    } 
    unset($result); 
} 
+0

Что случилось с сохранением вычисленных значений? ИМО, это лучший способ пойти, чем делать дополнительный запрос каждый раз, когда вы хотите данные. – Dave

+1

Сохранение значения, которое вычисляется из других полей и значений, приводит к риску дезинхронизации между вычисленным результатом и вычисленными значениями. Что произойдет, если база данных будет изменена из другого сценария, чем ваше приложение Cake?'BeforeSave' не будет вызываться, и вычисленное значение будет ошибочным. Если действительно необходимо сохранить вычисленное значение, было бы лучше использовать триггер в самой базе данных для выполнения расчета. – nIcO

+1

Похоже, это сильно зависит от приложения и данных, которые вы подсчитываете/добавляете. Но я вижу вашу точку зрения для некоторых приложений. – Dave

0

Насколько я знаю, лучший способ сделать это будет иметь фактическое total поле, и обновлять его каждый раз, когда данные сохраняются (вероятно, с afterSave callback method).

So - в любое время InvoiceLine сохраняется, вы запускаете некоторый код для обновления связанного с ним Invoice с новым итогом.

//InvoiceLine model 
public function beforeSave() { 
    //code to update Invoice's "total" field 
} 
0

Теоретически, да, если связанная таблица является ассоциированным соединяющийся (belongsTo и hasOne).

Однако это было бы плохой идеей, потому что, если вы решите не включать эту таблицу, вы создадите ошибку SQL.

Вам будет лучше иметь отдельную функцию захватить данные или создать виртуальное поле, которое было вложенным SQL-запросом.

0

Определение виртуального поля в соответствующей модели бы больше смысла.

Если этого не сделано, вы нарушите шаблон MVC.

Вы можете использовать это виртуальное поле для других родственных моделей.

Если вы не хотите использовать их во всех связанных моделях, вы всегда можете использовать атрибут поля , определяя отношения.

public $hasMany = array(
    'IwantVirtualField' => array(
     'className' => 'MyModel', 
     ... 
    ) 
); 

В модели, когда вы не хотите, виртуальное поле общественности $ belongsTo = массив ( 'IwantVirtualField' => массив ( 'имя класса' => 'MyModel1', 'поля' => массив ('MyModel1.id', 'MyModel1.name') ... ) );

Смежные вопросы