nahid/linkify
nahid/linkify is a lightweight PHP and Laravel package that converts plain-text URLs and email addresses into clickable HTML links, with configurable attributes, target and rel handling, and simple integration for linkifying user posts, comments, and bios safely.
Install
composer require nahid/linkify
This is a 2016-era Laravel 5 wrapper around misd/linkify. It predates package auto-discovery (5.5+), so you must register it manually.
Register in config/app.php
'providers' => [
// ...
Nahid\Linkify\LinkifyServiceProvider::class,
],
'aliases' => [
// ...
'Linkify' => Nahid\Linkify\Facades\Linkify::class,
],
Confirm the exact namespace/method names by opening
vendor/nahid/linkify/src/— the README is sparse, and the facade delegates toMisd\Linkify\Linkify. The service provider and facade files are the source of truth.
First use case — turning user-submitted plain text (comments, forum posts, bios, ticket bodies) into clickable URLs/emails without asking users to write markdown or HTML:
// app/Http/Controllers/CommentController.php
$comment->body_html = Linkify::convert(e($comment->body));
Where to look first
vendor/nahid/linkify/src/LinkifyServiceProvider.php — what it binds.vendor/nahid/linkify/src/Facades/Linkify.php — the public method surface.vendor/misd/linkify/src/Misd/Linkify/Linkify.php — the real implementation and options array.composer.json — check the illuminate/support constraint before assuming it runs on your Laravel version.Blade rendering (the 90% case)
{{-- Escape FIRST, then linkify, then optionally add line breaks --}}
{!! nl2br(Linkify::convert(e($comment->body))) !!}
Always escape before linkifying. Linkify wraps URLs in <a> tags but does not sanitize HTML. The pattern is e() → Linkify::convert() → {!! !!}, never Linkify::convert($raw).
Custom link attributes — pass an options array (mirrors Misd\Linkify\Linkify's constructor/call options):
Linkify::convert($text, [
'attr' => [
'target' => '_blank',
'rel' => 'nofollow noopener',
'class' => 'text-link',
],
]);
Centralize it in a presenter or Blade directive — don't scatter Linkify::convert across views:
// app/Presenters/TextPresenter.php
class TextPresenter
{
public static function linkify(?string $text): string
{
return nl2br(Linkify::convert(e($text ?? ''), [
'attr' => ['rel' => 'nofollow noopener', 'target' => '_blank'],
]));
}
}
{!! \App\Presenters\TextPresenter::linkify($comment->body) !!}
Consistency across channels — reuse the same presenter in:
Mail::send)body_html alongside body// app/Http/Resources/CommentResource.php
return [
'body' => $this->body,
'body_html' => TextPresenter::linkify($this->body),
// or omit body_html and let the frontend render
];
Testing — mock the facade so tests don't depend on regex behavior:
Linkify::shouldReceive('convert')
->once()
->with('see http://example.com', Mockery::any())
->andReturn('see <a href="http://example.com">http://example.com</a>');
Performance — linkifying on every render of a comment list re-runs regex per row. Cache the compiled HTML (body_html column or a Cache::remember) if you display many linkified fields on a hot page.
Fallback to the underlying library when the facade lacks what you need:
$linkify = new \Misd\Linkify\Linkify(); // per-call control
$linkify->convert($text, $options);
No auto-discovery, no maintained support. This is a 2016 Laravel 5 wrapper. On Laravel 5.5+ it won't register itself; on Laravel 6+/8+ the illuminate/support constraint may block installation entirely. Verify composer show nahid/linkify before committing.
License is NOASSERTION. License is unclear — treat as "unknown" and check with legal before shipping it in a commercial product. Combined with the abandoned misd/linkify parent, there are no security fixes upstream.
XSS footgun — the big one. {!! Linkify::convert($userInput) !!} is an injection vector: any <script> in the text passes through untouched. Always e() first. Also strip already-present anchors if input may include them:
$safe = strip_tags($text); // if you truly only want plain text
Linkifying text that already contains <a> tags risks nested anchors or mangled markup — linkify plain text only.
Double-linkifying / nested anchors — if a value is rendered twice (e.g., an accessor plus a view call), or if the text already has links, you'll get nested <a> and broken output. Decide once where linkification happens.
Trailing punctuation and edge cases. URLs ending a sentence (http://example.com.) may absorb the period or fail depending on the misd/linkify version. Test with prose and parentheses. Schemes are limited — relative paths (/docs/foo), mailto: without an @, and plain domains without a scheme generally aren't linked.
Emails vs URLs. Misd\Linkify\Linkify exposes separate URL/email conversion toggles; the wrapper may only surface convert(). If you need to link URLs but not emails (or vice versa), instantiate Misd\Linkify\Linkify directly.
Options arrays are silently ignored if malformed. The wrapper may pass options straight to misd/linkify; unknown keys do nothing rather than throw. When debugging styling/attributes, dd((new \Misd\Linkify\Linkify())->convert($text, $opts)) to isolate the library from the facade.
Config publishing. There is likely no config/linkify.php. Don't assume vendor:publish exists — configure per call or via your presenter.
Extension point. Custom callbacks (Linkify::setCallback) and per-call attributes live in the underlying misd library, not necessarily the facade. Subclass or instantiate it directly if the wrapper gets in the way.
Consider modern replacements. For new projects prefer maintained options:
GrahamCampbell/Linkify — the maintained successor for Laravel.symfony/string / manual regex for non-Laravel contexts.Migrate if you're on Laravel 6+ — the cost of pinning this abandoned chain usually outweighs the convenience.
How can I help you explore Laravel packages today?