Php 如何避免有口才的模型膨胀?
我一直试图在业余时间在Laravel做一个小游戏,但我遇到了如何最好地构建应用程序的问题,以及某些模型变得非常臃肿的问题 我目前正在使用雄辩的模型,并将功能直接附加到它们上。例如,我有一个用户模型,它从以下函数开始Php 如何避免有口才的模型膨胀?,php,laravel,Php,Laravel,我一直试图在业余时间在Laravel做一个小游戏,但我遇到了如何最好地构建应用程序的问题,以及某些模型变得非常臃肿的问题 我目前正在使用雄辩的模型,并将功能直接附加到它们上。例如,我有一个用户模型,它从以下函数开始 $user->verify() $user->creditGold() $user->debitGold() 这似乎是合理的。随着我向站点添加功能,类开始变得越来越大和笨拙,例如: $user->creditItem() $user->debitIte
$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
类中的一些关注点
- 项目
- 项目
- 探索
- 使用者
- 项目
- 探索
- 用户存储库(用户、物品、库存、设备、任务)
- 库存存储库(项目)
- 设备存储库(项目、集合)
- 探索(探索)
非常感谢您的详细解释,非常有帮助!很高兴我能帮忙:)
<?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);
}
}
}