Laravel 控制器:将 Code/Logic 提取到特征中
Laravel Controllers: Extracting Code/Logic Into Trait
我正在创建一些简单的论坛,这就是我的情况:
- 我有两个模型:
Thread
和 Post
;
Thread
只有title
属性,Post
只有body
属性;
- 当用户想要创建(开始)一个新线程时 - 他必须提交一个包含两个字段的表单:title(线程标题)和 body(这将是第一个 post)。
因此,当有人创建新线程时,他也创建了该线程的第一个 post。
用于启动新话题的此表单(包含 标题 和 body 字段)已提交至 ThreadsController@store
我在其中执行以下操作:
public function store(Request $request)
{
// Store a newly created thread in storage.
$thread = new Thread();
$thread->title = $request->title;
$thread = \Auth::user()->threads()->save($thread);
// Store a newly post in storage.
$post = new Post();
$post->body = $request->body;
$post->thread_id = $thread->id;
\Auth::user()->posts()->save($post);
return back();
}
但是,当有人回复时(在线程中创建一个新的 post)- 他将不得不提交一个仅包含 body 字段的表单,然后提交给 PostsController@store
:
public function store(Request $request)
{
// Store a newly post in storage.
$post = new Post();
$post->body = $request->body;
$post->thread_id = $thread->id;
\Auth::user()->posts()->save($post);
return back();
}
如您所见 - 这两个控制器使用相同的代码在存储中存储新 post:
// Store a newly post in storage.
$post = new Post();
$post->body = $request->body;
$post->thread_id = $thread->id;
\Auth::user()->posts()->save($post);
把这段代码移到一个特征中好吗?例如,在 app/http
中,我将创建 traits
目录,并在其中放置 PostsControllerTrait
:
<?php
namespace App\Http\Traits;
use App\Post;
use App\Thread;
use Illuminate\Http\Request;
trait PostsControllerTrait
{
/**
* Store a newly created post in storage.
*
* @param \Illuminate\Http\Request $request
* @param Thread $thread
* @return \Illuminate\Http\Response
*/
public function storePost(Request $request, Thread $thread)
{
$post = new Post();
$post->body = $request->body;
$post->thread_id = $thread->id;
\Auth::user()->posts()->save($post);
}
}
至于名称 PostsControllerTrait - 我在名称中有 "Controller" 的原因是因为将使用此特征仅在控制器中。对我来说,PostsTrait 看起来像是与 Eloquent 模型相关的东西。
最后,您有什么建议 - 在哪里创建 traits
目录:在 app/http
中还是在 app
中?还是偏好问题?
Traits are a mechanism for code reuse in single inheritance languages
such as PHP. A Trait is intended to reduce some limitations of single
inheritance by enabling a developer to reuse sets of methods freely in
several independent classes living in different class hierarchies. The
semantics of the combination of Traits and classes is defined in a way
which reduces complexity, and avoids the typical problems associated
with multiple inheritance and Mixins.
您正在创建一个重用代码,您创建的重用代码大部分不会在其他独立的类中使用。因此,您可以将您的重用代码放到 Post
模型中。
class Post extends Model {
...
public function storePost(User $user, Thread $thread, $body) {
$this->body = $body;
$this->thread_id = $thread->id;
$user->posts()->save($this);
}
...
}
如果使用Laravel模型关系(即一对多关系laravel one to many relationship)将post存储到线程中会简单得多。
定义线程与post的关系,一个线程有多个post。然后简单地保存 $thread->posts()->save($post);
我正在创建一些简单的论坛,这就是我的情况:
- 我有两个模型:
Thread
和Post
; Thread
只有title
属性,Post
只有body
属性;- 当用户想要创建(开始)一个新线程时 - 他必须提交一个包含两个字段的表单:title(线程标题)和 body(这将是第一个 post)。
因此,当有人创建新线程时,他也创建了该线程的第一个 post。
用于启动新话题的此表单(包含 标题 和 body 字段)已提交至 ThreadsController@store
我在其中执行以下操作:
public function store(Request $request)
{
// Store a newly created thread in storage.
$thread = new Thread();
$thread->title = $request->title;
$thread = \Auth::user()->threads()->save($thread);
// Store a newly post in storage.
$post = new Post();
$post->body = $request->body;
$post->thread_id = $thread->id;
\Auth::user()->posts()->save($post);
return back();
}
但是,当有人回复时(在线程中创建一个新的 post)- 他将不得不提交一个仅包含 body 字段的表单,然后提交给 PostsController@store
:
public function store(Request $request)
{
// Store a newly post in storage.
$post = new Post();
$post->body = $request->body;
$post->thread_id = $thread->id;
\Auth::user()->posts()->save($post);
return back();
}
如您所见 - 这两个控制器使用相同的代码在存储中存储新 post:
// Store a newly post in storage.
$post = new Post();
$post->body = $request->body;
$post->thread_id = $thread->id;
\Auth::user()->posts()->save($post);
把这段代码移到一个特征中好吗?例如,在 app/http
中,我将创建 traits
目录,并在其中放置 PostsControllerTrait
:
<?php
namespace App\Http\Traits;
use App\Post;
use App\Thread;
use Illuminate\Http\Request;
trait PostsControllerTrait
{
/**
* Store a newly created post in storage.
*
* @param \Illuminate\Http\Request $request
* @param Thread $thread
* @return \Illuminate\Http\Response
*/
public function storePost(Request $request, Thread $thread)
{
$post = new Post();
$post->body = $request->body;
$post->thread_id = $thread->id;
\Auth::user()->posts()->save($post);
}
}
至于名称 PostsControllerTrait - 我在名称中有 "Controller" 的原因是因为将使用此特征仅在控制器中。对我来说,PostsTrait 看起来像是与 Eloquent 模型相关的东西。
最后,您有什么建议 - 在哪里创建 traits
目录:在 app/http
中还是在 app
中?还是偏好问题?
Traits are a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way which reduces complexity, and avoids the typical problems associated with multiple inheritance and Mixins.
您正在创建一个重用代码,您创建的重用代码大部分不会在其他独立的类中使用。因此,您可以将您的重用代码放到 Post
模型中。
class Post extends Model {
...
public function storePost(User $user, Thread $thread, $body) {
$this->body = $body;
$this->thread_id = $thread->id;
$user->posts()->save($this);
}
...
}
如果使用Laravel模型关系(即一对多关系laravel one to many relationship)将post存储到线程中会简单得多。
定义线程与post的关系,一个线程有多个post。然后简单地保存 $thread->posts()->save($post);