gpt4 book ai didi

php - Eloquent 模型如何避免模型臃肿?

转载 作者:行者123 更新时间:2023-12-04 15:43:40 26 4
gpt4 key购买 nike

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

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

$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 类实例化和持有的辅助模型。下面的例子
$user->inventory()->creditItem()
$user->inventory()->debitItem()
$user->inventory()->useItem()

它很容易调用和使用,但感觉不正确。

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

最佳答案

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

关注点分离

让我们首先确定您的 User 中的一些问题。类(class)。

  • 库存
  • 设备
  • 任务

  • 以上是您的用户将使用的一般资源。这些中的每一个也有他们关心的事情:
  • 存货
  • 项目
  • 设备
  • 项目
  • 任务
  • 任务

  • 您已经可以看到我们有几个不同的用户部分需要相同的信息。

    将逻辑与状态分离

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

    所以我把这些东西分开了:
  • 楷模
  • 用户
  • 项目
  • 任务
  • 存储库(依赖项)
  • UserRepository(用户、元素、库存、设备、任务)
  • InventoryRepository (项目)
  • EquipmentRepository (Item, Collection)
  • QuestRepository (Quest)

  • 代码示例

    现在,这让我对我想要的设置和组织有了一个清晰的定义。但是让我们给出一些示例代码。这与数据的持久化方式无关(手动或通过 Eloquent 关系等)。
    <?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);
    }
    }

    InventoryRepository 只关心管理它的项目集合。添加它们,删除它们并检查是否有其他项目。为此,它取决于 Collection 类和 Item 模型。
    <?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;
    }
    }
    }

    另一个类只与当前装备的元素有关。装、卸等。

    把它放在一起

    一旦定义了单独的部分,您就可以将它们全部放入您的 UserRepository 类中。通过将它们作为依赖项拉入,UserRepository 中包含的代码将明确地基于用户管理,同时访问加载的依赖项可为您提供所需的所有功能。
    <?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);
    }
    }
    }

    这又只是一个组织代码的概念。在这种类型的设置中,您希望如何将数据加载和持久保存到数据库中取决于您。这也不是组织代码的唯一方法。这里的要点是如何将代码分解成单独的部分和关注点,以更好地将功能模块化和隔离成更易于管理和消化的位。

    我希望这对您有所帮助,不要犹豫,提出任何问题。

    关于php - Eloquent 模型如何避免模型臃肿?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34716080/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com