Laravel 5.6 - Использование трейтов

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

И в моем EventController, и в моем ArticleController у меня есть дублированная функция под названием handleTags(), которая буквально делает одно и то же в каждой модели.

Код выглядит так:

/**
* Handle tagging of this resource
*
* First, get the tags field and make sure it isn't empty
* Convert the string into an array and loop through the array
* Create new tags if they don't exist
*
* @param Request $request: data from the request
* @param int $id: the ID of the model instance have tags synced to
*/
public function handleTags(Request $request, $id)
{
    $event = Event::find($id);

    if ($request->has('tags')) {
        $tags = $request->get('tags');

        if (!empty($tags)) {
            // Turn a String into an array E.g. one, two
            $tagArray = array_filter(explode(", ", $tags));

            // Loop through the tag array that we just created
            foreach ($tagArray as $tag) {
                Tag::firstOrCreate([
                        'name' => ucfirst(trim($tag)),
                        'slug' => str_slug($tag)
                    ]);
            }

            // Grab the IDs for the tags in the array
            $tags = Tag::whereIn('name', $tagArray)->get()->pluck('id');
            $event->tags()->sync($tags);
        } else {
            // If there were no tags, remove them from this model instance
            $event->tags()->sync(array());
        }
    }
}

Можно ли было бы переместить эту функциональность в черту? Что-то вроде Taggable?

Затем вы могли бы вызвать handleTags() в соответствующих контроллерах через свойство, точно так же, как Searchable предоставляет вам доступ к методу search()?

конечно, php вас не остановит

lagbox 17.08.2018 11:32

Сам Laravel уже украшает свой шаблонный контроллер различными чертами, такими как use AuthorizesRequests, DispatchesJobs, ValidatesRequests;, поэтому нет ничего плохого в использовании черт.

apokryfos 17.08.2018 11:34

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

Namoshek 17.08.2018 11:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
3
693
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, что лучшим решением будет сделать черту Модель, я объясню сам.

trait HasTags {

    public function handleTags($tags) 
    {
        $tags = array_filter(explode(", ", $tags))

        $tags = array_map(function () {
            return Tag::firstOrCreate([
                'name' => ucfirst(trim($tag)),
                'slug' => str_slug($tag)
            ]);
        }, $tags)

        $this->tags()->sync(collect($tags)->pluck('id'))
    }

    public function tags()
    {
        return $this->morphMany(Tag::class);
    }

}

Модель

class Event extends Model
{
    use HasTags;
}

Контроллер

$event = Event::find($id);

if ($request->has('tags')) {
    $event->handleTags($request->get('tags'));
}

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

Сделать трейт можно в app/Http/Traits/TaggableTrait.php

Вам просто нужно передать объект вместо идентификатора, чтобы функция не зависела от типа класса.

тогда ваша черта будет примерно такой:

namespace App\Http\Traits;

use App\Tag;

trait TaggableTrait
{
    /**
    * @param Request $request: data from the request
    * @param App\Article | App\Event $object: the model instance have tags synced to
    */
    public function handleTags(Request $request, $object)
    {
        if ($request->has('tags')) {
            $tags = $request->get('tags');

            if (!empty($tags)) {
                  // Turn a String into an array E.g. one, two
                  $tagArray = array_filter(explode(", ", $tags));

                  // Loop through the tag array that we just created
                  foreach ($tagArray as $tag) {
                      Tag::firstOrCreate([
                         'name' => ucfirst(trim($tag)),
                         'slug' => str_slug($tag)
                      ]);
                  }

                  // Grab the IDs for the tags in the array
                  $tags = Tag::whereIn('name', $tagArray)->get()->pluck('id');
                  $object->tags()->sync($tags);
            } else {
                // If there were no tags, remove them from this model instance
                $object->tags()->sync(array());
            }
        }
    }
}

EventController

use App\Http\Traits\TaggableTrait;

class EventController extends Controller
{
    use TaggableTrait;

    /*** ***** */

    public function update(Request $request, $id)
    {
        /** ***/

        $event = Event::findOrFail($id);
        handleTags($request, $event);

       /*** *** */
    }       
}

Можно ли иметь черты на контроллере?

Jesse Orange 17.08.2018 13:13

да, так мы используем Laravel, посмотрите LoginController

bondif 17.08.2018 16:39

Другие вопросы по теме