Laravel: загрузка изображения в Ckeditor

В Laravel вы можете легко встроить визуальный редактор в форму, используя популярную JavaScript-библиотеку под названием CKEditor. CKEditor является свободным и открытым инструментом для веб-редактирования, который имеет множество функций.

Установка CKEditor

Создайте свою сборку CKEditor по ссылке https://ckeditor.com/ckeditor-5/online-builder/ скачайте с скопируйте в папку "/public/build/ckeditor5"

Теперь вы можете использовать CKEditor в своих представлениях или формах. Например, создайте новую форму в файле resources/views/editor.blade.php:

<form method="POST" action="/your-route">
    @csrf

<script src="{{asset('build/ckeditor5/build/ckeditor.js')}}"></script>
<script>
ClassicEditor
.create(document.querySelector('#editor'), {
simpleUpload: {
uploadUrl: '{{route('image.upload').'?_token='.csrf_token()}}',
},
mediaEmbed: {
previewsInData: true
}
})
.catch(error => {
console.error(error);


});
</script> <textarea name="content" id="editor">{!! old('content') !!}</textarea> <button type="submit">Submit</button> </form>

Обратите внимание, что в приведенном выше коде мы используем {!! old('content') !!} для заполнения текстового поля редактора сохраненными данными, если они доступны.

Не забудьте также определить маршрут и метод контроллера для обработки отправки формы.

Теперь, когда пользователи будут заполнять эту форму, они увидят визуальный редактор CKEditor, который позволяет им отформатировать содержимое.

Контроллер загрузки изображений

Создадим контроллер загрузки изображения:

php artisan make:controller ImageUploadController

app/Http/Controllers/ImageUploadController.php

<?php

namespace App\Services;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\File;
use Intervention\Image\ImageManagerStatic;
use Mockery\Exception;

class ImageUploadService
{
public static function uploadImage(UploadedFile $file): array
{
try {

// Получаем оригинальное имя файла
$originName = $file->getClientOriginalName();

// Извлекаем имя файла без расширения
$fileName = pathinfo($originName, PATHINFO_FILENAME);

// Получаем расширение файла
$extension = $file->getClientOriginalExtension();

// Создаем уникальное имя файла на основе текущей даты и времени
$uniqueFileName = $fileName . date('YmdHisu');

// Генерируем хэш из уникального имени файла и берем первые 8 символов
$hash = md5($uniqueFileName);

// Формируем окончательное имя файла с добавлением хэша и расширения
$fileName = substr($hash, 0, 8) . '.' . $extension;

// Создаем путь для сохранения файла, основываясь на текущей дате
$currentPath = date('Ymd');
$directoryPath = 'media/' . $currentPath . '/';

// Открываем изображение с помощью Intervention Image
$img = ImageManagerStatic::make($file->getRealPath());

// Получаем ширину и высоту изображения
$width = $img->getWidth();
$height = $img->getHeight();

// Проверяем, нужно ли уменьшать изображение по ширине
if ($width > 1080) {
$img->resize(1080, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
}

// Проверяем, нужно ли уменьшать изображение по высоте
if ($height > 840) {
$img->resize(null, 840, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
}

if (!File::exists($directoryPath)) {
File::makeDirectory($directoryPath);
}

// Сохраняем измененное изображение
$img->save(public_path($directoryPath) . $fileName);

} catch (Exception $e) {
return [
'uploaded' => false,
];
}
// Формируем URL для доступа к загруженному файлу
$url = '/' . $directoryPath . $fileName;

// Возвращаем информацию о загруженном файле
return [
'fileName' => $fileName,
'uploaded' => true,
'url' => $url
];
}

public static function uploadImageFromUrl(string $imageUrl): array
{
// Загружаем изображение по URL
$file = file_get_contents($imageUrl);

// Создаем временный файл для сохранения изображения
$tempFilePath = tempnam(sys_get_temp_dir(), 'image');
file_put_contents($tempFilePath, $file);

// Создаем экземпляр UploadedFile с временным файлом
$uploadedFile = new UploadedFile(
$tempFilePath,
basename($imageUrl)
);

// Вызываем функцию uploadImage для загрузки изображения
return self::uploadImage($uploadedFile);
}

public static function downloadAndReplaceImages(string $htmlContent): string|null
{
return preg_replace_callback("/<(img|image)[\s]+[^>]*src=['\"]?([^'\"\s>]+)['\"]?[^>]*>/is", array('self', 'replaceCallbackImages'), $htmlContent);
}

public static function replaceCallbackImages($matches): string
{
$src = $matches[2];
$img = $matches[0];

// Проверяем, является ли URL внешним (не ведет на наш сайт)
if (!self::isLocalUrlImage($src)) {
$uploadedImage = ImageUploadService::uploadImageFromUrl($src);
if ($uploadedImage['uploaded']) {
$img = '<img src="' . $uploadedImage['url'] . '" >';
}
}
return $img;
}

private static function isLocalUrlImage($url): bool
{
return (parse_url($url, PHP_URL_HOST) == null);
}
}

Добавьте в web.php следующие строчки

Route::post('admin/image/upload', [ImageUploadController::class, 'storeImage'])->middleware(['auth', 'verified'])->name('image.upload');

Установите биилиотеку:

composer require intervention/image  

 Загрузка изображения в Ckeditor

 Добавьте путь загрузки изображения в код Ckeditor:

ClassicEditor
.create(document.querySelector('#editor'), {
simpleUpload: {
uploadUrl: '{{route('image.upload').'?_token='.csrf_token()}}',
}
})
.catch(error => {
console.error(error);
});

Теперь у нас есть визуальный редактор с возможностью загрузки изображений.