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', 'Статья удалена!');
}
}