【问题标题】:Is it a good practice to extend Laravel models more than one layer?将 Laravel 模型扩展到一层以上是一种好习惯吗?
【发布时间】:2015-11-04 09:58:39
【问题描述】:

我正在修改 Laravel 5.1 上的项目

我意识到旧的类已经变得非常复杂,不再真正遵循“单一职责”的原则。

所以我打算这样做:

<?php

class User extends Model
{

}

class SocialUser extends User
{

}

所以我有几个问题,

  1. 有可能实现吗?
  2. 如果是,那么 SocialUser 类是否会链接回同一数据库表,即 Users 并且会与 User 模型冲突本身?
  3. 首先这一切都是一种好的设计实践吗?还是我更好地利用特质?

谢谢。

【问题讨论】:

  • 是的,是的,如果没有关于您的特定用例的更多详细信息,则无法发表评论。

标签: php laravel eloquent laravel-5.1


【解决方案1】:

您正在做的事情(扩展 User 模型)非常好,这是我自己在项目中使用的一种方法。

例如,如果我正在构建的应用程序具有类似商店的功能,那么我可以创建一个 Customer 模型来扩展我的 User 模型,并包含与订单相关的关系:

class Customer extends User
{
    public function orders()
    {
        return $this->hasMany(Order::class, 'customer_id');
    }

    public function worth()
    {
        return $this->orders()->sum(function ($order) {
            return $order->total();
        });
    }
}

在最近的一个项目中,我一直在研究电子邮件活动功能并创建了一个 Recipient 类,该类扩展了 User 模型以添加与活动相关的方法:

class Recipient extends User
{
    public function campaigns()
    {
        return $this->belongsToMany(Campaign::class, 'recipient_id');
    }
}

因为这两个类都扩展了 User 模型,所以我得到了所有这些(和 Eloquent)方法:

$customers = Customer::with('orders')->get();

只要您在基础User 模型中设置表,任何继承它的类都将使用同一个表,即使模型可能有不同的名称(即CustomerRecipientStudent等)。

【讨论】:

    【解决方案2】:

    恕我直言,我会选择存储库模式。在您的情况下,这很有意义。

    我会做以下事情:

    interface UserRepository {
    
        public function find($id); 
        public function getAll(); 
        public function create(array $attributes);
        public function destroy($id);
    
        //you get the point
    
    }
    
    class CoreUserRepository implements UserRepository
    {
    
         //implement the interface rules
    
    }
    
    class SocialUserRepository extends CoreUserRepository
    {
    
         //implement the specific logic related to a SocialUser
    
    }
    

    更新

    正如 Mjh 在 cmets 中描述的那样,简单地在所有 UserTypeRepository 上实现接口会导致重复 - 可能不是您想要的!

    通过扩展您的CoreUser,您可以避免重复并保持适合您情况的设计。

    尽管在您的情况下,可能会说您仍在遵循 SRP,因为 User 模型中的所有内容都与用户相关,但只是用户类型不同。

    为什么选择存储库模式?

    • 您确保您拥有所有User Repositories 都需要实施的合同协议。

    • 代码更容易维护。

    • 业务和数据访问逻辑可以分开测试

    你应该扩展你的用户模型吗?

    在这里,您有模型污染的危险。虽然您可以使用模型做任何事情 - 并非一切都是好主意。

    由于造成的混乱,在这种方法上定义关系将是一件令人头疼的事情。

    【讨论】:

    • 所以基本上,您会选择重复您实际需要的大部分代码,而您只需强制执行一个接口。现在,这对开发有多大帮助?
    • 可读性和可维护性。构建应用程序只是您花费更多时间维护和调试的开始。考虑到这一点,我想让未来从事该项目的开发人员的生活更轻松。如果实现的设计成为问题/性能问题,那么您需要进行相应的重构。
    • 好的,所以你正在解决一个问题,但不是 OP 遇到的问题。他显然追求的是不重复与用户相关的相同功能。您的建议是为他需要的每个类添加一个接口并重复所有这些方法。重复代码与可读性和可维护性有何关系?你不觉得你可能错过了什么吗?
    • 他追求的是一种分离用户类型的设计。我提供的。如果您对 DRY 如此着迷,那么您可以简单地使用 MasterUser implements UserRepo 然后 SocialUser extends MasterUser 避免在 SocialUser 中重复
    • @MartinBean - 我也很抱歉,我草草下结论。存储库不一定是所有问题的答案,但您的答案和此答案都使用继承来避免重复 - 这就是 OP 所追求的,这非常好,我相信我们可以就这部分达成一致。我发现这个答案更详细地说明了存储库如何提供帮助。就个人而言,如果我站在 OP 的立场上(我会选择你的立场),我不会那样做,但我确实发现这个答案对于类似的用例很有帮助且准确。无论如何,再次抱歉,祝你有愉快的一天:)
    猜你喜欢
    • 2020-02-06
    • 2014-12-22
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2013-03-28
    • 2016-06-25
    相关资源
    最近更新 更多