タイトルのとおりなのですが、諸事情によりハマってしまったのと最近ネタがないので書きます。

request->is() について


例えばhttps://example.com/test/fooというURLのリクエストで…

1
2
3
4
$request->is('hogeghoge');  // false
$request->is('*/test/foo'); // false
$request->is('*test*'); // true
$request->is('test/foo'); // true

と書くと、まあ上記のように引数に指定した文字列がHTTPリクエストのURLに一致するかどうか判定してくれる。んで、まあ2番目はOKそうに見えて実はダメで、ドメイン example.com から前はいりません。もうこの記事はここで結論が出てしまったように見えるのですが、今回書きたい本題はこれじゃないです。

環境


実際に試したのは5.5ですが5.8のソースコードもほぼ同じ(若干違いがあるが挙動に影響がでるものじゃない)なので、以下5.8のコードで説明します。

ソースコード見ながら確認


Laravelのコードを見ると下記のようになっています。

1
2
3
4
5
6
7
8
9
10
public function is(...$patterns)
{
$path = $this->decodedPath();
foreach ($patterns as $pattern) {
if (Str::is($pattern, $path)) {
return true;
}
}
return false;
}

実際に比較をしているのはStr::isのところで、そのコードはこちらです。

引数$pattern$this->decodedPath();の戻り値を比較しているわけでdecodedPathの戻り値は下記の通りで要するに$request->path()rawurlencodeしたものです。

1
2
3
4
public function decodedPath()
{
return rawurldecode($this->path());
}

ここで$request->path()は何を返すのか確認しましょう。下記のとおりです。

1
2
3
4
$request->path();    // test/fooが返ってくる

// ちなみにurlの場合
$request->url(); // https://example.com/test/foo

要するに$request->path()と比較しているのでドメイン部から前はいらないという話です。

この辺はだいたい公式のドキュメントに書いていて、なんでこんな記事を書いたかというと、めぼしい関数を探すためにIlluminate\Http\Requestクラスの中をざっと読んだ後で is関数に目を付けて isについて日本語で検索して間違った使い方を書いた記事を読んでハマった ということです。

公式のドキュメントとソースコードが唯一無二絶対神なので皆さんもこんな記事を読まずに公式のドキュメントとソースコードを読みましょう。

以上です。おわり。