Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何避免有口才的模型膨胀?_Php_Laravel - Fatal编程技术网

Php 如何避免有口才的模型膨胀?

Php 如何避免有口才的模型膨胀?,php,laravel,Php,Laravel,我一直试图在业余时间在Laravel做一个小游戏,但我遇到了如何最好地构建应用程序的问题,以及某些模型变得非常臃肿的问题 我目前正在使用雄辩的模型,并将功能直接附加到它们上。例如,我有一个用户模型,它从以下函数开始 $user->verify() $user->creditGold() $user->debitGold() 这似乎是合理的。随着我向站点添加功能,类开始变得越来越大和笨拙,例如: $user->creditItem() $user->debitIte

我一直试图在业余时间在Laravel做一个小游戏,但我遇到了如何最好地构建应用程序的问题,以及某些模型变得非常臃肿的问题

我目前正在使用雄辩的模型,并将功能直接附加到它们上。例如,我有一个用户模型,它从以下函数开始

$user->verify()
$user->creditGold()
$user->debitGold()
这似乎是合理的。随着我向站点添加功能,类开始变得越来越大和笨拙,例如:

$user->creditItem()
$user->debitItem()
$user->equipItem()
$user->unequipItem()
$user->moveToTown()
$user->takeQuest()
$user->ban()
$user->unban()
// etc. etc. 
有很多感觉非常不相关的代码被塞进了这个类,非常混乱

我开始做的是创建由用户类实例化和持有的帮助器模型。下面的例子

$user->inventory()->creditItem()
$user->inventory()->debitItem()
$user->inventory()->useItem()
打电话和工作很容易,但感觉不正确


对于如何最好地分解概念上属于同一实体的大量代码,有人有什么建议吗?我喜欢这样的想法,因为我认为这是理解OO的最自然的方式,但对我来说,将代码抽象到服务层,让服务类将用户作为参数并对其进行操作(即
$Service->giveItemToUser($user,$item)
)会更好吗

我认为你的用户有很多责任。看看坚实的原则。从单一责任原则开始。
因此,从用户库存操作中取出,并将库存职责放入库存服务中。

是的,我会将业务逻辑抽象到服务或存储库层

这是一篇好文章:

传递带有附加功能的模型类的问题之一是模型类固有的膨胀。基本上,每个模型类都带有整个数据库模型的重量,这相当重。这是典型的活动记录ORM实现,如Elount,而不是数据映射器风格的ORM原则。然而,我猜想,在咬了拉雷维尔的子弹之后,你或多或少地与雄辩的人结下了不解之缘

我发现,使用Laravel的Fluent类可以减轻数据模型的重量,但保持OO风格的接口。为此,我在这里写了一个小扩展:

使用以下工具将其拉入:

composer require delatbabel/fluents
这就是SoC(关注点分离)原则变得非常重要的地方。这意味着确保应用程序的每一部分都只关注它需要关注的内容

关注点分离 让我们首先确定
User
类中的一些关注点

  • 存货
  • 装备
  • 探索
  • 以上是用户将使用的一般资源。其中每一个都有他们关心的事情:

  • 存货
    • 项目
  • 装备
    • 项目
  • 探索
    • 探索
  • 您已经可以看到,我们有几个独立的用户部分需要相同的信息

    逻辑与状态分离 在这一阶段,我们现在需要分离一些其他关切。具体来说,就是业务逻辑(我们想对数据做什么)和数据访问层本身(ORM/模型)。就我个人而言,我喜欢通过使用存储库模式将这些内容分开。在模型上工作并与整个逻辑和应用程序过程有关的类。我觉得模型是状态的一种表示,应该只考虑获取或持久化该状态

    所以我把这些东西分成如下几部分:

  • 模型

    • 使用者
    • 项目
    • 探索
  • 存储库(依赖项)

    • 用户存储库(用户、物品、库存、设备、任务)
    • 库存存储库(项目)
    • 设备存储库(项目、集合)
    • 探索(探索)
  • 代码示例 现在,这给了我一个清晰的定义,我想要的设置和组织。但让我们给出一些示例代码。这与数据的持久化方式无关(手动或通过有说服力的关系等)


    非常感谢您的详细解释,非常有帮助!很高兴我能帮忙:)
    
    <?php namespace App\Repositories;
    
    use App\Models\Item;
    use Illuminate\Support\Collection;
    
    class Inventory {
    
        protected $contents;
    
        public function __construct(Item $item, Collection $contents)
        {
            $this->item = $item;
            $this->contents = $contents;
        }
    
        public function add(Item $item)
        {
            $this->contents->push($item);
        }
    
        public function remove(Item $item)
        {
            $this->contents->forget($item->id);
        }
    
        public function contains(Item $item)
        {
            return $this->contents->has($item->id);
        }
    }
    
    <?php namespace App\Repositories;
    
    use App\Models\Item;
    
    class Equipment {
    
        protected $slots = [
            'head' => null,
            'body' => null,
            'legs' => null,
            'feet' => null,
            'arms' => null,
        ];
    
        public function __construct(Item $item)
        {
            $this->item = $item;
        }
    
        public function get($slot)
        {
            return $this->slots[$slot];
        }
    
        public function set($slot, Item $item)
        {
            $this->slots[$slot] = $item;
        }
    
        public function empty($slot)
        {
            $this->slots[$slot] = null;
        }
    
        public function hasEquipment($slot)
        {
            return !empty($this->get($slot));
        }
    
        public function isEquipped(Item $item) 
        {
            if ($this->hasEquipment($item->slot))
            {
                return $this->get($item->slot)->id == $item->id;
            }
        }
    }
    
    <?php App\Repositories;
    
    use App\Models\User;
    use App\Repositories\Inventory;
    use App\Repositories\Equipment;
    
    class User {
    
        protected $user;
        protected $quests;
        protected $equipment;
        protected $inventory;
    
        public function __construct(
            User $user,
            Quests $quests,
            Equipment $equipment,
            Inventory $inventory
        ) {
            $this->user = $user;
            $this->quests = $quests;
            $this->equipment = $equipment;
            $this->inventory = $inventory;
        }
    
        public function equip(Item $item)
        {
            if ($this->inventory->contains($item))
            {
                $this->equipment->set($item->slot, $item);
            }
        }
    
        public function unequip(Item $item)
        {
            if ($this->equipment->isEquipped($item)) 
            {
                $this->equipment->empty($item->slot);
            }
        }
    }