Laravel-实施模型工厂设计模式

时间:2019-04-02 17:50:14

标签: laravel-5 model factory

我正在尝试使用Laravel模型实现Factory Design模式。我有一个奖励模型,目前可以有两种类型,积分奖励或现金返还奖励。

我所有的班级都有奖励

class Reward extends Model
{
    // class Reward stuff
}

我还制作了两个扩展Reward的类(它们的两个都带有引用其类型的globalScope):

class PointsReward extends Reward
{
    protected $table = "rewards";

    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(
            'points', 
            function (Builder $builder) {
                $builder->whereHas(
                    'rewardType', 
                    function ($subQuery) {
                        $subQuery->where('type', 'Points');
                    }
                );
            }
        );
    }
}

和CashbackReward:

class CashbackReward extends Reward
{
    protected $table = "rewards";

    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(
            'cashback', 
            function (Builder $builder) {
                $builder->whereHas(
                    'rewardType', 
                    function ($subQuery) {
                        $subQuery->where('type', 'Points');
                    }
                );
            }
        );
    }
}

现在我正在尝试制作Factory类:

class RewardFactory
{
    const CASHBACK_REWARD = 0;
    const POINTS_REWARD = 1;

    static function create(int $rewardType, array $data)
    {
        switch($rewardType){
        case self::CASHBACK_REWARD:
            return CashbackReward::create($data);
            break;
        case self::POINTS_REWARD:
            return PointsReward::create($data);
            break;
        default:
            throw new Exception("Not supported");
        }
    }

    static function find(int $id) : Reward
    {
        $main = Reward::find($id);

        switch($main->rewardType->type){
        case 'Points':
            return PointsReward::find($id);
            break;
        case 'Cashback':
            return CashbackReward::find($id);
            break;
        default:
            throw new Exception("Not supported");
            return null;
        }
    }
}

我的问题是在find方法上。其目的是通过id查找奖励(如Laravel方法)并根据其rewardType->type属性返回对象。

当然可以,但是我必须执行2个数据库查询才能实例化该对象。有更好的方法吗?如果没有,有没有办法只执行一个查询?

0 个答案:

没有答案