app/Models/Post.php
В app/Models/Post.php добавим несколько функций:
protected $fillable = ['title', 'description', 'content', 'category_id', 'thumbnail']; public static function uploadImage(Request $request, $image = null) { if ($request->hasFile('thumbnail')) { if ($image) { Storage::delete($image); // удаляем } $folder = date('Y-m-d'); return $request->file('thumbnail')->store("images/{$folder}"); } return null; } public function getImage() { if ($this->thumbnail) { return asset("/uploads/{$this->thumbnail}"); } return asset("no-image.jpg"); }
Найдем картинку и поместим ее в public/no-image.jpg . Картинка обозначает, что изображение отсутствует.
edit.blade.php
Скопируем весь код из create.blade.php в edit.blade.php и изменим его, получится так:
@extends('admin.layouts.layout'); @section('content') <!-- Content Header (Page header) --> <section class="content-header"> <div class="container-fluid"> <div class="row mb-2"> <div class="col-sm-6"> <h1>Редактирование статьи</h1> </div> <div class="col-sm-6"> <ol class="breadcrumb float-sm-right"> <li class="breadcrumb-item"><a href="#">Статья "{{ $post->title }}"</a></li> <li class="breadcrumb-item active">Редактирование статьи</li> </ol> </div> </div> </div><!-- /.container-fluid --> </section> <!-- Main content --> <section class="content"> <form action="{{ route('posts.update', ['post' => $post->id]) }}" method="post" enctype="multipart/form-data"> @csrf @method('PUT') <div class="card-body"> <div class="form-group"> <label for="title">Статья</label> <input type="text" class="form-control @error('title') is-invalid @enderror" id="title" value="{{ $post->title }}" autocomplete="off" name="title"> </div> <div class="form-group"> <label for="description">Цитата</label> <textarea name="description" class="form-control @error('description') is-invalid @enderror" rows="3" id="description">{{ $post->description }}</textarea> </div> <div class="form-group"> <label for="content">Контент</label> <textarea name="content" class="form-control @error('content') is-invalid @enderror" rows="10" id="content">{{ $post->content }}</textarea> </div> <div class="form-group"> <label for="category_id">Категория</label> <select name="category_id" id="category_id" class="form-control @error('category_id') is-invalid @enderror"> @foreach ($categories as $k => $v) <option value="{{ $k }}" @if ($k == $post->category_id) selected @endif>{{ $v }}</option> @endforeach </select> </div> <div class="form-group"> <label for="tags">Тэги</label> <select name="tags[]" id="tags" class="select2 @error('tags') is-invalid @enderror" multiple="multiple" data-placeholder="Выберите тэги" style="width: 100%;"> @foreach ($tags as $k => $v) <option value="{{ $k }}" @if (in_array($k, $post->tags->pluck('id')->all())) selected @endif>{{ $v }}</option> @endforeach </select> </div> <div class="form-group"> <label for="thumbnail">Выберите изображение</label> <div class="input-group"> <div class="custom-file"> <input type="file" name="thumbnail" class="custom-file-input @error('thumbnail') is-invalid @enderror" id="thumbnail"> <label class="custom-file-label" for="thumbnail">Выберите файл</label> </div> </div> </div> <img src="{{ $post->getImage() }}" class="img-thumbnail" width="250" alt="Image"> <div class="card-footer"> <button type="submit" class="btn btn-primary">Сохранить</button> </div> </div> </form> </section> <!-- /.content --> @endsection
app/Http/Controllers/Admin/PostController.php
<?php namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\Category; use App\Models\Post; use App\Models\Tag; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Storage; class PostController extends Controller { /** * Display a listing of the resource. * * @return Response */ public function index() { $posts = Post::with('tags', 'category')->paginate(10); return view('admin.posts.index', compact('posts')); } /** * Show the form for creating a new resource. * * @return Response */ public function create() { $categories = Category::pluck('title', 'id')->all(); $tags = Tag::pluck('title', 'id')->all(); return view('admin.posts.create', compact('categories', 'tags')); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return Response */ public function store(Request $request) { $request->validate([ 'title' => 'required', 'description' => 'required', 'content' => 'required', 'category_id' => 'integer', // значит, что параметр обязательный и он должен быть integer 'thumbnail' => 'nullable|image', // значит, что параметр не обязательный, но это должна быть картинка ]); $data = $request->all(); // сохраняем изображение $data['thumbnail'] = Post::uploadImage($request); $post = Post::create($data); /* * используем https://laravel.com/docs/8.x/eloquent-relationships#syncing-associations * для вставки уникальных связи в post_tag таблицу */ $post->tags()->sync($data['tags']); return redirect()->route('posts.index')->with('success', 'Статья добавлена!'); } /** * Show the form for editing the specified resource. * * @param int $id * @return Response */ public function edit($id) { $categories = Category::pluck('title', 'id')->all(); $tags = Tag::pluck('title', 'id')->all(); $post = Post::find($id); return view('admin.posts.edit', compact('post', 'tags', 'categories')); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return Response */ public function update(Request $request, $id) { $request->validate([ 'title' => 'required', 'description' => 'required', 'content' => 'required', 'category_id' => 'integer', // значит, что параметр обязательный и он должен быть integer 'thumbnail' => 'nullable|image', // значит, что параметр не обязательный, но это должна быть картинка ]); $data = $request->all(); $post = Post::find($id); // удаляем старое и сохраняем новое изображение $thumbnail = Post::uploadImage($request, $post['thumbnail']); if ($thumbnail) { $data['thumbnail'] = $thumbnail; } $post->update($data); if (isset($data['tags'])) { $post->tags()->sync($data['tags']); } return redirect()->route('posts.edit', $post->id)->with('success', 'Статья изменена!'); } /** * Remove the specified resource from storage. * * @param int $id * @return Response */ public function destroy($id) { $post = Post::find($id); $post->tags()->sync([]); // удаляем тэги Storage::delete($post->thumbnail); $post->delete(); return redirect()->route('posts.index')->with('success', 'Статья удалена!'); } }