В данном уроке мы с вами научимся создавать простой 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. Теперь найдите в данном файле вот такие строчки создающие обязательные поля:
Schema::create('notes', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); });
Давайте немного расширим нашу будущую таблицу добавив в неё поля 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