为 Laravel 应用程序添加服务层的效果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41926737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 15:13:39  来源:igfitidea点击:

The effects of adding a Service Layer to a Laravel application

laravelservice-layer

提问by Kim Prince

I have been developing with Zend Framework for a number of years and am now learning Laravel.

我已经使用 Zend Framework 开发多年,现在正在学习 Laravel。

In my previous applications I usually have a Service Layer that is called by controllers. The Service Layer sits across the top of a Mapper and a Domain Model and is responsible for some application logic, raising events, some input filtering, etc.

在我以前的应用程序中,我通常有一个由控制器调用的服务层。服务层位于映射器和域模型的顶部,负责一些应用程序逻辑、引发事件、一些输入过滤等。

Is there any reason why I should not implement a Service Layer in Laravel? In the examples that I have seen so far, controllers work directly with domain objects (or more accurately, active records).

我有什么理由不应该在 Laravel 中实现服务层?在我目前看到的示例中,控制器直接与域对象(或更准确地说,活动记录)一起工作。

If my Laravel controllers called my Service Layer, would I lose any of the advantages of Laravel? (As far as I can see I can still use Route/Model binding).

如果我的 Laravel 控制器调用我的服务层,我会失去 Laravel 的任何优势吗?(据我所知,我仍然可以使用路由/模型绑定)。

As a secondary question - what would be the best way to implement my Service Layer? As a collection of Service Providers, perhaps?

作为次要问题 - 实现我的服务层的最佳方法是什么?作为服务提供商的集合,也许?

回答by Kevin Peters

I also switched to Laravel coming from Zend and missed my Services. To sooth myself I have implemented a Service namespace which sits in namespace App\Services. In there I do all my Model / Validation handeling. I have experienced no loss of functionality or anything.

我也从 Zend 切换到 Laravel 并错过了我的服务。为了安慰自己,我实现了一个位于命名空间 App\Services 中的服务命名空间。在那里我做我所有的模型/验证处理。我没有遇到任何功能或任何损失。

An example of my controller layout:

我的控制器布局示例:

<?php
namespace App\Http\Controllers;

use App\Services\Contact as ContactService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Lang;

class IndexController extends Controller
{

    /**
     * Create a new controller instance.
     *
     * @param Request $request
     * @return void
     */
    public function __construct(Request $request)
    {
        $this->_request  = $request;
    }

    /**
     * Standard contact page
     * 
     * @return contact page
     */
    public function contact(ContactService $contactService)
    {
        $errors  = null;
        $success = false;
        if ($this->_request->isMethod('post')) {
            $validator            = $contactService->validator($this->_request->all());
            if ($validator->fails()) {
                $errors = $validator->errors();
            } else {
                $contactService->create($validator->getData());
                $success = true;
            }
        }
        return view('pages/contact', ['errors' => $errors, 'success' => $success]);
    }
}

The services return validators, handle cruds, basically do everything that I don't want to see in my Controller just like I had it in my Zend projects.

服务返回验证器,处理 cruds,基本上做我不想在我的控制器中看到的所有事情,就像我在我的 Zend 项目中一样。

Example of Service:

服务示例:

<?php
namespace App\Services;

use Validator;
use Mail;
use App\Models\Contact as ContactModel;

class Contact
{

    /**
     * Get a validator for a contact.
     *
     * @param  array $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    public function validator(array $data)
    {
        return Validator::make($data, [
                'email'     => 'required|email|max:255',
                'phone'     => 'max:255',
                'firstName' => 'required|max:255',
                'lastName'  => 'required|max:255',
                'message'   => 'required'
        ]);
    }

    /**
     * Create a new contact instance after a valid form.
     *
     * @param  array $data
     * @return ContactModel
     */
    public function create(array $data)
    {
        //Handle or map any data differently if needed, just for illustration
        $data = [
            'email'     => $data['email'],
            'firstName' => $data['firstName'],
            'lastName'  => $data['lastName'],
            'language'  => $data['language'],
            'phone'     => $data['phone'],
            'message'   => $data['message']
        ];

        // Send an email
        Mail::send('emails.contact', ['data' => $data], function ($m) use ($data) {
            $m->from(config('mail.from.address'), config('mail.from.name'));
            $m->to(env('MAIL_TO', '[email protected]'), env('MAIL_TO'))->subject('Contact form entry from: ' . $data['firstName']);
        });

        return ContactModel::create($data);
    }
}

回答by abbood

See this post: “Design Pattern?: Service Layer with Laravel 5” @Francoiss https://m.dotdev.co/design-pattern-service-layer-with-laravel-5-740ff0a7b65f.. in addition to the above answer you can also encapsulate the validation code inside a separate validator class

请参阅这篇文章:“设计模式?:使用 Laravel 5 的服务层”@Francoiss https://m.dotdev.co/design-pattern-service-layer-with-laravel-5-740ff0a7b65f.. 除了上述答案您还可以将验证代码封装在单独的验证器类中