0

模型有没有办法在保存之前计算一个字段?

我有一个这样的架构:

item_id
item_qty
item_price
linetotal

我试图在我的控制器中避免这种代码:

$model->linetotal = $f3->get('POST.item_qty') * $f3->get('POST.item_price');
$model->save();

相反,我想设置我的模型来计算linetotal之前的保存。

也许类似于beforeSavecakephp 中的回调,或者甚至更好,也许我错过了我可以像 f3 上的 Mapper 虚拟字段一样设置它,除了它是一个真实的字段......

4

1 回答 1

1

您要求的内容刚刚在 3.2.2 中发布。DB 映射器现在带有以下钩子:beforeinsert, afterinsert, beforeupdate, afterupdate, beforeerase,aftereraseonload.

所以你可以linetotal像这样实现计算:

class myModel extends \DB\SQL\Mapper {

  static function _beforeupdate($self,$pkeys) {
    $self->linetotal = $self->item_qty * $self->item_price;
  }

  function __construct() {
    $f3=\Base::instance();
    parent::construct($f3->get('DB'),'mytable');
    $this->beforeupdate(array(__CLASS__,'_beforeupdate'));
  }

}

但由于计算也与 INSERT 语句相关,因此您还需要挂钩beforeinsert事件。您可以使用相同的函数来挂钩这两个事件:

class myModel extends \DB\SQL\Mapper {

  static function _linetotal($self,$pkeys) {
    $self->linetotal = $self->item_qty * $self->item_price;
  }

  function __construct() {
    $f3=\Base::instance();
    parent::construct($f3->get('DB'),'mytable');
    $this->beforeinsert(array(__CLASS__,'_linetotal'));
    $this->beforeupdate(array(__CLASS__,'_linetotal'));
  }

}

注意:实现linetotal计算的另一种方法是简单地覆盖映射器set()方法:

class myModel extends \DB\SQL\Mapper {

  function set($key,$val) {
    parent::set($key,$val);
    if ($key=='item_qty' || $key=='item_price')
      $this->linetotal = $this->item_qty * $this->item_price;
  }

}

编辑:

我忘记了第三种选择,实际上在您的情况下看起来更合适:virtual fields。在这种情况下,计算留给数据库引擎。例如:

class myModel extends \DB\SQL\Mapper {

  function __construct(){
    $f3=\Base::instance();
    parent::construct($f3->get('DB'),'mytable');
    $this->linetotal = 'item_qty * item_price';
  }

}

PS:不要忘记linetotal从数据库中删除该字段。

于 2014-03-24T06:34:02.173 回答