alt-three/twitter
Alt Three Twitter is a Laravel package for integrating Twitter into your application, offering a simple wrapper for authenticated API requests and streamlined configuration so you can connect to Twitter without repetitive boilerplate.
This is a single-purpose utility, not a Twitter API client. It normalises/extracts @handle mentions from a string. Budget ten minutes to read the whole package — vendor/alt-three/twitter/src is a handful of files.
illuminate/* constraint range and was last released in 2018, so composer require alt-three/twitter will fail on Laravel 9+. On a modern app, copy the parser class into app/Support/ rather than fighting the constraint solver.AltThree\Twitter\TwitterServiceProvider) and exposes a Twitter facade alias. There is no config file to publish in most versions — no API keys, no OAuth, nothing to configure. If you were expecting to authenticate against the Twitter API, you have the wrong package.twitter column on a Profile/Speaker/Author model, or pulling mentions out of a free-text bio before storing it.use AltThree\Twitter\Facades\Twitter;
Twitter::parse('Thanks @taylorotwell and @GrahamJCampbell!');
// ['taylorotwell', 'grahamjcampbell']
If that method name does not match your version, open the facade's getFacadeAccessor() and follow the binding — the underlying class is where all the behaviour lives.
Ingest-time extraction, not render-time. Parse once on write and persist the result (a json column or a pivot table of handles). Parsing on every page render is wasted CPU and means a package upgrade can silently change what users see.
Separate "extract" from "validate". parse() is a scraper; it will happily return junk from [email protected]. If the field is supposed to hold one handle, validate the input yourself:
$handles = Twitter::parse($request->input('twitter'));
if (count($handles) !== 1) {
// reject, or take $handles[0]
}
$handle = strtolower($handles[0] ?? '');
Normalise before persisting. Twitter handles are case-insensitive; store lowercased and without the @. That makes where('twitter', $handle) lookups and unique indexes behave sanely. Keep a twitter_url accessor to rebuild https://twitter.com/{handle} on output.
Wrap it behind your own interface. Because the package is archived, do not let AltThree\Twitter\Facades\Twitter leak into twenty call sites:
interface MentionParser { public function handles(string $text): array; }
Bind your implementation to the package in a service provider. When you eventually replace it — you will — the swap is one line.
Model mutator + FormRequest combo. Normalise in a setTwitterAttribute mutator so seeders, imports and the API all get consistent data, and use a FormRequest rule (regex:/^[A-Za-z0-9_]{1,15}$/ applied to the parsed handle) for user-facing errors.
Rendering. When linking handles inside user text, run parse() to get the handles, then do a single preg_replace_callback over the original string to wrap them in anchors — do not loop str_replace on each handle, or you will double-link overlapping matches.
Testing. Fixture-test the parser with the nasty inputs (see below) rather than trusting it. If you wrap it, a fake implementation of your own interface keeps tests fast and decoupled.
[email protected] and https://example.com/@user will yield handles. Run an email/URL strip pass before parsing, or validate afterwards with a strict regex.Thanks @taylorotwell. should not produce taylorotwell.. Check whether the package trims; if not, rtrim($handle, '.,;:!?)').[A-Za-z0-9_]. The parser is probably permissive; enforce the limit yourself to avoid storing garbage that breaks your outbound links.@Foo @foo should collapse to one handle. array_unique(array_map('strtolower', $handles)).@ and Cyrillic lookalikes appear in scraped bios. If you accept arbitrary user input, either reject non-ASCII in the field or normalise with Normalizer::normalize() first.var_dump(Twitter::parse($input)) in php artisan tinker. There is no config to cache and no queue involved — if results look wrong, it is the regex, not your setup.twitter-text (the official conformance library) has PHP ports and is actively maintained; so does a ten-line regex if your needs are narrow. Plan the replacement at the same time you add the interface, not after the second Laravel upgrade breaks it.How can I help you explore Laravel packages today?