【Laravel5.3】url(), redirect()使用時にURLが変わる場合の対処方法


使用環境

  • php7
  • Laravel5.3
  • Apache2.4

※上記を使用していますが、他Laravelバージョンでも応用可能かと思います。

問題点

プロキシサーバを通したあとの処理で、url(), redirect()を使用するとURLが変わってしまう』という問題が発生した。

たとえばurl('/user')とした際に、希望としてはhttp://example.co.jp/userというURLを取得したいにもかかわらず、http://hoge01.example.co.jp/userとプロキシサーバからサーバへアクセスするためのURLが使用されてしまう。

url()redirect()や、AuthまわりのReferrer機能をそのまま使用したい…

解決法

url()を探るとUrlGenerator.phpto()で絶対URLを取得している様子。

ということで、
vendor/laravel/framework/src/Illuminate/Contracts/Routing/UrlGenerator.phpto()をoverwriteできれば解決しそうです。

app/Providers/AppServiceProvider.phpregister()を修正

app/Providers/AppServiceProvider.php
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $url = $this->app['url'];
        $this->app->singleton('url', function () use ($url) {
            return new CustomUrlGenerator($url);
        });
    }

app/Providers/CustomUrlGenerator.php作成(2017/3/26修正)

app/Providers/CustomUrlGenerator.php
<?php
namespace App\Providers;

use Illuminate\Routing\UrlGenerator;

/**
 * Class CustomUrlGenerator
 * @package App\Providers
 */
class CustomUrlGenerator extends UrlGenerator
{
    /**
     * Create a new manager instance.
     *
     * @param Illuminate\Routing\UrlGenerator $url
     */
    public function __construct(UrlGenerator $url)
    {
        parent::__construct($url->routes, $url->request);
    }

    /**
     * Generate an absolute URL to the given path.
     *
     * @param  string $path
     * @param  mixed $extra
     * @param  bool $secure
     * @return string
     */
    public function to($path, $extra = [], $secure = null)
    {
        // First we will check if the URL is already a valid URL. If it is we will not
        // try to generate a new one but will simply return the URL as is, which is
        // convenient since developers do not always have to check if it's valid.
        if ($this->isValidUrl($path)) {
            return $path;
        }

        $scheme = $this->getScheme($secure);

        $extra = $this->formatParameters($extra);

        $tail = implode('/', array_map(
            'rawurlencode', (array) $extra)
        );

        // Once we have the scheme we will compile the "tail" by collapsing the values
        // into a single string delimited by slashes. This just makes it convenient
        // for passing the array of parameters to this URL as a list of segments.

        // Original
        //$root = $this->getRootUrl($scheme);
        $root = 'http://example.co.jp';

        if (($queryPosition = strpos($path, '?')) !== false) {
            $query = mb_substr($path, $queryPosition);
            $path = mb_substr($path, 0, $queryPosition);
        } else {
            $query = '';
        }

        return $this->trimUrl($root, $path, $tail).$query;
    }
}

まとめ

これでurl(), redirect()を無事プロキシサーバを通す前のURLで取得できました。

$root = 'http://example.co.jp'; は少し雑かもしれませんが、現時点ではこれで問題は特に起きていません。
getRootUrl()に手をいれるのもありかも知れません。

上記を行わずともプロキシサーバを通す前のURLを取得する方法がありましたら、教えていただければ幸いです。