Laravel模式-工作与服务的使用

时间:2018-10-19 15:36:07

标签: php laravel laravel-5 model-view-controller service-layer

我想知道大多数开发人员如何使用这两个Laravel工具。

在Laravel中,您可以使用服务或作业来处理业务逻辑(让我们仅讨论不可排队的作业,只讨论那些在相同流程中运行的作业)。

例如,一个用户想要创建一个实体,比如说一本书,您可以通过服务来处理该实体的创建或调度一个工作。

使用工作是这样的:

class PostBook extends Job
{
    ...
    public function handle(Book $bookEntity)
    {
        // Business logic here.
    }
    ...
}

class BooksController extends Controller
{
    public function store(Request $request)
    {
        ...
        dispatch(new PostBook($request->all()));
        ...
    }
}

使用服务,就像这样:

class BookService
{
    public function store(Request $request)
    {
        // Business logic here.
    }
}

class BooksController extends Controller
{
    public function store(Request $request)
    {
        ...
        // I could inject the service instead.
        $bookService = $this->app()->make(App\Services\BookService::class);
        $bookService->store($request);
        ...
    }
}

问题是,您主要选择哪种方式使用另一种方式?为什么?

在这件事上肯定有两所“学校”,但我想了解每所学校的利弊。

1 个答案:

答案 0 :(得分:7)

“业务逻辑”可以用任何东西进行处理,因此似乎真正要问的是哪个选项更适合重复相同的业务逻辑而不重复代码

工作类通常会执行一件事,这由其handle()方法定义。很难从比较中排除排队的作业,因为同步运行它们通常会破坏目的,即在当前请求得到处理后 处理缓慢,昂贵或不可靠的操作(例如调用Web API)。完成并向用户显示了响应。

如果希望所有作业都是同步的,则与为您的业务逻辑定义功能没什么不同。实际上,这与调度同步作业的工作非常接近:在调用堆栈的某个地方,它最终运行call_user_func([$job, 'handle'])来调用作业对象上的单个方法。更重要的是,同步作业缺少用于重试可能由于外部原因(例如网络故障)而失败的作业的机制

另一方面,

服务是一种将逻辑封装在组件周围的简便方法,它们可能会做一件事 >。在这种情况下,组件可能被认为是您的应用程序的一部分,可以将其替换为其他实现,而无需修改使用该组件的代码。框架中包含的一个完美示例是Filesystem服务(最常通过Storage门面访问)。

考虑是否没有通过将书籍插入数据库来存储书籍,而是通过发布到外部API来进行存储。您可能拥有一个BookRepository 服务,该服务不仅具有store()方法,还具有get()update()list(),{{1 }}或任何其他方法。所有这些请求都共享用于对外部Web服务进行身份验证的逻辑(例如,向请求中添加标头),并且BookRepository类可以封装该可重用逻辑。您可以在计划的工匠命令,Web控制器,API控制器,作业,中间件等内部使用此服务类-无需重复代码。

使用本示例,您可以创建一个 Job 来存储一本新书,这样您就不会在API响应速度慢时让用户等待(并且在出现故障时可以重试)。在内部,您的作业在运行时会调用您的 Service的 delete()方法。服务完成的工作由工作安排。