Работа с изображениями в Laravel, Image Intervention
В этом посте я попробую показать как использовать пакет для работы с изображениями Image Intervention в Laravel.
Обычно Image Intervention используют для загрузки и стандартной работы с изображениями (изменением размера, обрезкой и т.п.). Создадим для примера простое приложение для публикации новостей, которое будет иметь всего две функции:
- вывод всех новостей;
- добавить новость с картинкой.
Сразу создадим модель, миграцию и контроллер ресурсов для наших новостей, выполнив команду:
php artisan make:model News -mcr
Открываем созданный файл миграции /database/migrations/XXXX_XX_XX_XXXX_create_news_table.php
и добавляем нужные поля, их буде три: название, содержание, картинка.
public function up()
{
Schema::create('news', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->text('body');
$table->string('image');
$table->timestamps();
});
}
Выполняем миграцию php artisan migrate
Создаем Blade шаблон для главной страницы новостей resources/views/news/index.blade.php
Пока там будет заглушка, просто напишем слово «Новости».
Далее настроим роуты добавив в файл /routes/web.php
Route::resource('news', 'NewsController');
Теперь в контроллере app/Http/Controllers/NewsController.php
в методе index()
вызовем шаблон index.blade.php
public function index()
{
return view('news.index');
}
Переходим по http://нашсайт/news и убеждаемся что все работает.
Далее создаем форму для добавления новостей resources/views/news/create.blade.php
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>Добавление новости</title>
</head>
<body>
<div class="container">
<div class="col-8">
<h1>Добавить новость</h1>
<form method="post" action="{{ route('news.store') }}" enctype="multipart/form-data">
@csrf
<div class="form-group">
<label for="name">Название новости</label>
<input type="text" class="form-control" id="name" name="name">
</div>
<div class="form-group">
<label for="body">Содержание</label>
<textarea class="form-control" id="body" rows="3" name="body"></textarea>
</div>
<div class="form-group">
<label for="image">Картинка для новости</label>
<input type="file" class="form-control-file" id="image" name="image">
</div>
<button type="submit" class="btn btn-primary">Добавить</button>
</form>
</div>
</div>
</body>
</html>
Изменим в нашем контроллере новостей метод create():
public function create()
{
return view('news.create');
}
Теперь у нас по адресу http://нашсайт/news/create открывается форма добавления новости с картинкой, на этом подготовительный этап закончен.
Работа с Intervention Image в Laravel
Теперь добавим к нашему проекту пакет Intervention Image http://image.intervention.io/ с помощью Composer, идем в терминал и выполняем команду
composer require intervention/image
После установки открываем конфигурационный файл нашего приложения config/app.php
и в массив providers добавляем сервис провайдер установленного пакета:
'providers' => [
…….
/*
* Package Service Providers...
*/
Intervention\Image\ImageServiceProvider::class,
……
],
Так же добавляем фасад в массив aliases:
'aliases' => [
…..
'Image' => Intervention\Image\Facades\Image::class,
],
Далее в нашем контроллере новостей изменяем метод store():
public function store(Request $request)
{
$data = $request->all();
$filename = $data['image']->getClientOriginalName();
//Сохраняем оригинальную картинку
$data['image']->move(Storage::path('/public/image/news/').'origin/',$filename);
//Создаем миниатюру изображения и сохраняем ее
$thumbnail = Image::make(Storage::path('/public/image/news/').'origin/'.$filename);
$thumbnail->fit(300, 300);
$thumbnail->save(Storage::path('/public/image/news/').'thumbnail/'.$filename);
//Сохраняем новость в БД
$data['image'] = $filename;
News::create($data);
return redirect()->route('news.index');
}
Не забываем в начало контроллера добавить:
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image;
Прежде чем продолжить…Если вы ни разу не сталкивались с работой с файлами в Laravel, настоятельно рекомендую изучить этот раздел официальной документации, а уже после этого продолжить чтение статьи.
Далее в модель новостей app/News.php
добавить переменную $fillable с полями БД, которые мы будем записывать:
class News extends Model
{
protected $fillable = ['name', 'body', 'image'];
}
Переходим http://нашсайт/news/create и пробуем добавить новость. В случае успешной добавлении новости, запись появляется в БД, добавляются 2 файла изображения (оригинал и миниатюра) и нас переадресовывает на главную страницу.
В случае если у вас возникла ошибка «Can’t write image data to path…» попробуйте вручную создать папку public/image/news/thumbnail
В завершении выведем на главной страницы новостей их название и миниатюры изображений, для этого в контроллере app/Http/Controllers/NewsController.php
немного изменим метод index():
public function index()
{
return view('news.index',['news' => News::all()]);
}
И шаблон resources/views/news/index.blade.php
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>Список новостей</title>
</head>
<body>
<div class="container">
@foreach($news as $item)
<div class="col-8">
<h2>{{ $item->name }}</h2>
p><img src="{{ Storage::url('image/news/thumbnail/'.$item->image) }}" alt=""></p>
</div>
@endforeach
</div>
</body>
</html>
Перейдем http://нашсайт/news/ и убедимся, что все работает.
Итак, мы разобрали как можно работать с изображениями с помощью пакета Intervention Image добавив его к своему проекту в Ларавел. Выше мы использовали только метод fit() из этого пакета, какие еще существуют методы можно прочитать на официальном сайте http://image.intervention.io/