Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 02.01.2017 17:53:19

Сохранение Многие-ко-многим

Опыта очень мало, код работает, но правильно ли это?

Есть форма с данными + input с тегами через "," которые вводит пользователь.


public function store(Request $request)
    {
       //validation

        $post = Post::create([
            'title' => $request->title,
            'slug' => $request->slug,
            'body' => $request->body
        ]);

        if($request->tags == true)
        {
            $tags = explode(', ', $request->tags);
            
            foreach($tags as $tagname)
            {
                $tag = Tag::create([
                    'name' => $tagname
                ]);

                $post->tags()->attach($tag->id);
            };
        };

       //redirect
    }

Нормальный ли это код? Или можно записать куда проще?

Не в сети

#2 02.01.2017 19:01:34

Re: Сохранение Многие-ко-многим

В принципе, код нормальный: читаемый, без велосипедов и извращений - это уже очень хорошо. Но если хочется улучшить, то смотри ниже.

Раз уж используешь create(), то можно использовать $request->all().

if($request->tags == true) можно заменить на if ($request->tags), т.к. if изначально проверяет равно ли выражение true или false. При некоторых подходах, tags вообще не будет в объекте Request, тогда для проверки лучше isset() использовать.

После if {} и foreach {} не нужна точка с запятой. PSR-2 говорит о том, что { должен располагаться в одной строке с if/foreach, а после if нужен пробел.

foreach можно записать короче. attach() лучше вынести за пределы цикла.

public function store(Request $request)
{
   //validation

    $post = Post::create($request->all());

    if ($request->tags) {
        $tags = explode(', ', $request->tags);
        $tagIds = [];

        foreach($tags as $name) {
            $tagIds[] = Tag::create(compact('name'))->id;
        }

        $post->tags()->attach($tagIds);
    }

   //redirect
}

Еще, я бы вынес работу с данными в модель и добавил комментарии. smile

Изменено AlexeyMezenin (02.01.2017 19:07:44)

Не в сети

#3 02.01.2017 22:57:58

Re: Сохранение Многие-ко-многим

Спасибо за советы, можно подробней про вынос данных в модели на моём примере? Я просто совсем зеленый, я максимум делал todo list на голом php. Сейчас вот начал осваивать laravel. Во всех примерах что я видел, модели пустые, только отношения.

Не в сети

#4 03.01.2017 03:00:47

Re: Сохранение Многие-ко-многим

Ларакаст по твоему вопросу:
https://laracasts.com/series/laravel-5- … pisodes/23

Рекомендую посмотреть и другие серии.

Не в сети

#5 03.01.2017 10:30:24

Re: Сохранение Многие-ко-многим

laravel пишет:

Спасибо за советы, можно подробней про вынос данных в модели на моём примере? Я просто совсем зеленый, я максимум делал todo list на голом php. Сейчас вот начал осваивать laravel. Во всех примерах что я видел, модели пустые, только отношения.

Fat models, skinny controllers. Суть в том, что контроллеры должны выполнять только свою функцию - связывать модели, представления, бизнес логику, валидацию и т.д.

В твоем случае, валидацию нужно вынести в отдельный Request класс, например PostRequest, шаблон которого создается с помощью команды php artisan make:request PostRequest.

Создание поста и привязка тегов выносится в модель. Для инъекции классов (модели, Request и пр.) лучше использовать контейнер.

Таким образом, контроллер будет выглядеть примерно так:

....

use App\Requests\PostRequest;
use App\Post;

class PostController extends Controller
{
    protected $post;

    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    public function store(PostRequest $request)
    {
        $this->post->createWithTags($request->all());

        return redirect()->back();
    }

Модель как-то так:

public function createWithTags($data)
{
    $post = $this->create($data);

    if (isset(data['tags'])) {
        $tags = explode(', ', $data['tags']);
        $tagIds = [];

        foreach($tags as $name) {
            $tagIds[] = $this->tag()->create(compact('name'))->id;
        }

        $post->tags()->attach($tagIds);
    }
}

Можно пойти дальше и присваивание/синхронизацию вынести в отдельный метод или в модель тэгов, но это уже зависит от целей, архитектуры и пр.

Не в сети

Подвал раздела