在数据库中存储数据vs在类中存储数据


Storing data in database vs within a class

我正在使用Laravel 4.2构建一个PHP应用程序。该应用程序允许用户访问一个网站并提交一个独特的代码。当提交代码时,他们将获得他们所获得的奖励。奖励可以是"下次购物打九折"、"免费t恤一件"、"下次购物免运费"等等。

我的应用程序中有一个Code模型,它是用户最初提交的唯一代码的模型。因此,申请的第一步是检查他们提交的代码,确保它存在于数据库中,然后回复他们有资格获得的可能奖励列表。

我的第一个想法是使用Reward模型和rewards表将可用奖励存储在数据库中,然后在用户提交其唯一代码后将相关奖励呈现给用户。在我的模板中像这样:

<ul> 
    @foreach($rewards as $reward) 
        <li>{{ $reward->name }}</li>
        <li>{{ $reward->value }}</li>
        <li>{{ $reward->redemption_instructions }}</li>
    @endforeach
</ul>

然而,我现在认为它实际上会更方便我有每个奖励设置为它自己的类。这样我就可以根据自己的需要为每种奖励类型添加定制功能。因此,例如,每个奖励类都有一个名为display()的方法,该方法将输出必要的html以向用户显示奖励。在这种情况下,我的模板看起来像这样:

<ul> 
    @foreach($rewards as $reward) 
        <li>{{ $reward->display() }}</li>
    @endforeach
</ul>

我想弄清楚如何设置这些东西,使它们以这种方式工作。我计划建立类来存储每个奖励所需的信息。例如,可能像这样:

class TenPercentOffNextOrderReward {
    private $name = '10% Off Your Next Order';
    private $description = 'Take 10% off your next order on our website!';
    public function createCoupon() {
        // create a coupon for this reward
    }
}
class FreeShirtReward {
    private $name = 'Free T-Shirt';
    private $description = 'Get a free t-shirt!';
    public function sendShirt() {
        // send tshirt to customer
    }
}

所以,正如你所看到的,每种奖励类型都有不同的功能。这是处理这种设置的最好方法吗?我的rewards表应该只是存储所有奖励的不同类名吗?我真的需要一个rewards表吗?

根据我的经验,拥有一个包含任何冗余数据(如名称,描述等)的表是更好的做法,因为这也有助于以后能够使用web界面输入新的奖励。然后,应该使用一些服务器端逻辑指定特定于奖励的显示规则(就像您在上面的类中所做的那样),或者只是使用某种模板机制并通过template_id引用它们,该template_id将存储在您的。事实上,甚至template_id也可以与匹配的模板一起存储在数据库的查找表中,使其在将来也可编辑。

所以我不仅会把它留在数据库中,而且如果你想自定义你的显示模板,你可能会考虑增强你的数据库来适应它,而不是削减它。

一般来说,数据库表适合存储具有相似属性(如可能的奖励)的东西的多个实例,类适合定义行为(它们如何显示),所以你不会走在错误的道路上考虑使用类,但我只是确保在数据库中实际存储有关这些奖励的数据,并且只在编程代码中处理它们的行为,而不是数据本身。

如果奖励可能有自己的业务逻辑(比如发送衬衫),那么最好使用类。

interface RewardInterface
{
    public function getName();
    public function getDescription();
    public function reward();
}
class NextOrderReward implements RewardInterface
{
    private $percent;
    public function __construct($percent = 10)
    {
        $this->percent = $percent;
    }
    public function getName()
    {
        return $this->percent.'% Off Your Next Order';
    }
    public function getDescription()
    {
        return 'Take '.$this->percent.'% off your next order on our website!';
    }
    public function reward()
    {
        // create coupon
    }
}
class FreeShirtReward implements RewardInterface
{
    public function getName()
    {
        return 'Free T-Shirt';
    }
    public function getDescription()
    {
        return 'Get a free t-shirt!';
    }
    public function reward()
    {
        // send tshirt to customer
    }
}
使用

$rewards = [new NextOrderReward(), new NextOrderReward(20), new FreeShirtReward()];
<ul> 
    @foreach($rewards as $reward) 
        <li>{{ $reward->getName() }} <span>{{ $reward->getDescription() }}</span></li>
    @endforeach
</ul>

一次实例化所有RewardInterface类。当然,所有的构造函数都不应该有参数。

$rewards = [];
foreach (get_declared_classes() as $className) {
    if (in_array('RewardInterface', class_implements($className))) {
        $rewards[] = new $className();
    }
}

注意,如果奖励没有特定的业务逻辑,使用类可能是过度工程。