Laravel Повторное использование привязки модели маршрута - PullRequest
2 голосов
/ 13 февраля 2020

Я создаю подобную функцию для своего приложения, где пользователи могут лайковать сообщения, события, продукты и т. Д. c.

У меня есть 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');

Итак, я хочу вызвать тот же метод и передать соответствующий модель.

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 15 февраля 2020

Я не знаю, сработает ли это, но, пожалуйста, укажите go.

Вы можете попробовать явное связывание . Давайте определим явные привязки в 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();
    }
}
0 голосов
/ 13 февраля 2020

У вас может быть определенный c маршрут для таких действий, может быть это «действия»:

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

Затем в запросе вы отправляете объект, который вы sh выполняете для действия над Я лично хэшировал, ха sh содержит идентификатор и имя_класса (тип объекта) в stdClass.

Вот как я лично это делаю: Каждая имеющаяся у меня модель наследует 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') содержащий объект (идентификатор и тип). затем обработайте его в контроллере так, как вам нравится.

Если вы отправляете это через javascript, вы можете захотеть его кодировать.

затем в 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 + в строке, но вы можете отправить идентификатор и ввести текст в виде обычного текста и указать маршрут, который будет иметь следующий вид:

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

Затем создайте модель из Type + ID, за которым следует то, что у вас есть в черте ($Model->like());

Все зависит от вас, но я пытаюсь намека что если вы хотите использовать действие like во многих местах, вы можете начать строить логи c, начиная с самого action (лайки, комментарии), а не от цели (посты, события).

Коды, которые я здесь поместил, написаны здесь, а не вставлены из того, что я на самом деле делаю, я пытаюсь донести до вас концепцию. Вы можете написать это по своему усмотрению.

...