此包已被弃用且不再维护。未建议替代包。

Laravel项目的服务实现

2.0.0 2019-03-29 03:15 UTC

README

Laravel项目的服务实现。

Latest Version on Packagist Build Status Quality Score Total Downloads

Bright Components

免责声明

BrightComponents命名空间下的包基本上是我避免在我所有项目中复制粘贴我喜欢的基本功能的一种方式。这里没有突破性的东西,只是为表单请求、控制器、自定义规则、服务等提供了一些额外的功能。

灵感

BrightComponents的服务包解决了我一直以来的一个痒点。我经常使用单动作控制器与响应者类结合使用,同时使用服务类来收集/处理数据。在这个包的早期版本中,我将服务类建模为Laravel的作业。在这个过程中,我使用了一个类似于Laravel的调度器的ServiceCaller。到目前为止,我已经重构为基本上创建一个类并调用一个方法。然而,在这个时候,我仍然保留了ServiceCaller组件,因为我可能在接近1.0版本时需要它。

示例

namespace App\Http\Controllers\Tasks;

use App\Http\Controllers\Controller;
use App\Services\StoreNewTaskService;
use App\Http\Requests\StoreNewTaskRequest;
use App\Http\Responders\Task\StoreResponder;
use BrightComponents\Services\Traits\CallsServices; // the trait could be added to your parent Controller class

class Store extends Controller
{
    use CallsServices;

    /**
     * The service used to store a new task.
     *
     * @var \App\Http\Responders\Task\StoreResponder
     */
    private $responder;

    /**
     * Construct a new Store controller.
     *
     * @param  \App\Http\Responders\Task\StoreResponder  $responder
     */
    public function __construct(StoreResponder $responder)
    {
        $this->responder = $responder;
    }

    /**
     * Handle the task store action.
     *
     * @param  \App\Http\Requests\StoreTaskRequest  $request
     *
     * @return \Illuminate\Http\Response
     */
    public function __invoke(StoreTaskRequest $request)
    {
        $task = $this->call(StoreNewTaskService::class, ($request->validated()));

        return $this->responder->respond($request, $task);
    }
}

我的控制器只是简单地将脏活推给服务来处理,然后使用响应者发送响应。一个非常干净的方法。

安装

您可以通过composer安装此包。从您的项目目录,在您的终端中输入

composer require bright-components/services

注意:在1.0版本发布之前,可能会在次要版本之间添加主要功能和错误修复。为了保持稳定性,我建议使用“0.8.*”形式的限制。这将采取以下形式

composer require "bright-components/services:0.8.*"

在Laravel > 5.6.0中,ServiceProvider将自动检测并注册。如果您正在使用Laravel的较旧版本,请将包服务提供者添加到您的config/app.php文件中的'providers'数组

'providers' => [
    //...
    BrightComponents\Services\ServicesServiceProvider::class,
    //...
];

包配置

如果您想更改任何包配置选项,请在您的终端中运行以下命令

php artisan vendor:publish

并选择'BrightComponents/Services'选项。

这将把包配置(service-classes.php)复制到您的'config'文件夹中。请参阅下面的配置文件,了解所有可用的选项

return [
    /*
    |--------------------------------------------------------------------------
    | Namespaces
    |--------------------------------------------------------------------------
    |
    | Set the namespace for Service classes.
    |
    */
    'namespace' => 'Services',

    /*
    |--------------------------------------------------------------------------
    | Suffixes
    |--------------------------------------------------------------------------
    |
    | Set the suffix for the Service classes.
    |
    */
    'suffix' => 'Service',

    /*
    |--------------------------------------------------------------------------
    | Method Name
    |--------------------------------------------------------------------------
    |
    | Set the method name for handling services.
    |
     */
    'method' => 'run',

    /*
    |--------------------------------------------------------------------------
    | Duplicate Suffixes
    |--------------------------------------------------------------------------
    |
    | If you have a Service suffix set in the config and try to generate a Service that also includes the suffix,
    | the package will recognize this duplication and rename the Service to remove the extra suffix.
    | This is the default behavior. To override and allow the duplication, change to false.
    |
    */
    'override_duplicate_suffix' => true,

    'cached_services' => [
        /*
        |--------------------------------------------------------------------------
        | Namespaces
        |--------------------------------------------------------------------------
        |
        | Set the namespace for cached Service classes. The namespace is relative to the Services namespace defined above.
        |
        */
        'namespace' => 'Caching',

        /*
        |--------------------------------------------------------------------------
        | Namespaces
        |--------------------------------------------------------------------------
        |
        | Set the prefix for cached Service classes.
        |
        */
        'prefix' => 'Cached',

        /*
        |--------------------------------------------------------------------------
        | Parent class
        |--------------------------------------------------------------------------
        |
        | The shortname for the parent cached services class.
        |
        */
        'parent' => 'BaseCachedService',

        /*
        |--------------------------------------------------------------------------
        | Classes
        |--------------------------------------------------------------------------
        |
        | The mapping of cached services to their base service.
        |
        */
        'classes' => [],
    ],
];

使用

一旦安装了包并复制了配置(可选),您就可以开始生成您的服务。

生成服务类

在您的项目目录内部,在您的终端中运行

php artisan adr:service StoreNewTask

基于上面的配置选项,这将创建一个'App\Services\StoreNewTaskService'类。

注意,默认情况下,当您'调用'服务时将调用'run'方法。您可以在配置文件中更改此方法名。

示例服务类

// Service Class
namespace App\Services;

use App\Models\Repositories\TaskRepository;
use BrightComponents\Common\Payloads\Payload;

class StoreNewTaskService
{
    /**
     * The parameters for building a new Task.
     *
     * @var array
     */
    public $repo;

    /**
     * Construct a new StoreNewTaskService.
     *
     * @param  \App\Models\Repositories\TaskRepository  $repo
     */
    public function __construct(TaskRepository $repo)
    {
        $this->repo = $repo;
    }

    /**
     * Handle the call to the service.
     *
     * @param  mixed  $params
     *
     * @return mixed
     */
    public function run($params)
    {
        $task = $this->repo->create($params);

        return new Payload(['task' => $task]);
    }
}

如上例所示,只需在服务构造函数中声明任何依赖项。这些依赖项将由Laravel从容器中解析。调用服务时传递的任何参数都将传递到服务的"run"方法中。

为了保持一致性,您可以选择在Service类的返回值中包裹一个Payload对象。Payload类包含在bright-components/common包中。Payload是用于将数据发送回控制器的包装器。您可以扩展AbstractPayload类,或者使用包含的通用Payload类(Payload和ErrorPayload)。这些payload类目前没有任何功能。在1.0版本之前的未来版本中可能会引入这些类的方法和/或属性。

生成缓存的Service类

缓存服务目前是WIP。完成后我们将更新此处。可能可以通用到装饰器服务?

如何调用服务

目前有几种调用服务的方式。理想情况下,我希望只有几种选择。随着我们接近1.0版本,这些选项可能会发生变化。

首先,您可以使用包含的'CallsServices'特质

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\StoreNewTaskService;
use BrightComponents\Services\Traits\CallsServices;

class StoreTaskController extends Controller
{
    use CallsServices;

    public function store(Request $request)
    {
        $task = $this->call(StoreNewTaskService::class, ($request->all()));

        return view('tasks.show', ['task' => $task]);
    }
}

下一个选项是通过依赖注入包含ServiceCaller,然后使用"call"方法

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\StoreNewTaskService;
use BrightComponents\Services\ServiceCaller;

class StoreTaskController extends Controllerr
{
    private $caller;

    public function __construct(ServiceCaller $caller)
    {
        $this->caller = $caller;
    }

    public function store(Request $request)
    {
        $task = $this->caller->call(StoreNewTaskService::class, ($request->all()));

        return view('tasks.show', ['task' => $task]);
    }
}

接下来,服务具有调用自身的能力

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\StoreNewTaskService;

class StoreTaskController extends Controller
{
    public function store(Request $request)
    {
        $task = StoreNewTaskService::call($request->all());

        return view('tasks.show', ['task' => $task]);
    }
}

最后,也是最常见的方式,是在您的控制器或动作中注入Service类,并调用'run'方法

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\StoreNewTaskService;

class StoreTaskController extends Controllerr
{
    private $service;

    public function __construct(StoreNewTaskService $service)
    {
        $this->service = $service;
    }

    public function store(Request $request)
    {
        $task = $this->service->run($request->all());

        return view('tasks.show', ['task' => $task]);
    }
}

关于Service类参数的说明

在调用服务类时,您可以传递多个参数

$this->call(MyService::class, $params, $anotherParam);
// or
$this->serviceCaller->call(MyService::class, $params, $anotherParam):
// or
MyService::call($params, $anotherParam);
// or
$service->run($params, $anotherParam);

我发现通常一个参数数组就足够了,但您可能会有需要传递另一个参数的情况。在调用Service时添加这些参数,这些参数将被传递到服务的'run'方法中。确保当服务被调用时,'run'方法的参数与使用的参数匹配

// MyServiceClass

public function run($data, $mystring, $anotherString)
{
    //
}

// In your controller
MyService::call($params, $string1, $string2);

测试

composer test

变更日志

请参阅变更日志获取有关最近更改的更多信息。

贡献

请参阅贡献指南以获取详细信息。

安全

如果您发现任何安全相关的问题,请通过电子邮件clay@phpstage.com而不是使用问题跟踪器。

路线图

我们计划尽快处理灵活性/配置,以及发布一个与框架无关的包版本。

致谢

许可

MIT许可(MIT)。请参阅许可文件获取更多信息。