使用Laravel将响应信息从模型传递到控制器的最佳方法 [英] Best way of passing response information from Model to Controller using 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 Model
and 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屋!