Подключаем текстовый (wysiwyg) редактор к Laravel

Ромчик
4

Подключаем Summernote к LaravelДоброго времени суток. В одной из своих статей «Подключаем CKEditor к Laravel 5.1 и интегрируем в него файловый менеджер elFinder» я описал как интегрировать CKEditor в приложение на Laravel.  И все бы хорошо, но CKEditor превратился в «монстра» с поддержкой огромного функционала, который мне в моих проектах вряд ли пригодится. Да и размер редактора уж очень раздулся. Поэтому решил я найти простенький WYSIWYG редактор. И мой выбор пал на Summernote. Очень маленький (около 500 килобайт и это со всеми модулями и локализациями), с поддержкой стандартных функций.

Дальше я расскажу как подключить Summernote к Laravel, сделать возможность загрузки файлов на сервер. А все это мы будем делать на примере создания статей.

Немного о Summernote

Это простой и легкий wysiwyg редактор, использующий bootstrap. Поддерживает:

  • Локализацию
  • Форматирование текста
  • Вставку списков
  • Вставку таблиц
  • Ссылок
  • Возможность загрузки видео и изображений
  • Возможность редактировать код

Подготовка проекта на Laravel

Будем считать, что у вас уже установлен и настроен Laravel.

У меня установлен и настроен Laravel 5.5.

Версия Laravel

Для работы с файлами я буду использовать пакет Intervention Image. Как подключить и интегрировать данный пакет в Laravel я описал в статье «Загрузка и работа с изображениями в Laravel — пакет Intervention Image».

Давайте создадим миграцию, которая будет создавать таблицу articles. Переходим в консоль и выполняем следующую команду.


    php artisan make:migration CreateArticlesTable --create=articles

Теперь давайте откроем файл миграции и изменим метод up:


    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('text');
            $table->timestamps();
        });
    }

Запускаем миграцию.


    php artisan migrate

Отлично миграция выполнена, таблица создана.

Теперь создадим модель Article и контроллер ArticleController


    php artisan make:model Article -c

Создание модели и контроллера

Модель и контроллер созданы. Открываем модель Article и добавляем следующий код:


    <?php
        namespace App;

        use Illuminate\Database\Eloquent\Model;

        class Article extends Model
        {
            protected $fillable = [
                'title', 'text'
            ];
}

Модель готова. Теперь переходим к контроллеру ArticleController. Данный контроллер будет иметь четыре метода:

  • Index – все статьи
  • Create – форма для создания статьи
  • Store – для сохранения статьи
  • uploadFile – для загрузки файла не сервер

Давайте опишем первый метод index:


    public function index()
    {
        $articles = Article::all();
        return view('index',['articles' => $articles]);
    }

Получаем все статьи и передаем их во вьюшку index.blade.php. Давайте создадим данную вьюшку:


<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Laravel</title>
        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
        <!-- Styles -->
        <style>
            html, body {
                background-color: #fff;
                color: #636b6f;
                font-family: 'Raleway', sans-serif;
                font-weight: 100;
                height: 100vh;
                margin: 0;
            }
            .full-height {
                height: 100vh;
            }
            .position-ref {
                position: relative;
            }
            .top-right {
                position: absolute;
                right: 10px;
                top: 18px;
            }
            .content {
                text-align: center;
            }
            .title {
                font-size: 84px;
            }
            .links > a {
                color: #636b6f;
                padding: 0 25px;
                font-size: 12px;
                font-weight: 600;
                letter-spacing: .1rem;
                text-decoration: none;
                text-transform: uppercase;
            }
            .m-b-md {
                margin-bottom: 30px;
            }   
        </style>
    </head>
    <body>
        <div class=" position-ref full-height">
            <div class="content">
                @foreach($articles as $article)
                    <h1>{{ $article->title }}</h1>
                    <div>{{ $article->text }}></div>
                    <hr><br>
                @endforeach
            </div>
        </div>
    </body>
</html>

Теперь давайте опишем второй метод create.


    public function create()
    {
        return view('create');
    }

Данный метод просто возвращает вьюшку с формой добавления статьи. Давайте создадим данную вьюшку.


<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="csrf-token" id="csrf-token" content="{{ csrf_token() }}">
        <title>Laravel</title>
        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
        <!-- Styles -->
        <style>
            html, body { 
                background-color: #fff; 
                color: #636b6f; 
                font-family: 'Raleway', sans-serif; font-weight: 100; 
                height: 100vh; margin: 0; 
            } 
            .full-height { 
                height: 100vh; 
            } 
            .position-ref { 
                position: relative; 
            } 
            .top-right { 
                position: absolute; right: 10px; top: 18px; 
            } 
            .content { 
                text-align: center; 
            } 
            .title { 
                font-size: 84px; 
            } 
            .links > a { 
                color: #636b6f; 
                padding: 0 25px; 
                font-size: 12px; 
                font-weight: 600; 
                letter-spacing: .1rem; 
                text-decoration: none; 
                text-transform: uppercase; 
            } 
            .m-b-md { 
                margin-bottom: 30px; 
            }
        </style> 
    </head>
<body>
    <div class=" position-ref full-height">
        <div class="content">
            <form action=" {{ route('store') }} " method="POST">
                {{ csrf_field() }}
                <label for="title">Заголовок</label><br />
                <input type="text" name="title" id="title"><br />
                <label for="text">Текст</label><br />
                <input type="text" name="text" id="text"><br />
                <button type="submit">Добавить</button>
            </form>
        </div>
    </div>
</body>
</html>

Теперь опишем метод store:


    public function store(Request $request)
    {
        Article::create(['title' => $request->title, 'text' => $request->text]);
        return redirect()->route('all');
    }

Осталось добавить три роута. Открываем файл routes/web.php и добавляем следующий код:


<?php

    Route::get('','ArticleController@index')->name('all');
    Route::get('/create','ArticleController@create')->name('create');
    Route::post('/create','ArticleController@store')->name('store');

Проверяем, что у нас получилось. Переходим по ссылке <домен>/create и видим форму добавления. Давайте добавим одну статью.

Добавленние статьи

Отлично сам функционал работает. Теперь давайте к нашей форме добавления статьи подключим wysiwyg редактор.

Подключение wysiwyg редактора к Laravel

Открываем нашу вюшку, которая содержит форму добавления статьи. Для полноценной работы редактора Summernote необходимо подключить bootstrap и jquery. А затем подключить сам редактор (файл со стилями и файл с javascritpt). И так давайте изменим код create.blade.php

После подключения шрифтов добавим:


<!-- подключаем boostrap -->

<link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">

<!-- подключаем стили Summernote -->

<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.7/summernote.css" rel="stylesheet">

А в конец, перед тегом </body> добавим:


<!-- подключаем jquery -->

<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>

<!-- подключаем bootstrap.js -->

<script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.js"></script>

<!-- подключаем сам summernote -->

<script src="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.7/summernote.js"></script>

<script>

$(document).ready(function() {

    $('#text').summernote();

});

</script>

Давайте посмотрим, что у нас получилось:

Подключение редактора Summernote к Laravel

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

Настройка загрузки файлов, используя текстовый редактор Summernote

Открываем нашу вьюшку с формой добавления статьи. И первое, что мы сделаем заменим


<input type="text" name="text" id="text">

на


<textarea name="text" id="text"></textarea>

Второе поменяем код скрипта:


$(document).ready(function() {

    $('#text').summernote({
        callbacks: {
            onImageUpload: function(files) {
                var el = $(this);
                sendFile(files[0],el);
            }
       }
    });
});

function sendFile(file, el) {
    var  data = new FormData();
    data.append("file", file);
    var url = '{{ route('upload') }}';
    $.ajax({
        data: data,
        type: "POST",
        headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
        url: url,
        cache: false,
        contentType: false,
        processData: false,
        success: function(url2) {
            el.summernote('insertImage', url2);
        }
   });
}

При добавлении файла в редакторе будет вызываться функция sendFile. Теперь давайте пропишем маршрут для /upload


Route::post('upload','ArticleController@upload')->name('upload');

А в контроллер ArticleController добавим метод upload.


    public function upload(Request $request)
    {
        $path =  public_path().'\images\\';
        $file = $request->file('file');
        $filename = str_random(20) .'.' . $file->getClientOriginalExtension() ?: 'png';
        $img = Image::make($file);
        $img->save($path . $filename);
        echo '/images/'.$filename;
    }

Осталось только во вьюшке index.blade.php немного поправить код, чтобы шаблонизатор не экранировал вывод текста. Для этого заемним:


<div>{{ $article->text }}</div>

на


<div>{!! $article->text !!}</div>

Все. Можно проверить.

Добавление статьи с картинкой

Заключение

Мы с вами подключили к проекту на Laravel легковесный wysiwyg редактор – Summernote, который позволяет загружать файлы (мы это настроили), редактировать текст и многое другое.

Понравилась статья? Поделись с друзьями.
  • Add to favorites
  • Добавить ВКонтакте заметку об этой странице
  • Twitter
  • Facebook
  • Мой Мир
  • LiveJournal
  • Одноклассники
  • Блог Я.ру
  • MySpace
  • FriendFeed
  • В закладки Google
  • Google Buzz
  • Яндекс.Закладки
  • Reddit
  • StumbleUpon
  • Technorati
  • del.icio.us
  • БобрДобр
  • LinkedIn
  • Memori.ru
  • Сто закладок
  • Blogger

  • Иван - 10.10.2018 в 18:08

    Не работает загрузка изображений в редакторе :(

    • Ромчик - 10.10.2018 в 18:24

      Странно. А версия Laravel какая? И какую ошибку выдает?

  • Xintrea - 06.05.2019 в 19:00

    Два вопроса:

    — А как удаляются картинки с диска, если они перестают использоваться в тексте?
    — А как загружать не картинки, а прикрепляемые файлы и получать на них ссылки? И чтобы имена файлов были не рандомными а родными?

  • ©2012-2020 По всем вопросам обращайтесь через форму обратной связиПолитика конфиденциальности

    Яндекс.Метрика