LoginSignup
5

More than 3 years have passed since last update.

【Laravel】routeメソッドやリダイレクトで生成されるURLのホスト名を指定する

Last updated at Posted at 2019-12-24

経緯

Laravel6.0

・Laravelはルートを指定していない場合$_SERVERから取得する。

$_SERVERの値はサーバーの設定により決まる。
PHP: $_SERVER - Manual

・サーバーの設定が複雑で期待する値が取得できなかった。

・リダイレクトやrouteメソッドで生成されるURLに影響がでて正しく遷移できない。

結論

UrlGeneratorにルートURLを設定することで、生成されるURLを固定できる

app/Privider/AppServiceProvider.php

    public function boot()
    {
        // ルートURLを設定
        Illuminate\Support\Facades\URL::forceRootUrl(\config('app.url'));

        // 必要に応じてsslを強制する
        if (\config('app.env') !== 'local') {
            Illuminate\Support\Facades\URL::forceScheme('https');
        }
    }
.env
APP_URL=https://foo.com

ソースコード(ざっくり)

Illuminate/Routing/UrlGenerator.phpforcedRootを指定することで生成されるURLを変更できる。

Illuminate/Routing/UrlGenerator.php


    public function formatRoot($scheme, $root = null)
    {
        if (is_null($root)) {
            if (is_null($this->cachedRoot)) {
                // forcedRootが設定されている場合は優先されるみたい。
                $this->cachedRoot = $this->forcedRoot ?: $this->request->root();
            }

            $root = $this->cachedRoot;
        }

        $start = Str::startsWith($root, 'http://') ? 'http://' : 'https://';

        return preg_replace('~'.$start.'~', $scheme, $root, 1);
    }

    // forcedRootを設定するためのメソッドがある
    public function forceRootUrl($root)
    {
        $this->forcedRoot = rtrim($root, '/');

        $this->cachedRoot = null;
    }

forcedRootが指定されていない場合は$_SERVERから値を取得しているみたい。

symfony/http-foundation/Request.php
 public function getHost()
    {
        // ここの処理がいまいちわかってない
        // プロキシを指定したときなどに関係ありそう
        if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) {
            $host = $host[0];

        // $_SERVERから取得している
        } elseif (!$host = $this->headers->get('HOST')) {
            if (!$host = $this->server->get('SERVER_NAME')) {
                $host = $this->server->get('SERVER_ADDR', '');
            }
        }

Symfony2のコントローラについてまとめた(後半) - OTOBANK Engineering Blog

// $_SERVER['DOCUMENT_ROOT']
$request->server->get('DOCUMENT_ROOT');

// \$_SERVERのインデックスのうち、命名がHTTP_*に該当するもの
// \$_SERVER['HTTP_USER_AGENT']
$request->header->get('user-agent');

優先順位的には

  1. $this->forcedRoot
  2. $_SERVER['HTTP_HOST']
  3. $_SERVER['SERVER_NAME']
  4. $_SERVER['SERVER_ADDR']

になりそう。多分。

テスト(追記)

PHPUnitでテストを行う場合はphpunit.xmlAPP_URLを空にしておく。

FooTest.php
$response= $this->get('foo/bar');
$response->assertStatus(200);
phpunit.xml
<php>
        <server name="APP_URL" value=""/>
</php>

この記述がない場合、404がかえってきてテストが失敗してしまいました。

参考

LaravelのURLジェネレーターで.envに設定したホスト名を使用する。 - Qiita

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5