Квест → Как хакнуть форму
Прошли: 77
Всем привет! Я хотел бы рассмотреть некоторые концепции удаления в Laravel. Иногда нам может понадобиться спроектировать приложение так, чтобы в случае удаления пользователем данных, они не удалялись бы навсегда и все равно оставались в базе данных, но внешне не отображались. Laravel предоставил нам эту функцию "из коробки" под названием softDelete, поэтому я проиллюстрирую как удалить, просмотреть, восстановить и как навсегда удалить удаленные данные. Я назвал эту концепцию Корзиной (Recycle Bin).
Если вы предпочитаете видео, вы можете посмотреть видео на Youtube.
В Soft Delete Laravel данные фактически не удаляются из базы данных, но к ним добавляется атрибут deleted_at, поэтому, когда мы запрашиваем данные из базы данных, Eloquent ищет данные с нулевым значением deleted_at и выдает их, но когда они имеют ненулевое значение deleted_at, обрабатывает их как удаленные.
Поэтому нам нужно добавить его и снова запустить нашу миграцию.
Запуск команды на Шаге 2 создаст файл миграции в database/migrations/, отредактирует файл и добавит $table->softDeletes(); в функцию up(), а также $table->dropSoftDeletes(); в функцию down(). Наш файл миграции выглядит следующим образом:
Нам нужно снова запустить миграцию, чтобы новый столбец был добавлен в существующую таблицу
php artisan migrate
Зайдя в нашу базу данных, вы увидите новый столбец, созданный со значениями Null
Перейдите в app/Models/Project.php и добавьте трейт мягкого удаления. Он скажет модели только добавить дату к уже удаленной модели, но не удалять ее навсегда.
use SoftDeletes;
Также, добавьте путь трейта сверху
use Illuminate\Database\Eloquent\SoftDeletes;
Перейдите в routes/web.php и добавьте маршрут для получения всех удаленных проектов
Route::get('projects/deletedprojects', [ProjectController::class, 'getDeleteProjects'])->name('getDeleteProjects');
В нашем маршруте выше мы указали методы getDeletedProjects в классе ProjectController, поэтому мы создаем этот метод. Перейдите в app/Http/Controllers/ProjectController.php и добавьте его:
public function getDeleteProjects() { $projects = Project::onlyTrashed()->paginate(10); return view('projects.deletedprojects', compact('projects')) ->with('i', (request()->input('page', 1) - 1) * 10); }
Из приведенного выше метода мы использовали Eloquent-функцию onlyTrashed(). Эта функция извлекает только модель с ненулевыми значениями deleted_at, поэтому она будет извлекать только удаленные проекты.
Из нашего метода getDeletedProjects() выше, мы возвращаемся к представлению deletedprojects, поэтому нам нужно создать его, перейти к resources/views/projects/, создать файл deletedprojects.blade.php и скопировать индексную страницу, а затем отредактировать ее:
@extends('layouts.app') @section('content')
@if ($message = Session::get('success'))
{{ $message }}
@endif @foreach ($projects as $project) @endforeach
No | Name | Introduction | Location | Cost | Date Deleted | Action |
---|---|---|---|---|---|---|
{{ ++$i }} | {{ $project->name }} | {{ $project->introduction }} | {{ $project->location }} | {{ $project->cost }} | {{ date_format($project->deleted_at, 'jS M Y') }} |
{!! $projects->links() !!} @endsection
В столбце проекта action из приведенного выше кода мы добавили значок для восстановления удаленного файла - это удалит значение в deleted_at в таблице. Также мы добавили еще один значок для полного удаления проекта - это навсегда удалит проект из базы данных.
Далее, нам нужно создать функцию для восстановления удаленного проекта.
Route::get('projects/deletedprojects/{id}', [ProjectController::class, 'restoreDeletedProjects'])->name('restoreDeletedProjects');
В нашем маршруте мы также указываем метод контроллера restoreDeletedProjects, поэтому мы направляемся к ProjectController и создаем этот метод.
Перейдите в app/Http/Controllers/ProjectController.php и добавьте этот метод:
public function restoreDeletedProjects($id) { $project = Project::where('id', $id)->withTrashed()->first(); $project->restore(); return redirect()->route('projects.index') ->with('success', 'You successfully restored the project'); }
Нам также нужно создать функционал, чтобы полностью удалить проект, который мы не хотим оставлять в базе данных, поэтому давайте создадим маршрут:
Route::get('projects/retoreprojects/{id}', [ProjectController::class, 'deletePermanently'])->name('deletePermanently');
public function deletePermanently($id) { $project = Project::where('id', $id)->withTrashed()->first(); $project->forceDelete(); return redirect()->route('projects.index') ->with('success', 'You successfully deleted the project fromt the Recycle Bin'); }
Вот и всё! Давайте протестируем нашу работу
Мы создали проекты,
Мы также добавили значок корзины, который приведет нас на страницу, на которой мы показываем все удаленные проекты. Затем мы удалили два проекта и перешли на страницу корзины
Это проекты, которые мы удалили с индексной страницы. Здесь у нас есть два значка: один для восстановления удаленных проектов, а другой для окончательного удаления проекта из базы данных.
Мы восстановили проект, и теперь он возвращается на главную страницу. Затем, наконец, мы полностью удалили другой проект.
Вы можете просмотреть весь код в репозитории на GitHub.