jeroennoten/laravel-ckeditor
A Laravel package that integrates CKEditor into your application, offering Blade helpers and configuration to load the editor, manage assets, and customize toolbars. It simplifies adding rich-text editing to forms while keeping setup and options centralized in Laravel.
Install via Composer and publish the config:
composer require jeroennoten/laravel-ckeditor
php artisan vendor:publish --provider="Jeroennoten\LaravelCkeditor\CkeditorServiceProvider"
On Laravel 5.5+ the provider/alias are usually auto-discovered; on older versions register Jeroennoten\LaravelCkeditor\CkeditorServiceProvider and the Ckeditor alias in config/app.php.
Look here first: config/ckeditor.php. It holds the CDN toggle, CKEditor version, language, default editor options, and the file-browser upload/browse route names. Almost every day-to-day tweak lives there or is passed as an options array per call.
First use case — replace a post body textarea in a form:
<textarea name="body" id="body">{{ old('body', $post->body ?? '') }}</textarea>
@push('scripts')
{!! Ckeditor::script() !!}
<script>{!! Ckeditor::replace('body') !!}</script>
@endpush
Render a textarea, include the script once in your layout's script stack, then initialise the editor by element id. That is the entire happy path.
Ckeditor::script() into a @stack('scripts') in your base layout so it loads once per page, even when a form is included via a partial. Only Ckeditor::replace() belongs next to the textarea.minimal, full) in config/ckeditor.php, then select one per form. This keeps toolbars and height settings out of Blade and consistent across admin screens.Ckeditor::replace('body', ['height' => 400, 'removePlugins' => 'elementspath']) merges into the defaults — use this for the occasional one-off rather than editing config.<textarea> + Ckeditor::replace() in one partial that takes $name, $value, and $options, so every CRUD screen gets the same markup and init.replace() for each (or drive it from a data-editor attribute loop). Avoid re-initialising an id.filebrowserUploadRoute / filebrowserBrowseRoute at your own routes, then return the expected CKEditor callback payload (CKEditorFuncNum, URL, message) or JSON for the modern integration. Protect those routes with auth and validation middleware as you would any upload endpoint.mews/purifier or similar) before persisting, and treat stored HTML as untrusted on render.Ckeditor::script() output, and the init snippet — CKEditor itself never boots in the test client, so test the form contract, not the editor.Ckeditor::script() and the replace snippet return HTML/JS; print with {!! !!}. Using {{ }} renders a broken page silently.config/ckeditor.php, run php artisan config:cache again — stale config is the usual cause of "my toolbar change did nothing".Ckeditor::script() twice, or calling replace() on an id that already has an instance, throws a CKEditor "editor instance already exists" error. Guard with if (!CKEDITOR.instances[id]) when in doubt, and check duplicated layout stacks first.cdn => true the editor silently fails without internet/CDN access. For offline or air-gapped installs, publish the assets and switch the config to local; verify the request in the network tab.VerifyCsrfToken.CKEDITOR.instances and CKEDITOR.config in the console, and watch the network tab for a failed ckeditor.js or config.js request.config.js via the config's custom-config option, extra plugins by adding files to the published plugins directory, and toolbar layout entirely through the options array — no need to fork the package.How can I help you explore Laravel packages today?