Laravel — Использование значений, возвращаемых из группы промежуточного программного обеспечения, для глобальных переменных

#laravel #global-variables #middleware

#laravel #глобальные переменные #промежуточное программное обеспечение

Вопрос:

Справочная информация: Я хочу использовать один и тот же код для нескольких шаблонных веб-сайтов. Я хочу, чтобы код идентифицировал домен, к которому осуществляется доступ, а затем мог устанавливать глобальные переменные, которые будут использоваться во всем приложении.

Сначала я создал configglobal.php и логика там работала так, как ожидалось:

 $webUrl = url()->current();

/**************************************************
 * Set Conference name based on URL
 **************************************************/
$confId = 0;
$confName = '';
$confAbbrev = '';
if(strpos($webUrl, 'webdomain1') > 0) {
    $confName = 'Domain 1 Full Name';
    $confAbbrev = 'Dom1';
    $confId = 25;
}
elseif(strpos($webUrl, 'webdomain2') >0) {
    $confName = 'Domain 2 Full Name';
    $confAbbrev = 'Dom2';
    $confId = 35;
}
  

Однако в конечном итоге я обнаружил, что «url ()» вызывал ошибки, которые не позволяли мне использовать команды «php artisan» во всем приложении. После консультации с моим коллегой-профессиональным веб-разработчиком, он сказал, что использование «глобального» конфигурационного файла для глобальных переменных не является лучшей практикой, и рекомендовал вместо этого промежуточное программное обеспечение. Он взял под контроль мой ноутбук и работал ОЧЕНЬ быстро…

В appHttpKernel.php он добавил строку SetDomainVariables в конце $ middlewareGroups:

     protected $middlewareGroups = [
    'web' => [
        AppHttpMiddlewareEncryptCookies::class,
        IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
        IlluminateSessionMiddlewareStartSession::class,
        // IlluminateSessionMiddlewareAuthenticateSession::class,
        IlluminateViewMiddlewareShareErrorsFromSession::class,
        AppHttpMiddlewareVerifyCsrfToken::class,
        IlluminateRoutingMiddlewareSubstituteBindings::class,
        AppHttpMiddlewareSetDomainVariables::class,
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];
  

Затем он создал новый файл: appHttpMiddlewareSetDomainVariables.php

 <?php

namespace AppHttpMiddleware;

use Closure;

class SetDomainVariables
{
    /**
     * Handle an incoming request.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        dd($request->getHttpHost());
        return $next($request);
    }
}
  

Результаты «$request-> getHttpHost()» — это то, что мне нужно… он возвращает «foo» из www.foo.com. Однако я не знаю, как присвоить это значение переменной и вернуть его через «$ next», а затем, как я могу применить логику к этому, чтобы установить мои глобальные переменные, на которые я могу ссылаться в разделительной части и т.д.

Спасибо!

РЕДАКТИРОВАТЬ: если использовать configglobal.php действительно ли это правильный способ выполнить то, что я хочу, могу ли я просто закомментировать строку «url ()» всякий раз, когда я хочу выполнить команду «php artisan»?

Ответ №1:

Существует несколько различных способов решения этой проблемы, самым простым было бы использовать config — который позволяет динамически получать и устанавливать значения конфигурации.

  1. Создайте новый файл с именем, config/sites.php содержащий массив для каждого из ваших сайтов, гарантируя, что вы начинаете каждый домен с www и заменяете любой . в домене на - (поскольку . в ключе конфигурации это не сработает, поскольку Laravel использует точку для доступа к дочерним значениям).
 return [
    'default' => [
        'id' => 15,
        'name' => 'Default Full Name',
        'abbreviation' => 'Def',
    ],
    'www-webdomain1-com' => [
        'id' => 25,
        'name' => 'Domain 1 Full Name',
        'abbreviation' => 'Web1',
    ],
    'www-webdomain2-com' => [
        'id' => 35,
        'name' => 'Domain 2 Full Name',
        'abbreviation' => 'Web2',
    ],
];
  

Теперь у вас есть значения конфигурации для каждого из ваших сайтов, доступные в любом месте вашего приложения, например: config('sites.www-webdomain1-com.name') .

  1. Добавьте следующее в свое промежуточное программное обеспечение:
 public function handle($request, Closure $next)
{
    $host = str_slug(starts_with('www.', $request->getHttpHost()));

    $configuration = config("sites.{$host}") ?: config('sites.default');

    config(['site' => $configuration]);

    return $next($request);
}
  

Теперь вы установили значение конфигурации для ключа site для содержимого конфигурации сайта, которую вы задали в config/sites.php для домена запроса.

  1. Везде, где вам нужно получить доступ к опции конфигурации активного сайта, используйте config('site.property') , например:
 Hello, welcome to {{ config('site.name') }}
  

Есть лучшие способы решения этой проблемы, лично я бы создал Site модель, а затем использовал привязку модели маршрута, однако способ, который я описал здесь, очень прост в настройке для новичка и должен соответствовать вашим потребностям.

Комментарии:

1. Спасибо. Если бы я пошел этим путем, смог бы я подключиться к своей базе данных в config/sites.php ? Приведенный выше пример (жестко запрограммированный идентификатор, имя и аббревиатура для каждого клиентского веб-сайта) был скорее для того, чтобы просто убедиться, что у меня есть данные для тестирования. Но у меня есть таблица в моей базе данных, куда я мог бы передать доменное имя и динамически возвращать идентификатор, название, аббревиатуру для правильной конференции. Прямо сейчас у меня 2 клиента, но если я получу более 10 клиентов, я чувствую, что один вызов DB (передача имени домена) был бы более масштабируемым.

2. Если вы делаете это на основе базы данных, тогда привязка модели маршрута является правильным подходом, это очень просто. Вы создаете группу маршрутов поддомена («Маршрутизация поддомена» в документации по маршрутизации) и создаете явную привязку модели маршрута для ключа, который вы используете в маршруте вашего домена, например: Route::domain('{conference}.example.com )` и затем Route::bind('conference', ...) — все это описано в документации. Дайте мне знать, если вам нужны дополнительные рекомендации.

3. На будущее, когда вы задаете подобный вопрос, лучше всего сначала описать, чего вы пытаетесь достичь, например: «У меня есть конференции в моей базе данных, и я хочу, чтобы у каждой конференции была страница, доступная через уникальный поддомен, который определяется domain свойством модели, например: conference.example.com is Conference id 1″, а не описывать, каково ваше решение / что вы считаете решением. Это дает людям информацию, наиболее необходимую для того, чтобы помочь вам достичь ваших целей 🙂

4. Я ценю ваш вклад. Я постараюсь внедрить рекомендованные вами изменения в течение следующих нескольких дней. Одно уточнение… это будут отдельные домены, а не поддомены одного и того же веб-сайта. Мой первый клиентский веб-сайт www.pac7sports.org … Моим вторым клиентом будет отдельная конференция. Но из-за характера контента (спортивные результаты и т.д.), Они будут использовать одну и ту же базу данных, но будут полностью отдельными доменами, на которые я планирую развернуть один и тот же точный код, чтобы минимизировать обслуживание.

5. Вам не нужно развертывать одну и ту же кодовую базу несколько раз, вы можете указать несколько доменов в одной и той же установке Laravel, а затем использовать домен (будь то поддомены или полные домены), чтобы определить, какие данные загружаются.