使用Laravel将响应信息从模型传递到控制器的最佳方法 [英] Best way of passing response information from Model to Controller using Laravel

查看:60
本文介绍了使用Laravel将响应信息从模型传递到控制器的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Model View Controller体系结构告诉我,我的所有业务逻辑都应在Model内部,而数据流应由Controller处理. 知道了这一点,在我处理Model内的逻辑时,我需要让Controller知道他是否应该重定向到另一个url,重定向回来,在重定向过程中要传递什么样的消息或变量,等等. 最好的方法是什么?

我可以想到一些方法,例如在Model上引发异常并将其捕获在Controller上,或者从Model返回一个数组并在Controller上对其进行处理,但是它们似乎都不是很好的.最简单的方法是在Model内调用Redirect->to()(或back()),并在Controller上返回Model的返回值,但是这似乎破坏了体系结构的规则分离.

是否有正确"的方法?每种方式的利弊是什么?

解决方案

下面的答案很旧. Laravel现在包含了许多处理常见问题的不同方法.

例如,使用Laravel的 FormRequest 作为验证方式轻松地获取有关控制器方法的数据,并工作处理创建/更新的业务逻辑模型.

旧帖子:

这是一个常见的问题,虽然"MVC"模式非常适合作为Web应用程序的基本起点,但我觉得大多数开发人员始终都需要另一种中间服务来进行验证,数据处理以及开发过程中出现的其他问题.

无偏见地回答您的问题:没有正确方式.

要以我个人的偏见来回答您的问题,我觉得大多数开发人员都将使用存储库服务模式来处理控制器与控制面板之间的中间数据处理.模型,并且还具有用于验证的单独类.

我认为,存储库更适合框架和数据不可知的设计(由于其界面驱动的实现),而服务更适合处理业务逻辑/规则.控制器更适合用于处理响应将输入数据传递到存储库或服务.

尽管每种模式的路径都相同:

Request -> Controller (Validation) -> Service -> Model -> Database

Request -> Controller (Validation) -> RepositoryInterface -> Model -> Database

验证放在括号中,因为输入没有从验证器传递到服务/存储库,输入已发送到验证器,输入"OK",然后让控制器知道可以将数据发送到服务/存储库进行处理.

仅当我绝对乐观时,我才使用服务.我不会更改框架或数据源.否则,我将使用存储库.存储库只是设置工作,因为您需要使Laravel通过其IoC解析与存储库类的接口.

服务示例:

服务:

namespace App\Services;

use App\Models\Post;

class PostService
{

    /**
     * @var Post
     */
    protected $model;

    /**
     * Constructor.
     *
     * @param Post $post
     */
    public function __construct(Post $post)
    {
        $this->model = $post;
    }

    /**
     * Creates a new post.
     *
     * @param array $input
     */
    public function create(array $input)
    {
        // Perform business rules on data

        $post = $this->model->create($input);

        if($post) return $post;

        return false;
    }
}

控制器:

namespace App\Http\Controllers;

use App\Services\PostService;
use App\Validators\PostValidaor;

class PostController extends Controller
{
    /**
     * @var PostService
     */
    protected $postService;

    /**
     * @var PostValidator
     */
    protected $postValidator;

    /**
     * Constructor.
     *
     * @param PostService $postService
     * @param PostValidator $postValidator
     */
    public function __construct(PostService $postService, PostValidator $post Validator)
    {
        $this->postService = $postService;
        $this->postValidator = $postValidator;
    }

    /**
     * Processes creating a new post.
     */
    public function store()
    {
         $input = Input::all();

         if($this->postValidator->passes($input)) {
             // Validation passed, lets send off the data to the service
             $post = $this->postService->create($input);

             if($post) {
                 return 'A post was successfully created!';
             } else {
                 return 'Uh oh, looks like there was an issue creating a post.';
             }
         } else {
             // Validation failed, return the errors
             return $this->postValidator->errors();
         }
    }
}

现在有了这种模式,您可以很好地分离所有流程,并清楚地表明每个流程的作用.

对于存储库示例,请使用Google的"Laravel存储库模式".有很多关于此的文章.

The Model View Controller architecture tells me that all my business logic should be inside the Model, while the data flow should be handled by the Controller. Knowing this, while I'm dealing with my logic inside the Model, I need to let the Controller know if he's supposed to redirect to another url, redirect back, what kind of message or variable to pass during the redirection, etc. What is the best way of doing this?

I can think of some ways, like throwing exceptions on the Modeland catching them on the Controller or returning an array from the Model and treating it on the Controller, but none of them seem very nice. The easiest way would be calling the Redirect->to() (or back()) inside the Model and just returning the Model's return on the Controller, but it seem to break the architecture's separation of rules.

Is there a "right" way of doing this? What would be the pros and cons of each way?

解决方案

EDIT:

The answer below is old. Laravel now includes a bunch of different ways of handling common problems.

For example, use Laravel's FormRequest's as a way of validating data easily on controller methods, and Jobs to handle business logic for creating / updating models.

OLD POST:

This is a common question, and while the 'MVC' pattern is nice for a basic starting point for a web app, I feel like the majority of developers always need another intermediate service for validation, data handling, and other problems that come up during development.

To answer your question without bias: There is no right way.

To answer your question with my own personal bias, I feel the majority of developers will use the Repositories or Services pattern to handle intermediate data handling between the controller and the model, and also have separate classes for validation as well.

In my opinion, Repositories are better for a framework and data agnostic design (due their interface driven implementation), and Services are better for handling the business logic / rules. Controllers are better used for handling responses and for passing the input data to the repository or the service.

The paths for each of these patterns are the same though:

Request -> Controller (Validation) -> Service -> Model -> Database

Request -> Controller (Validation) -> RepositoryInterface -> Model -> Database

Validation is in brackets since input isn't passed from the validator to the service / repository, the input sent to the validator, gives the 'OK', and let's the controller know it's ok to send the data to the Service / Repository to be processed.

I only use Services when I'm absolutely positive I won't be changing frameworks or data sources. Otherwise I'll use Repositories. Repositories are just a little more work to setup, since you'll need to make Laravel resolve the interface to your repository class through its IoC.

Services Example:

The Service:

namespace App\Services;

use App\Models\Post;

class PostService
{

    /**
     * @var Post
     */
    protected $model;

    /**
     * Constructor.
     *
     * @param Post $post
     */
    public function __construct(Post $post)
    {
        $this->model = $post;
    }

    /**
     * Creates a new post.
     *
     * @param array $input
     */
    public function create(array $input)
    {
        // Perform business rules on data

        $post = $this->model->create($input);

        if($post) return $post;

        return false;
    }
}

The Controller:

namespace App\Http\Controllers;

use App\Services\PostService;
use App\Validators\PostValidaor;

class PostController extends Controller
{
    /**
     * @var PostService
     */
    protected $postService;

    /**
     * @var PostValidator
     */
    protected $postValidator;

    /**
     * Constructor.
     *
     * @param PostService $postService
     * @param PostValidator $postValidator
     */
    public function __construct(PostService $postService, PostValidator $post Validator)
    {
        $this->postService = $postService;
        $this->postValidator = $postValidator;
    }

    /**
     * Processes creating a new post.
     */
    public function store()
    {
         $input = Input::all();

         if($this->postValidator->passes($input)) {
             // Validation passed, lets send off the data to the service
             $post = $this->postService->create($input);

             if($post) {
                 return 'A post was successfully created!';
             } else {
                 return 'Uh oh, looks like there was an issue creating a post.';
             }
         } else {
             // Validation failed, return the errors
             return $this->postValidator->errors();
         }
    }
}

Now with this pattern, you have a nice separation of all your processes, and a clear indication of what each of them do.

For a repository example, Google 'Laravel Repository Pattern'. There are tons of articles about this.

这篇关于使用Laravel将响应信息从模型传递到控制器的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆