Laravel 8 принцип создания CRUD с минимальным колличеством кода
В данном уроке мы с вами научимся создавать простой CRUD на Laravel 8 на примере заметок, а заодно и оптимизировать код. Тут будут использованы некоторые ухищрения которые заметно стали экономить мне время при создании приложений на Laravel. Роуты
Давайте начнём с создания роутов. Поскольку это CRUD соответственно у нас должно быть 7 роутов типа:
Route::get('notes', 'NotesController@index');
Route::get('notes/create', 'NotesController@create');
Route::get('notes/store', 'NotesController@store');
Route::get('notes/{id}/edit', 'NotesController@edit');
Route::get('notes/{id}/update', 'NotesController@update');
Route::get('notes/{id}/show', 'NotesController@show');
Route::get('notes/{id}/destroy', 'NotesController@destroy');
Для тех кто не в курсе роуты прописываются в файле routes/web.php
Но право же, для каждой сущности плодить по 7 роутов, ещё и таких типовых, это бесполезная трата времени, лучше уж пойти погулять в лесу или выгулять пса 😉
Роутинг в одну строку
Давайте мы научимся записывать их все одной строкой, вот так например:
# Подключаем контроллер
use App\Http\Controllers\UserController;
# Добавляем роут
Route::resource('notes', 'NotesController');
Контроллер и модель
Теперь сгенирируем сам роутер с этими методами:
php artisan make:controller NotesController --resource --model=Note
Флаг --resource
сразу сделает нам разметку контроллера, а флаг --model
ещё и предложит создать модель на лету. Для этого необходимо ответить Y в ответ на вопрос - A App\Models\Note model does not exist. Do you want to generate it?
И всё! Больше нам ничего писать в роутах не нужно, потому, что они сами создадутся. Не верите? Давайте сами в этом убедимся. Вам всего лишь нужно запустить в терминале команду: php artisan route:list
что бы увидеть все доступные пути в текущем приложении.
Должно получится вот такое великолепие со всеми путями алиасами и методами:
| Method | URI | Name | Action | Middleware
| POST | notes | notes.store | App\Http\Controllers\NotesController@store | web |
| GET|HEAD | notes | notes.index | App\Http\Controllers\NotesController@index | web |
| GET|HEAD | notes/create | notes.create | App\Http\Controllers\NotesController@create | web |
| PUT|PATCH | notes/{note} | notes.update | App\Http\Controllers\NotesController@update | web |
| GET|HEAD | notes/{note} | notes.show | App\Http\Controllers\NotesController@show | web |
| DELETE | notes/{note} | notes.destroy | App\Http\Controllers\NotesController@destroy| web |
| GET|HEAD | notes/{note}/edit | notes.edit | App\Http\Controllers\NotesController@edit | web |
Миграция
Хорошим тоном будет использовать миграции для организации структуры базы данных. Хотя вы можете сделать это и без миграции вручную, на ваше усмотрение. Итак для создания миграции выполните следующую команду в консоли:
php artisan make:migration create_notes_table --create=notes
Теперь вы можете перейти в папку database/migrations
и там найдёте ваш новенький файл миграции create_notes_table.php
Там уже будут стандартные обязательные для всех моделей поля. Давайте немного расширим нашу будущую таблицу добавив в неё поля title и body:
Schema::create('notes', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->timestamps();
});
Всё можно выполнять миграцию:
php artisan migrate --path=/database/migrations/create_notes_table
И напоследок давайте укажем какие поля для массового заполнения доступны в нашей модели, иначе у вас не получится выполнить сохранение по соображениям безопасности в Laravel. Контроллер и представления
В контроллере нам необходимо будет описать все доступные нам методы которые нам создал роутер.
Итак за показ всех доступных заметок у нас будет отвечать метод index()
public function index()
{
$notes = Note::orderBy('id', 'desc')
->paginate(10); // Трюк для получения пагинатора
return view('note.index')->with('nodes', $nodes);
}
Как вы видите здесь мы просто получаем все объекты нашего класса Note
Ну и давайте по быстрому сюда прикрутим вьюшку. Да кстати что бы не засорять папку Views рекомендую для всех типов создавать свои подпапки в нашем случае это будет папка note и в ней вложенный файл index.blade.php у меня получился приметрно такой вид:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Node admin <a href="/node/create" class="btn btn-success"> + Create</a></div>
<div class="panel-body">
<table class="table">
<thead>
<tr>
<th>id</th>
<th>Title</th>
<th>Type</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach($nodes as $node)
<tr>
<td>{{ $node->id }}</td>
<td>{{ $node->title }}</td>
<td>{{ $node->type }}</td>
<td style="text-align:right;">
<a href="/node/{{ $node->id }}" class="btn btn-info">View</a>
<a href="/node/{{ $node->id }}/edit" class="btn btn-success">Edit</a>
<a href="/node/{{ $node->id }}/destroy" class="btn btn-danger">Dellete</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@endsection
Валидация и ошибки
Для того чтобы организовать валидацию подключите в контроллере класс валидации
use Illuminate\Foundation\Validation\ValidatesRequests;
Затем внутри класса контроллера укажите глобальное использование класса валидации
class NoteController extends Controller
{
use ValidatesRequests;
Теперь внутри нашего метода Store можно использовать вот такой простой набор валидаций:
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required',
'slug' => 'uniqe'
]);
Осталось лишь в вывести в шаблоне блок с ошибками например в лайоуте, что бы они были доступны во всех шаблонах:
@if($errors->any())
<div class="alert alert-danger">
<ul>
@foreach($errors->all() as $error)
<li>{{$error}}</li>
@endforeach
</ul>
</div>
@endif