Метод toUri() у Laravel для динамічного формування URL-адрес

Перекладено ШІ
Оригінал: Laravel News
Оновлено: 16 липня, 2025
Справжня магія Laravel ховається у методі `toUri()`, який перетворює обробку URL на прості та зручні операції. Дізнайтеся, як цей метод спрощує маніпуляції з URI, роблячи ваш код більш читабельним і легким у підтримці

Метод toUri() у Laravel перетворює обробку рядкових URL у гнучку маніпуляцію з URI, що дозволяє динамічно додавати й змінювати параметри за допомогою ланцюжкових викликів методів

Традиційна обробка URL передбачає складну маніпуляцію рядками та логіку парсингу:

$text = 'Завітайте {https://api.service.com/endpoint} для доступу до даних.';
preg_match('/\{(.*?)\}/', $text, $matches);
$baseUrl = $matches[1];
$finalUrl = $baseUrl . '?' . http_build_query($params);

Новий підхід спрощує це завдання, перетворюючи складні операції на легко читабельні та зрозумілі завдяки допоміжним рядковим методам Laravel

$uri = str($text)->between('{', '}')->toUri();
$finalUrl = $uri->withQuery(['key' => 'value'])->value();

Ось всебічна система сповіщень, що демонструє різні сценарії маніпуляції з URI:

class NotificationService
{
    public function processEmailTemplate(string $template, User $user): string
    {
        $actionUrl = str($template)
            ->between('[ACTION_URL]', '[/ACTION_URL]')
            ->toUri();
 
        if ($user->hasRole('premium')) {
            $actionUrl = $actionUrl
                ->withQuery(['tier' => 'premium'])
                ->withQuery(['features' => 'advanced'])
                ->withFragment('dashboard');
        } else {
            $actionUrl = $actionUrl
                ->withQuery(['tier' => 'basic'])
                ->withQuery(['upgrade' => 'available']);
        }
 
        $trackingUrl = $actionUrl
            ->withQuery(['utm_source' => 'email'])
            ->withQuery(['utm_campaign' => 'user_engagement'])
            ->withQuery(['user_id' => $user->id]);
 
        return str($template)->replace(
            '[ACTION_URL]' . str($template)->between('[ACTION_URL]', '[/ACTION_URL]') . '[/ACTION_URL]',
            $trackingUrl->value()
        );
    }
 
    public function generateApiEndpoints(array $baseUrls, array $parameters): array
    {
        $endpoints = [];
 
        foreach ($baseUrls as $service => $url) {
            $uri = str($url)->toUri();
 
            $uri = $uri->withQuery(['api_version' => $parameters['version'] ?? 'v1'])
                      ->withQuery(['format' => $parameters['format'] ?? 'json']);
 
            if (isset($parameters['auth_token'])) {
                $uri = $uri->withQuery(['token' => $parameters['auth_token']]);
            }
 
            if (isset($parameters['timeout'])) {
                $uri = $uri->withQuery(['timeout' => $parameters['timeout']]);
            }
 
            $endpoints[$service] = $uri->value();
        }
 
        return $endpoints;
    }
 
    public function buildDownloadLinks(Collection $files, string $baseTemplate): Collection
    {
        return $files->map(function ($file) use ($baseTemplate) {
            $downloadUri = str($baseTemplate)
                ->replace('{FILE_ID}', $file->id)
                ->toUri();
 
            $downloadUri = $downloadUri
                ->withQuery(['expires' => now()->addHours(24)->timestamp])
                ->withQuery(['signature' => $this->generateSignature($file)])
                ->withQuery(['download' => 'true']);
 
            if ($file->requires_authentication) {
                $downloadUri = $downloadUri->withQuery(['auth' => 'required']);
            }
 
            return [
                'file_id' => $file->id,
                'name' => $file->name,
                'download_url' => $downloadUri->value(),
                'expires_at' => now()->addHours(24)->toISOString()
            ];
        });
    }
 
    public function createWebhookUrls(string $configTemplate, array $webhookData): array
    {
        $webhooks = [];
 
        foreach ($webhookData as $event => $endpoint) {
            $webhookUri = str($configTemplate)
                ->replace('{ENDPOINT}', $endpoint)
                ->toUri();
 
            $webhookUri = $webhookUri
                ->withQuery(['event' => $event])
                ->withQuery(['secret' => $this->generateWebhookSecret()])
                ->withQuery(['version' => '2024-07']);
 
            if ($event === 'payment_completed') {
                $webhookUri = $webhookUri
                    ->withQuery(['priority' => 'high'])
                    ->withQuery(['retry_count' => '3']);
            }
 
            $webhooks[$event] = [
                'url' => $webhookUri->value(),
                'secret' => $this->generateWebhookSecret(),
                'events' => [$event]
            ];
        }
 
        return $webhooks;
    }
 
    private function generateSignature($file): string
    {
        return hash_hmac('sha256', $file->id . $file->name, config('app.key'));
    }
 
    private function generateWebhookSecret(): string
    {
        return 'whsec_' . bin2hex(random_bytes(24));
    }
}
 
class RedirectController extends Controller
{
    public function buildRedirectUrl(Request $request): string
    {
        $baseRedirect = 'https://app.example.com/dashboard';
 
        $redirectUri = str($baseRedirect)->toUri();
 
        if ($request->has('campaign')) {
            $redirectUri = $redirectUri->withQuery(['utm_campaign' => $request->input('campaign')]);
        }
 
        if ($request->has('source')) {
            $redirectUri = $redirectUri->withQuery(['utm_source' => $request->input('source')]);
        }
 
        if (auth()->check()) {
            $redirectUri = $redirectUri
                ->withQuery(['user' => auth()->id()])
                ->withFragment('welcome');
        } else {
            $redirectUri = $redirectUri->withFragment('login');
        }
 
        return $redirectUri->value();
    }
}

Метод toUri() спрощує маніпуляцію з URL, зберігаючи при цьому конвенції гнучкого інтерфейсу Laravel, що робить складне створення URI читабельним та легким у підтримці