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

Emoji Laravel Package

alt-three/emoji

Alt Three Emoji is a Laravel package that integrates the Emoji One library, making it easy to convert emoji shortcodes to Unicode and render emoji as images. It includes a service provider and facade for quick setup, so you can add rich emoji support to user-generated content.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a thin Laravel wrapper around the EmojiOne PHP client. It gives you a single injectable translator plus an Emoji facade that turns emoji into shortcodes, shortcodes into unicode, or emoji into <img> tags.

composer require alt-three/emoji

On Laravel 5.5+ the AltThree\Emoji\EmojiServiceProvider is auto-discovered. On 5.1–5.4 add it to config/app.php providers and register the AltThree\Emoji\Facades\Emoji alias. The illuminate/support constraint is pinned to the Laravel 5 era, so on Laravel 6+ expect to either fork the constraint or skip the package entirely — this is the first thing to verify before committing to it.

Where to look first:

  • vendor/alt-three/emoji/src/ — the service provider shows exactly what is bound into the container (a singleton translator); the facade just resolves that binding.
  • vendor/emojione/emojione/lib/php/ — the underlying client. Most of the behaviour you will actually care about (image URLs, sprite mode, ASCII conversion) lives here, not in the Laravel package.

First use case: user-submitted content. Accept raw emoji in a comment box, store it as shortcode with Emoji::toShort($text), and render it back with Emoji::toUnicode() in plain-text surfaces or Emoji::toImage() in HTML surfaces. That input-store-render split is the pattern the package is designed around.

use AltThree\Emoji\Facades\Emoji;

Emoji::toShort('Hello 😀');        // "Hello :grinning:"
Emoji::toUnicode('Hello :grinning:'); // "Hello 😀"
Emoji::toImage('Hello 😀');        // "Hello <img class="emojione" ...>"

Implementation Patterns

Pick one canonical storage form and stick to it. Store shortcodes (:smile:) in the database, not raw unicode. Shortcodes survive utf8 (3-byte) columns, are greppable in SQL, and are stable across emoji-set upgrades. Convert on input with toShort(), convert on output. Storing unicode means you need utf8mb4 on every column, connection, and index that might touch the field — a migration you do not want to run twice.

Render at the edge, not at write time. Keep the model accessor pattern:

public function getBodyHtmlAttribute()
{
    return Emoji::toImage(e($this->body));
}

Note the e() before toImage(). The EmojiOne client only rewrites emoji tokens — it does not escape surrounding HTML. Passing raw user input through {!! !!} after toImage() is a straight XSS hole.

Match the output format to the channel. HTML views get toImage(); emails, SMS, push notifications, JSON APIs, and log lines get toUnicode(). Image tags in a plain-text mail are noise, and unicode in an HTML mail renders inconsistently across clients.

Order matters in a markdown/HTML pipeline. If you run CommonMark or Parsedown, do emoji conversion after markdown rendering and before any HTML purifier — or configure the purifier to allow the <img> tags and classes EmojiOne emits. Run it before markdown and your :shortcode: syntax can collide with markdown emphasis; run it after purifying and every emoji gets stripped.

A Blade directive keeps views clean:

Blade::directive('emoji', fn ($expr) => "<?php echo \\AltThree\\Emoji\\Facades\\Emoji::toImage(e($expr)); ?>");

For search and indexing, run toShort() and then strip /:([a-z0-9_+-]+):/ so emoji do not pollute full-text matches, or keep the shortcodes and let users search :fire: — that is often a nicer feature than you'd expect.

Resolve from the container, not the facade, in jobs and services. The translator is a singleton; injecting it makes tests trivial and avoids the facade root being unset in unusual bootstrap paths.

Gotchas and Tips

  • This package is archived and its dependency is worse. emojione/emojione is abandoned, and EmojiOne itself relicensed into JoyPixels (with a different licence and no maintained PHP client under the old name). Pin both packages to exact versions in composer.json, commit the lockfile, and treat any emoji-set refresh as a fork-and-patch task rather than a composer update.
  • toImage() points at a CDN by default. In air-gapped, intranet, or offline-CI environments you get broken images. Publish/copy the EmojiOne assets locally and point the client at them, or use sprite mode if you're rendering long feeds and care about request count.
  • Round-tripping is not guaranteed. Several emoji have multiple shortnames, and older EmojiOne data predates modern ZWJ sequences — skin-tone modifiers, family groupings, and flags often degrade to a base emoji. Test your specific set; don't assume toUnicode(toShort($x)) === $x.
  • mbstring is mandatory. These conversions walk multibyte strings. Missing extension or an mb_internal_encoding mismatch produces mangled output that looks like a data problem.
  • Facade alias collisions. If another package registers an Emoji alias, resolution order decides which one wins. Check config/app.php aliases if behaviour changes after adding a dependency.
  • Cache the expensive path. toImage() on a 5,000-comment thread is not free. Wrap it: hash the stored body, cache the rendered HTML, invalidate on save. The translator being a singleton does not memoize anything for you.
  • Config caching. If you publish any config, remember php artisan config:cache in deploy. A stale cached config after flipping image mode is the classic "why are my emoji still PNGs" bug.
  • Testing. The facade has no fake(). Bind a mock AltThree\Emoji\EmojiTranslator into the container in your test case, or just assert against real conversions — they are deterministic and fast enough.
  • Extension point. The translator is resolved from the container, so you can swap the binding in a service provider to wrap the client with logging, caching, or a different emoji dataset without touching call sites. That decorator seam is the most valuable thing this package offers for a long-lived app.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console