Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel U Editor Laravel Package

stevenyangecho/laravel-u-editor

Laravel wrapper for Baidu's UEditor rich text editor. Drop a full-featured WYSIWYG editor into Blade views, publish its config, and route image, file, video, and scrawl uploads through Laravel storage and authentication. Simplifies server-side handling for a classic rich text editor.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a Laravel 5–era wrapper around Baidu's UEditor, so the setup is the classic three-step flow: install, register, publish.

  1. Install with Composer:
    composer require stevenyangecho/laravel-u-editor
    
  2. Register the service provider in config/app.php under providers. This package predates auto-discovery (2015 release), so you must add it manually and, if it exposes an alias/facade, add that to aliases too.
    'providers' => [
        // ...
        Stevenyangecho\UEditor\UEditorServiceProvider::class,
    ],
    
  3. Publish assets and config:
    php artisan vendor:publish
    
    This should drop the UEditor front-end (JS, CSS, themes, lang, dialogs) into public/ and the backend config into config/. Confirm where the JS actually landed (public/vendor/ueditor/ueditor.all.js is typical) before wiring it into a view.
  4. Verify the backend routes the package registers:
    php artisan route:list | grep -i ueditor
    
    You should see the controller endpoint UEditor calls for action=config and the upload actions. Note the URI — the JS config must point at it.

First use case: a CMS "post body" field. In your Blade form:

<textarea name="body" id="editor">{{ old('body', $post->body ?? '') }}</textarea>

<script src="{{ asset('vendor/ueditor/ueditor.config.js') }}"></script>
<script src="{{ asset('vendor/ueditor/ueditor.all.js') }}"></script>
<script>
  var ue = UE.getEditor('editor', {
    serverUrl: '{{ url('/ueditor/serve') }}' // match the route from route:list
  });
</script>

Before building anything on top, hit the controller directly — GET /ueditor/serve?action=config — and confirm it returns the JSON config UEditor expects. That single check tells you whether routing, config publishing, and the response format are all wired correctly.

Implementation Patterns

Blade partial for editor init. Wrap the two <script> tags plus the instantiation in a partial (partials/ueditor, taking a $name and $value) so every form reuses it. Pass serverUrl from route() rather than hard-coding, so staging/production URLs stay consistent.

Repopulating content after save/validation failure. UEditor renders into an iframe; a value attribute on the textarea is ignored. Use the textarea old()/model value as the initial HTML and either set it via ue.ready(() => ue.setContent(...)) or — simpler — let UEditor read from the textarea by using UE.getEditor with the textarea as source and calling setContent on ready. Always set content inside the ready callback, never immediately after instantiation.

Multiple editors per page. Each editor needs a unique container id and its own UE.getEditor('id'). Don't reuse the default serverUrl if different forms need different upload directories — pass per-instance config.

Per-context upload paths. Publish the config and edit the image/file/video path rules. UEditor path templates use its own tokens ({yyyy}, {mm}, {dd}, {time}, {rand:n}) — not Laravel's date() tokens. Set these per project, e.g. uploads/posts/{yyyy}{mm}/, and commit the config so path behaviour is reproducible.

Storage integration. If you're on Laravel 5.2+ with the public disk, point the upload path at storage/app/public/... and run php artisan storage:link, or keep uploads in public/uploads. Choose one and document it — mixing both is a common source of "images upload but 404" bugs.

Customising the controller. When you need auth on uploads, custom responses, or S3-style storage, publish/extend the package controller rather than editing vendor files. Register your own route that points at your subclass, or overlay the route in routes/web.php after disabling the package's (check the provider for a config flag or route-registration toggle).

Protecting the editor endpoints. Put the upload/config route behind your auth middleware group so anonymous users can't upload files. If you need a public read-only config endpoint but authenticated uploads, split them.

Sanitising on save. UEditor sends raw HTML. Store it, but sanitise on output (or on save with HTMLPurifier / a whitelist) — treat the editor content as untrusted user input even from "trusted" admins, since the editor allows pasted/raw HTML.

Form handling. Nothing special is required on the Laravel side: the textarea posts as a normal field. Validate body as required|string, and keep a FormRequest in front of it so the raw HTML doesn't bypass your usual validation boundary.

Gotchas and Tips

  • Age and compatibility is the big one. Last release 2015, Laravel 5 era. Expect friction on Laravel 8+/PHP 8 (typed properties, deprecations, str_* helpers, container bindings). Test the service provider boot on your target version before committing to the package; if it breaks, the fallback is to use the published UEditor front-end assets and write a small controller yourself — you'd be reimplementing only the config/upload actions.
  • "后端配置项没有正常加载" (backend config failed to load). This classic UEditor error means the action=config response wasn't valid JSON or the serverUrl is wrong. Curl the endpoint and inspect the body before touching the JS.
  • CSRF kills uploads silently. UEditor's XHR won't carry your Blade @csrf token. Either add the upload route to VerifyCsrfToken::$except, or inject the token into UEditor's headers (ue.execCommand/custom XHR) — the exempt route is the pragmatic choice for most apps.
  • Size limits live in three places. The package config, php.ini (upload_max_filesize, post_max_size), and Nginx client_max_body_size. If uploads cap unexpectedly, check all three — the editor's error messages are unspecific.
  • Language defaults to Chinese. Publish/verify the lang assets and set lang: 'en' in the editor config if you want English UI; otherwise the toolbar labels stay zh-cn.
  • Path tokens ≠ Laravel tokens. The {yyyy}{mm}{dd} placeholders in the path format are UEditor's, and are not evaluated by Laravel. Don't try to pass a date('Y/m') string there.
  • Asset URLs hard-coded in published JS. If the published ueditor.config.js references an absolute path (or http), you'll get mixed-content or broken dialogs behind a proxy/https. Grep the published config for http:// and switch to relative or asset()-driven URLs.
  • Permissions. The upload directory must be writable by the web user. On shared hosting this is the #1 cause of "上传失败" (upload failed) with an apparently correct config.
  • Debugging loop. Reproduce the editor's request with curl/Postman: POST /ueditor/serve?action=uploadimage with a multipart file. That isolates package vs. browser vs. network issues fast.
  • Extension points, ranked by usefulness: (1) published config for paths/sizes; (2) a subclassed controller for storage and auth; (3) overriding the route in your app to add middleware. Editing vendor files is a dead end — the package is effectively unmaintained, so keep all your changes in published/app-owned files.
  • Prefer it for legacy compatibility only. For new projects, a maintained editor (TinyMCE, TipTap, CKEditor 5) with a modern Laravel upload endpoint will save you the compatibility archaeology this package requires. Where you do keep it — old admin panels, internal tools, sites already using UEditor — the patterns above keep it contained and predictable.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin