kwi/urllinker
Laravel/PHP URL linker that scans text and converts web addresses, emails, and similar patterns into clickable HTML links. Lightweight helper for turning plain content into safe, formatted output in views, notifications, and user-generated text.
Installation
composer require kwi/urllinker
No additional configuration is required for basic usage.
First Usage
Use the UrlLinker class directly in your code:
use Kwi\UrlLinker\UrlLinker;
$text = "Check out https://laravel.com and http://example.com";
$linkedText = UrlLinker::link($text);
Output:
<a href="https://laravel.com">https://laravel.com</a> and <a href="http://example.com">http://example.com</a>
Where to Look First
Kwi\UrlLinker\Facades\UrlLinker for cleaner syntax in Laravel applications.Basic Linking Convert plain text URLs to HTML links:
$text = "Visit my site: example.com";
echo UrlLinker::link($text);
Output:
Visit my site: <a href="http://example.com">example.com</a>
HTML Context
Use linkHtml() for existing HTML content:
$html = '<p>Check <a href="#">here</a> or visit http://example.com</p>';
echo UrlLinker::linkHtml($html);
Output:
<p>Check <a href="#">here</a> or visit <a href="http://example.com">http://example.com</a></p>
Laravel Integration Service Provider (Recommended)
// app/Providers/AppServiceProvider.php
public function boot()
{
$this->app->singleton(UrlLinker::class);
}
Facade Usage
use Kwi\UrlLinker\Facades\UrlLinker;
$linkedText = UrlLinker::link($comment->text);
Blade Directives Create a custom Blade directive for templates:
// app/Providers/BladeServiceProvider.php
Blade::directive('linkUrls', function ($expression) {
return "<?php echo \\Kwi\\UrlLinker\\UrlLinker::link({$expression}); ?>";
});
Usage in Blade:
{!! linkUrls($post->content) !!}
Text Processing Pipeline
Combine with Laravel’s Str helper or other text processors:
$processedText = Str::markdown($markdownText);
$linkedText = UrlLinker::link($processedText);
Form Requests Auto-link URLs in form submissions or validation messages:
$validator = Validator::make($data, $rules);
$errors = $validator->errors();
$linkedErrors = collect($errors->all())
->map(fn($error) => UrlLinker::link($error))
->implode('<br>');
Custom Link Attributes
Extend the UrlLinker class to add custom attributes:
class CustomUrlLinker extends UrlLinker
{
protected function getLinkAttributes($url)
{
return 'target="_blank" rel="noopener noreferrer"';
}
}
Domain Whitelisting Filter URLs to only link specific domains:
$whitelistedUrls = UrlLinker::link($text, ['example.com', 'laravel.com']);
Event-Based Processing Use Laravel events to process URLs before storage or display:
// In a service or observer
event(new ProcessingComment($comment));
// Listener
public function handle(ProcessingComment $event)
{
$event->comment->linked_body = UrlLinker::link($event->comment->body);
}
API Responses Auto-link URLs in JSON:API or GraphQL responses:
return response()->json([
'data' => [
'id' => '1',
'type' => 'comment',
'attributes' => [
'body' => UrlLinker::link($comment->body),
],
],
]);
Email Templates
Use in Laravel’s Mailable classes:
public function build()
{
return $this->markdown('emails.comment')
->with(['comment' => UrlLinker::link($this->comment->body)]);
}
False Positives
example.com in a sentence) gets linked.linkHtml() for strict HTML contexts or adjust the regex in UrlLinker::getRegex().filter_var($url, FILTER_VALIDATE_URL).HTML Injection
$cleanHtml = Purifier::clean(UrlLinker::linkHtml($userInput));
Performance with Large Texts
linkHtml() for pre-existing HTML or implement caching:
Cache::remember("linked_{$text}", now()->addHours(1), function() use ($text) {
return UrlLinker::link($text);
});
Regex Limitations
UrlLinker::getRegex():
protected function getRegex()
{
return '/\b(?:https?:\/\/|www\.|ftp:\/\/)?[a-z0-9-]+(?:\.[a-z0-9-]+)+(?:[\/\?#][^\s"]*)?\b/i';
}
Nested HTML Conflicts
<a> inside <code>).linkHtml() for mixed content or disable linking in specific tags:
$dom = new \DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new \DOMXPath($dom);
// Disable linking in <code> tags
foreach ($xpath->query('//code') as $node) {
$node->parentNode->removeChild($node);
}
$cleanHtml = $dom->saveHTML();
echo UrlLinker::linkHtml($cleanHtml);
Inspect Regex Matches
Use preg_match_all to debug regex behavior:
preg_match_all(UrlLinker::getRegex(), $text, $matches);
dd($matches);
Log False Positives/Negatives Track edge cases for regex tuning:
$linked = UrlLinker::link($text);
if (strpos($text, 'example.com') !== false && strpos($linked, 'example.com') === false) {
Log::warning("False negative: $text");
}
Test with Edge Cases Validate against these inputs:
https://例子.测试http://[2001:db8::1]Visit http://example.com or \http://example.com``htp://missing-tldNo Built-in Config
UrlLinker class.getRegex(), getLinkAttributes(), or shouldLink().Default Behavior
http://, https://, and www. URLs.mailto:, tel:, or other protocols by default.HTML vs. Text
link() for plain text.linkHtml() for existing HTML to avoid double-encoding.link() method to add pre/post-processing:
class CustomUrl
How can I help you explore Laravel packages today?