symfony:我应该在哪里存储以及如何检索税率?

时间:2016-02-22 15:56:07

标签: symfony

我想知道我应该在哪里存储以及如何检索我将在多个班级中使用的税率。我想将此值设置为参数一次。 parameters.yml是设置它的好地方吗?

/**
* @ORM\Column(type="string")
*/
protected $taxRate;

正如我所说,我将把上面的代码放在多个类中。

请记住,我也想使用模板上的值。

5 个答案:

答案 0 :(得分:0)

此代码看起来像属于实体。您可以通过创建一个抽象类来共享此参数,并创建所有需要的实体,并使该属性扩展为它:

abstract class TaxableEntity {

    /**
    * @ORM\Column(type="string")
    */
    protected $taxRate;
}

class Entity extends TaxableEntity {
    //here you have access to taxRate
}

这种方法有其缺点,这是继承的常见缺点。一旦你获得了这个API(受保护)的许多消费者,你将很难重新分解,而且你还要强制所有的应税实体将该字段映射到数据库中。

另一种方法是将TaxRate的概念包装到ValueObject中。通过这种方式,您可以将其更多地用作常规属性,但具有更强的类型:

class TaxRate {
    private function __construct($rate) {
        $this->rate = $rate;
    }

    public static function fromFloat($value) {
        if(!is_float($value)) {
            throw new \InvalidArgumentException();
        }

        return self($value);
    }

    public static function fromInteger($value) {
        if(!is_int($value)) {
            throw new \InvalidArgumentException();
        }

        return self((float)$value);
    }            
}

无论如何," parameters.yml"与您的对象的属性无关,而是与您项目的属性有关。例如,连接到数据库的必要参数将位于parameters.yml:

database_host: localhost
database_port: 3306
database_user: user
database_password: password
database_name: db_name

通过这种方式,可以通过DIC在服务中注入/使用它们。

答案 1 :(得分:0)

如果您只想将值设置为单个点,那么最简单的解决方案就是使用特征。 好处是你可以使用多个特征,这些特征感觉就像多重继承,而不是一个不灵活且不关心单一责任原则的大型基础类。

特征可能如下所示:

namespace Your\Namespace;

use Doctrine\ORM;

trait TaxRate {
    /**
     * @ORM\Column(type="string")
     */
    protected $taxRate = 'your_default_value';

    // set get methods here
}

然后您可以多次使用它:

namespace Your\Namespace;

use Your\Namespace\TaxRate;

class Entity {
    use TaxRate;

    // more methods here
}

在Symfony中,将来自parameters.yml的参数添加到实体中是相当混乱的。一个想法是使用实​​体作为使用Doctrine的find()时无法正常工作的服务。所以我不推荐这个。

答案 2 :(得分:0)

答案 3 :(得分:0)

您可以在更改税率时处理不同税率的选项是将税率存储在单独的表格中,并从您的实体中引用,可能使用易于使用的特征和DRY代码。

我将使用注释,因为它似乎是你正在使用的。

的appbundle \实体\将TaxRate

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="app_tax_rate")
 * @ORM\Entity(repositoryClass="AppBundle\Entity\TaxRateRepository")
 */
class TaxRate
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var float
     *
     * @ORM\Column(type="decimal", scale=2, column="tax_rate")
     */
    private $rate;

    /**
     * @var \DateTime
     *
     * @ORM\Column(type="datetime", column="active_from")
     */
    private $activeFrom;

    .. getter & setters
}

在此,您将存储税率和费率变为/变为活跃的日期。例如,如果您知道在3个月内费率会发生变化,您可以在准备中将其添加到您的数据库中,但在该日期之前它不会生效。如果需要,您还可以设置过去或未来的实体税率。

的appbundle \实体\ TaxRateRepository

use Doctrine\ORM\EntityRepository;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class TaxRateRepository extends EntityRepository
{
    /**
     * Get current tax rate if available
     *
     * @return TaxRate
     * @throws NotFoundHttpException
     */
    public function getCurrentTaxRateForDate(\DateTime $date)
    {
        return $this->getTaxRateForDate(new \DateTime());
    }

    /**
     * Get tax rate for a specified date if available
     *
     * @param \DateTime $date
     * @return TaxRate
     * @throws NotFoundHttpException
     */
    public function getTaxRateForDate(\DateTime $date)
    {
        $queryBuilder = $this->createQueryBuilder('r');

        $rate = $queryBuilder
            ->where($queryBuilder->expr()->lte('r.activeFrom', ':date'))
            ->setParameter('date', $date)
            ->orderBy('r.activeFrom', 'DESC')
            ->setMaxResults(1)
            ->getQuery()
            ->getResult();

        if (null === $rate) {
            throw new NotFoundHttpException(sprintf(
                'No tax rate available for "%s"',
                $date->format('Y-m-d')
            ));
        }

        return $rate;
    }
}

这" getTaxRateForDate"方法将查找在今天或之前变为活动的所有税率,并在它们变为活动的日期之前对它们进行排序,反过来,然后返回列表中的第一个...所以最后一个税率在给定日期之前变为活动状态。 " getCurrentTaxRate"将执行上述操作但会自动将日期设置为"今天"。

然后,您可以创建一个特征,您可以将该特征放入使用税率的任何实体中,特征包含必要的注释。该关联将是单向的,这意味着您可以从订单/发票/等获得税率,但不能相反。

的appbundle \实体\性状\ TaxableTrait

use Doctrine\ORM\Mapping as ORM;

trait TaxableTrait
{
    /**
     * @ORM\ManyToOne(targetEntity="TaxRate")
     * @ORM\JoinColumn(name="tax_rate_id", referencedColumnName="id")
     */
    private $taxRate;

    .. getters & setters
}

然后,在每个实体中,您只需添加特征,即为该字段添加getter,setter和annotation。

use AppBundle\Entity\Traits\TaxableTrait;

class Order
{
    use TaxableTrait;

    // the rest of your entity
}

要使用此功能,您可以执行类似..

的操作
$order = new Order();
// This, as stated in your custom repository, would cause an exception
// to be thrown if no tax rate was available for "now"
$order->setTaxRate($taxRateRepository->getCurrentTaxRate());
.. set the rest of the order details

$order->getTaxRate();            // would get the tax rate object
$order->getTaxRate()->getRate(); // would get the actual rate
{{ order.taxRate.rate }}         // would get the rate in a twig template

答案 4 :(得分:0)

创建从数据库返回taxrate的服务。

对于性能使用Doctrine二级缓存(如果您访问一次或一百次税后没有区别 - 在SLC中存储第一时间值后 - 直到请求结束)