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

Twitter Laravel Package

cachethq/twitter

Twitter integration for Cachet status pages. Connect a Twitter account and automatically share incident and maintenance updates with followers, keeping them informed while preserving your existing Cachet workflow and simple Laravel-based configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a single-responsibility package: it turns plain text containing @handle mentions into HTML with links to the corresponding Twitter profiles. Treat it as a text formatter, not a Twitter API client — it makes no network calls and requires no OAuth credentials.

Install and register

composer require cachethq/twitter

On Laravel 5.5+ the service provider is auto-discovered. On Laravel 5.0–5.4, add the provider and facade manually in config/app.php:

'providers' => [
    CachetHQ\Twitter\TwitterServiceProvider::class,
],
'aliases' => [
    'Twitter' => CachetHQ\Twitter\Facades\Twitter::class,
],

No config file needs publishing and there is nothing to migrate. If the provider isn't discovered, run composer dump-autoload and confirm the package is listed under vendor/cachethq/twitter.

Where to look first

The package is tiny — read src/ end to end before using it (10–15 minutes). The relevant surface is a parser class and, usually, a facade or container binding. Confirm the exact method name from the source before wiring it in; the README is thin and the API has changed between minor versions.

First use case

The canonical scenario this was built for is Cachet-style status/incident text: an operator writes Database failover complete — thanks @oncall_team, and the rendered status page should show a clickable profile link rather than raw text.

// routes/web.php — smoke test
Route::get('/parse', function () {
    return app(\CachetHQ\Twitter\Parser::class)->parse('Thanks @cachethq for the quick fix');
});

If you get <a href="https://twitter.com/cachethq">@cachethq</a> back, the package is wired correctly. If not, check class name and method signature in vendor/cachethq/twitter/src/ — that is faster than debugging the facade.

Implementation Patterns

Linkify at render time, store raw text

Keep the raw string in the database and parse on output. Parsing on write means a future change to link format (or a switch to x.com URLs) requires a data migration.

// Blade component
{!! app(\CachetHQ\Twitter\Parser::class)->parse(e($incident->message)) !!}

Wrap it behind your own helper

Because the package is small and lightly maintained, insulate your codebase with one boundary so swapping it later is a one-file change:

namespace App\Support;

class MentionParser
{
    public function link(string $text): string
    {
        return app(\CachetHQ\Twitter\Parser::class)->parse($text);
    }
}

Then inject MentionParser everywhere. If the package dies, you replace the body with a regex and never touch call sites.

Extracting handles vs. rendering links

Two distinct needs show up in practice:

  • Rendering — you want HTML for display (what this package does).
  • Extraction — you want ['cachethq', 'oncall_team'] to fire notifications, build a mention index, or resolve user IDs.

For extraction, do not round-trip through the HTML output. Either run your own preg_match_all('/@([A-Za-z0-9_]{1,15})/', $text, $m) or strip tags from the parser output. Extraction is the more common need in modern apps, and it is a five-line job — factor that in when deciding whether the dependency earns its place.

Integration points

  • Model accessors — expose $incident->message_html that composes parsing plus escaping. Cache the attribute on the model instance so a list view doesn't re-parse the same row repeatedly.
  • Notifications / mailables — parse before handing to the mail view if you want mentions clickable in email; otherwise leave the text plain.
  • API resources — return both message (raw) and message_html (parsed) so clients choose.
  • Form requests — validate and normalise the raw mention text (@Name → @name) at the boundary, since Twitter handles are case-insensitive but your links should be consistent.

Pipeline order matters

Escape first, parse second. If you parse then escape, your generated <a> tags get neutralised. If you escape then parse, a malicious "><script> payload in the surrounding text is already inert while the parser only ever sees the @handle token.

Gotchas and Tips

It is effectively unmaintained. Two stars, zero dependents, and a Laravel 5/6 target means the composer.json almost certainly pins php: ^7.x and illuminate/support: 5.*|6.*. On Laravel 9/10/11 you will hit dependency resolution failures. Options: fork and widen the constraints (the code is a few dozen lines), or drop the dependency and inline a parser. For a package this small, inlining is usually the right call — the "opportunity" score is low precisely because the functionality is trivially reproducible.

Regex edge cases you will hit

  • Trailing punctuation — @cachethq. or @cachethq, should link the handle, not the period. Check the parser's output on sentence-ending mentions; many naive implementations swallow the punctuation into the link.
  • Email addresses — [email protected] contains a @. A correct parser requires a word boundary or start-of-string before the @. Verify this explicitly with a unit test.
  • Length limits — Twitter handles max out at 15 characters and [A-Za-z0-9_]. A loose parser will happily link @some_really_long_thing that can never be a real handle.
  • Already-linked text — parsing text that already contains an <a href="...">@foo</a> produces nested anchors. Parse once, at one layer only.
  • Code blocks — if you render Markdown, run the Twitter parser before Markdown only if you're certain the parser won't touch fenced code. Usually it's safer to leave mentions unlinked inside code spans.

Debugging approach

The package has no logging. Isolate failures with a three-input test matrix: plain text, text with punctuation, text with an email address. If output looks wrong, dump preg_last_error() from your own comparison regex — the bug is nearly always in the pattern, not the Laravel wiring.

Extension points are minimal

There is likely no config file or driver system, so "extending" means either subclassing the parser and rebinding it in the container, or forking. If you need custom behaviour (link to x.com, add rel="nofollow noopener", use a different handle pattern), assume you're writing it yourself rather than configuring it.

XSS is your responsibility. The parser emits raw HTML. Any output path must be {!! !!} on escaped input, never on user-supplied text directly. If a future contributor "simplifies" the Blade by removing the e(), you have a stored XSS vector on your status page — add a test that asserts a script payload stays escaped.

Recommendation for a day-to-day workflow: use it if you're already on Cachet or a Laravel 5/6 app that needs mention linkification today and you want the behaviour off your plate. Otherwise, budget an hour to write a 20-line MentionParser with tests, skip the dependency, and avoid the framework-version dead end.

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/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
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route