php - 为什么我应该在 Laravel 中同时使用特征和服务?

标签 php laravel model-view-controller eloquent traits

我有一个简单的问题我正在努力回答,我希望你们能帮助我。所以我正在 laravel 上开发应用程序。我想让 Controller 清楚,所以我在模型类本身中有复杂的查询(我不想使用存储库)。如果我想要一些可用于许多模型的功能,我会将这个功能放入特征中,并在需要时使用它。所以这是我的问题.. 我需要服务类吗?特质还不够吗?

最佳答案

假设您有一个需要 Cat 的 trait 方法。型号和 Dog模型。每次使用该特征时,都需要传入 Cat 的实例。和 Dog 的实例让它完成它的工作。

最终会变得很累。如果你最终添加了一个特性并且特性现在需要一个 Bird 会发生什么?模型?现在你有很多代码要修改,只是为了开始传递 Bird每次你想使用它时,它的特征中的方法。

这是服务类变得非常方便的地方。在服务类的构造函数中,您可以注入(inject) User , Permission , 和 Role像这样的模型...

public function __construct(Cat $cat, Dog $dog, Bird $bird)
{
    $this->cat = $cat;
    $this->dog = $dog;
    $this->bird = $bird;
}

然后你可以向你的应用程序添加一个服务提供者,它指示 Laravel 如何通过传入适当的模型来创建这个服务类。从那里,您可以将该服务自动注入(inject)到您的 Controller 中,只要您认为合适,当前您只是为此使用一个特征。

这意味着如果您需要添加依赖项,您只需要更新一个,可能是两个文件。服务类本身向构造函数和可能的服务提供者添加附加项。所有使用它的 Controller 都不需要更新以将这些附加项传递给构造函数,因为这是由 Laravel(更恰本地说是 IoC 容器)处理的。

这对测试也非常有利。将依赖项注入(inject)类时,只需设置测试环境来模拟这些依赖项,而不是尝试动态构建模拟以传递给 trait 方法,会更容易。测试特征也更加困难,因为需要use该特征以便测试该特征的方法。
// we can use a service provider to tell laravel how to create this service (https://laravel.com/docs/5.7/providers)
class PetService
{
    protected $cat;
    protected $dog;
    protected $bird;

    public function __construct(Cat $cat, Dog $dog, Bird $bird)
    {
        $this->cat = $cat;
        $this->dog = $dog;
        $this->bird = $bird;
    }

    public function doStuff()
    {
        //  does things with $this->cat, $this->dog, $this->bird
    }
}


class PetController
{
    // use PetTrait;

    protected $petService;

    // laravel will automatically create the PetService for us and pass it into the constructor when building this controller (https://laravel.com/docs/5.7/container)
    public function __construct(PetService $petService) 
    {
        $this->petService = $petService;
    }

    public function someControllerMethod()
    {
        // $this->doStuff(new Cat, new Dog, new Bird); // In order to modify this method, we need to update each time it's used.
        $this->petService->doStuff(); // We don't need to worry about passing in arguments since it's handled by the service container when constructing the pet service and can make changes without updating each controller that uses it.
    }
}

更详细地说,如果您决定 Bird 会发生什么?现在需要 Chicken 的实例, Turkey , Dodo以使其正常运行。现在你需要再次检查所有使用 Bird 的特征。并更新每个以传入其每个依赖项的实例。

这就是为什么使用服务容器和提供者来规划和构建服务类的依赖关系是有利的。它极大地提高了应用程序的可维护性。到目前为止,它在一个非常庞大且复杂的应用程序中是最有益的。

但是,如果您的应用程序相当简单,它可能没有那么有用,甚至可能会增加不必要的复杂性,并且如果特性对您更有意义,那么实际上在此时使用它们可能会更好。让你的应用在不需要的时候灵活地使用服务是不好的。

关于php - 为什么我应该在 Laravel 中同时使用特征和服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53744359/

相关文章:

php - CakePHP 2.0 对象不是数组

javascript - 将 Elastic Beanstalk PHP 应用程序环境变量传递给 Javascript

php - Laravel:使用分页显示来自 mysql 的 10 个随机行的查询

java - 动态按钮上的事件监听器

php - Laravel - 无法使用 Blade 从多维数组中获取值

php - Order By before Group By 使用 Eloquent (Laravel)

model - Laravel 查询模型关系

javascript - 面向 Ajax 的 JavaScript 的 MVC 替代方案

python - wxPython 的 MVC 框架

php - 在 php 站点中流式传输音频文件