Я ищу более чистый способ проверки тегов при хранении сообщения.
Вся проверка ввода происходит в рамках моего пользовательского запроса StorePostRequest
, Проблема в том, что мне нужно проверить, существуют ли данные теги в базе данных, разрешены только существующие теги. Функция $request->input('tags')
возвращает строку со значениями, разделенными запятыми, например: Tag1,Tag2,Tag3
,
Вот код:
/**
* Store a newly created resource in storage.
*
* @param StorePostRequest $request
* @return Response
*/
public function store(StorePostRequest $request)
{
//THIS PIECE OF CODE
$tags = explode(',', $request->input('tags'));
$tags = Tag::whereIn('title', $tags)->lists('id');
if(count($tags) < 1)
{
return redirect()->back()->withInput()->withErrors([ trans('tags.min') ]);
}
else if(count($tags) > 5)
{
return redirect()->back()->withInput()->withErrors([ trans('tags.max') ]);
}
//TILL HERE
$post = $request->user()->posts()->create([
'slug' => unique_slug('Post', $request->input('title')),
'title' => $request->input('title'),
'description' => $request->input('description'),
'summary' => $request->input('summary'),
]);
$post->tags()->attach($tags);
return redirect(route('theme.post.show', [$theme->slug, $post->slug]))->with(['success', trans('messages.post.store')]);
}
Код немного неаккуратный и избыточный при использовании его в нескольких контроллерах.
Чтобы решить эту проблему, я создал ValidationServiceProvider
расширить основные правила валидатора. Что-то вроде этого:
$this->app['validator']->extend('tags', function ($attribute, $value, $parameters)
{
$tags = explode(',', $value);
$tags = Tag::whereIn('title', $tags)->lists('id');
if(count($tags) < 1 || count($tags) > 5))
{
return false;
}
});
Довольно аккуратно. Дело в том, что мне все еще нужно иметь доступ к $tags
переменная внутри контроллера (из-за ->attach($tags)
).
Есть ли лучший способ решения этой проблемы? Или я должен перестать думать и просто использовать (и повторить) код, который у меня есть?
Заранее спасибо, надеюсь, что это имеет смысл.
Я предполагаю, что вы понимаете использование этого класса, потому что я видел, что вы определили StorePostRequest
учебный класс. Итак, просто для пояснения, rules
Метод может выглядеть так:
public function rules()
{
return [
'tags' => ['required', 'tags'] //kb
];
}
Наконец, со всеми инструментами в правильном месте, вы только заставляете манипулировать данными в ваших контроллерах следующим образом:
public function store(StorePostRequest $request)
{
// at this point, the tags are already validated, so we, proceed get them:
$tags = explode(',', $$request->get('tags'));
$post = $request->user()->posts()->create([
'slug' => unique_slug('Post', $request->input('title')),
'title' => $request->input('title'),
'description' => $request->input('description'),
'summary' => $request->input('summary'),
]);
$post->tags()->attach($tags);
return redirect(route('theme.post.show', [$theme->slug, $post->slug]))->with(['success', trans('messages.post.store')]);
}
Имейте в виду, что заражение
StorePostRequeststore
в функции контроллера он уже проверяет и запускает правила.
Этого достаточно, если вы действительно правильно определили правила StorePostRequest.
foreach($request->tags as $k=>$tags){
$this->validate($request, [
'tags.'.$k => 'required|string|max:20'
]);
}