我想知道大多数开发人员如何使用这两个Laravel工具。
在Laravel中,您可以使用Services或Jobs处理业务逻辑(我们只讨论不可排队的作业,只讨论那些在同一进程中运行的作业)。
例如,用户想要创建一个实体,比如说Book,您可以使用服务处理实体创建或调度作业。
使用工作会是这样的:
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);
...
}
}
问题是,你如何选择使用单向或另一种方式?为什么?
当然,在这个问题上有两个“学校”,但我想了解每个学校的利弊。
“业务逻辑”可以用任何东西来处理,所以看起来真正被问到的是哪个选项更好地重复相同的业务逻辑而不重复代码。
Job类通常做一件事,由其handle()
方法定义。从比较中排除排队的作业很困难,因为同步运行这些作业通常会破坏目的,即在当前请求完成并显示响应后处理缓慢,昂贵或不可靠的操作(如调用Web API)给用户。
如果预期所有作业都是同步的,那么与为业务逻辑定义函数没有太大区别。这实际上与调度同步作业非常接近:在调用堆栈的某个地方,它最终运行call_user_func([$job, 'handle'])
来调用作业对象上的单个方法。更重要的是,同步作业缺少重试由于外部原因(如网络故障)而可能失败的作业的机制。
另一方面,服务是一种将逻辑封装在组件周围的简单方法,它们可能不止一件事。在此上下文中,组件可以被视为应用程序的一部分,可以替换为不同的实现,而无需修改使用它的代码。框架中包含的一个完美示例是Filesystem
服务(最常用Storage
门面访问)。
考虑一下您是否通过将书籍插入数据库来存储书籍,而是通过发布到外部API来存储书籍。您可能有一个BookRepository服务,它不仅具有store()
方法,还具有get()
,update()
,list()
,delete()
或任何其他方法。所有这些请求共享用于向外部Web服务进行身份验证的逻辑(如向请求添加标头),并且BookRepository类可以封装该可重用逻辑。您可以在计划的工匠命令,Web控制器,API控制器,作业,中间件等中使用此服务类 - 而无需重复代码。
使用此示例,您可以创建一个用于存储新书的作业,这样您就不会在API响应缓慢时让用户等待(并且可以在出现故障时重试)。在内部,您的工作在运行时调用服务的store()
方法。该服务完成的工作由作业安排。