QeePHP使用ActiveRecord更好的封装业务逻辑

blogdaren 2014-12-27 抢沙发 1355人次
通常的 ActiveRecord 实现,无非是封装一个数据库记录。然后把记录的字段变成对象属性而已。QeePHP 的 ActiveRecord 是很不同的,其属性不但可以是记录的字段,还可以映射到不同的方法。
举个最简单的例子:计算订单总金额
订单通常由多个订单项目组成,订单项目包含有商品的ID和购买价格。所以计算订单金额合计就是遍历订单项目,然后用订单项目的价格乘以数量,最后累加。

//传统代码
<?php
$sum = 0;
foreach ($order->items as $item) 
{
    $sum += $item->price * $item->quantity;
}
虽然没什么问题,但是这段代码放在哪里合适呢?
放在控制器:业务逻辑跑到和用户界面打交道的地方去了
放在单独的函数中:还要传入订单对象,而且搞些全局函数,岂不是和面向对象的设计背道而驰,使用时还得载入单独的文件
放在一个公共类中:很好,这个类最后就会变成个大杂烩,什么都沾边
放在 Order 对象中:很不错,我们可以用 $order->getSum() 来获得订单金额合计。
与上面几种方法不同,QeePHP 的 ActiveRecord 可以这样做:
<?php
echo '订单金额合计:';
echo order->sum;
我们数据库的 orders 表并没有 sum 这个字段,那这个属性怎么来的呢?
答案是 QeePHP 允许给 ActiveRecord 对象指定一些虚拟属性。这些属性并不实际存在。当访问对象这些虚拟属性时,QeePHP会自动调用特定的方法来获取属性值。所以订单的金额合计可以改成下面这样:
<?php
class Order extends QDB_ActiveRecord_Abstract
{
    //...... 定义 sum 属性对应到 getSum() 方法 ......    

    function getSum()
    {
         $sum = 0;
         foreach ($this->items as $item) 
         { 
            $sum += $item->quantity * $item->price; 
         }
         
         return $sum;
    }
}
以后我们要获得订单金额不需要 $order->getSum(),只需要 $order->sum 接口。同理,我们可以把 $item->quantity * $item->price 也给封装到订单项目对象中。更进一步,除了属性的读取,属性的写入也可以对应到一个方法。这样我们把订单项目的 quantity 和 price 属性分别指向 setQuantity() 和 setPrice() 方法。这两个方法内部可以完成合法性检查(例如数量必须大于等于1,而价格不能是负数)。以前这些判断方法要写在外部,现在都封装到对象内部了。
// 传统代码
<?php
$quantity = (int)$_POST['quantity'];
$price = (float)$_POST['price'];if ($quantity < 1) 
{
  //... 报错
}
if ($price < 0) 
{
  //... 报错
}
$order_item->quantity = $quantity;
$order_item->price = $price;
//改进代码:
<?php
try 
{
    // 假定 setQuantity() 和 setPrice() 方法会抛出异常
    $order_item->quantity = (int)$_POST['quantity'];
    $order_item->price = (int)$_POST['price'];
    ....
}  
catch (Exception $e) 
{
    //.....
}
这个例子其实没什么实用价值,因为通常这些合计都是预先计算好就存在数据库里面了。
但这个例子很好的表现了如何更好的封装业务逻辑。
并且可以把一个很复杂的逻辑分散到各个对象中去实现,真正体现了面向对象的单一职责原则。

版权声明:除非注明,本文由( blogdaren )原创,转载请保留文章出处。

本文链接:QeePHP使用ActiveRecord更好的封装业务逻辑

发表评论:

您的昵称:
电子邮件:
个人主页: