dk/calculator-bundle

为 Symfony 计算实体属性

dev-develop 2013-06-19 12:53 UTC

This package is not auto-updated.

Last update: 2024-09-23 11:31:11 UTC


README

这是一个简单的包,允许你在 Doctrine 实体中使用动态计算的属性。

安装

要使用 Composer 安装 CalculatorBundle,只需将以下内容添加到您的 composer.json 文件中

// composer.json
{
    // ...
    require: {
        // ...
        "dk/calculator-bundle": "dev-master"
    }
}

然后,您可以通过在您的 composer.json 文件所在的目录中运行 Composer 的 update 命令来安装新依赖项

php composer.phar update dk/calculator-bundle

现在,Composer 将自动下载所有必需的文件,并为您安装它们。剩下的只是更新您的 AppKernel.php 文件,并注册新的包

<?php

// in AppKernel::registerBundles()
$bundles = array(
    // ...
    new DK\CalculatorBundle\DKCalculatorBundle(),
    // ...
);

用法

假设您有一个 User 实体和一个 Transaction 实体,它与 User 有一个 @ManyToOne 关联。进一步假设您想在 User 上有一个 balance 属性,该属性将累加用户的所有交易。这可以通过双向关联和在 PHP 中累加值来实现,但与使用 DQL 相比,这将非常低效。也可以制作自定义仓库(或自定义服务)来手动填充实体,但这意味着您需要以特殊方式访问实体,如果您正在使用序列化(例如,使用 https://github.com/schmittjoh/JMSSerializerBundle),这可能会变得相当复杂。

此包提供另一种解决方案

use DK\CalculatorBundle\Annotation\Calculator;

/**
 * @ORM\Entity
 */
class User {

    /**
     * @Calculator(class="UserCalculator")
     */
    protected $balance;
    public function getBalance() { return $this->balance; }

    /**
     * @Calculator(service="my.calculator.service")
     */
    protected $serviceBalance;
    public function getServiceBalance() { return $this->serviceBalance; }

}

class UserCalculator {

    public function getBalance(User $user, EntityManager $em) {
        $query = $em->createQuery("SELECT SUM(t.value) FROM Transaction t JOIN t.user u WHERE u=:user");
        $query->setParameter('user', $user);
        return (float)$query->getSingleScalarResult();
    }

}
/**
 * @ORM\Entity
 */
class Transaction {

    /**
     * @ORM\Column(type="decimal", scale=2)
     * @JMS\Expose
     */
    protected $value;
    public function setValue($value) { $this->value = $value; return $this; }
    public function getValue() { return $this->value; }

    /**
     * @ORM\ManyToOne(targetEntity="User")
     */
    protected $user;
    public function setUser($value) { $this->user = $value; return $this; }
    public function getUser() { return $this->user; }
    
}

@Calculator 注解的 class 属性中指定一个类(任何类都可以),当实体加载时,将在这个类上调用方法名 get<property>is<property>has<property>。方法将传递实体作为参数,并且当使用 class 而不是 service 时,将传递 EntityManager 作为第二个参数。

未来

这非常快速地拼凑在一起,可以从许多方面进行扩展和改进。

  • 缓存:通过在注解中指定计算字段依赖关系,我们可以在数据库中存储值,并且仅在依赖关系更改时执行新的计算
  • 单元测试