2

我正在为我的应用程序创建一个类似的功能,用户可以在其中喜欢帖子、事件、产品等。

我有一个 LikeController 和一个处理类似功能的 Trait

public function store(Post $post)
{
    $post->like();
    return back();
}

上面的代码是为了赞一个帖子

我不想复制代码并创建单独的函数来对事件或产品执行相同的操作,我想知道如何执行路由模型绑定并让应用程序只执行一个函数,根据什么传递模型信息被喜欢的帖子、事件或产品。

以下代码工作正常,但没有实现 DRY 原则

public function store(Post $post)
{
    $post->like();
    return back();
}

public function store_event(Event $event)
{
    $event->like();
    return back();
}

以下是特征

trait LikeTrait
{

    public function getLikesCountAtrribute()
    {
        return $this->likes->count();
    }

    public function like()
    {
        if (!$this->likes()->where(['user_id' => auth()->id()])->exists()) {
            $this->likes()->create(['user_id' => auth()->id()]);
        }
    }

    public function likes()
    {
        return $this->morphMany(Like::class, 'likeable');
    }

    public function isLiked()
    {
        return !!$this->likes->where('user_id', auth()->id())->count();
    }
}

我的网络路由文件如下

Route::post('post/{post}/likes', 'LikeController@store');
Route::post('event/{event}/likes', 'LikeController@store_event');

所以我想要的结果是调用相同的方法并传递相关的模型。

提前致谢

4

2 回答 2

0

我不知道这是否行得通,但请试一试。

您可以尝试显式绑定。让我们在 App\Providers\RouteServiceProvider 中定义显式绑定:

public function boot()
{
    parent::boot();

    Route::model('post', App\Post::class);

    Route::model('event', App\Event::class);
}

然后定义路线:

Route::post('/posts/{post}/likes', 'LikesController@store');
Route::post('/events/{event}/likes', 'LikesController@store');

最后在控制器中:

class LikesController extends Controller
{
    public function store($object)
    {
        $object->like();
    }
}
于 2020-02-15T09:18:30.637 回答
0

您可以为此类操作制定特定路线,可能是“操作”:

Route::post('actions/like','ActionsController@like')->name('actions.like');

然后在请求中发送您希望对其执行操作的对象,我个人对其进行了散列,散列包含 ID 和 stdClass 中的 class_name(对象类型)。

这就是我个人的做法:我拥有的每个模型都继承Base模型,它包含hash属性,它包含

$hash = new stdClass;
$hash->id = $this->id;
$hash->type = get_class($this);
return encrypt($hash);

这将返回一个字符串值,并加密,您也可以为此设置密码。

然后,假设您在表单或 javascript 中有类似按钮,您可以这样做:

<form action="{{ route('actions.like') }} method="post">
   <input type="hidden" name="item" value="{{ $thisViewItem->hash }}">
   <button type="submit">Like</button>
</form>

这样做,当喜欢一个对象时,您将散列字符串作为数据发送,从而获得$request->get('item')包含对象(id 和类型)的请求。然后在控制器中处理它,但是你喜欢。

如果您通过 javascript 发送此内容,您可能需要对其进行 urlencode。

那么ActionsController@like你可以有这样的东西:

$item = decrypt($request->get('item'));
# Will result in:
# Item->id = 1;
# Item->type = 'App\Post';

$Type = $Item->type;

# Build the model from variable
# Get the model by $item->id
$Model = (new $Type)->find($item->id);

# Like the model
$Like = $Model->like();

// the rest...

我个人更喜欢在字符串中组合和加密 id+type,但是您可以发送 id 并以纯文本形式输入,并有一个如下命名的路由:

Route::post('actions/like/{type}/{id}','ActionsController@like');

然后从 Type+ID 以及你在 trait ( $Model->like()) 中拥有的内容构建模型;

这完全取决于您,但我试图暗示,如果您想在许多地方重用该操作,您可能希望从自身(喜欢、评论)而不是目标(帖子、事件)like开始构建逻辑action)。

我放在这里的代码是写在这里的,而不是从我实际做的事情中粘贴的,我试图让你了解这个概念。你可以随心所欲地编写它。

于 2020-02-13T01:45:44.077 回答