Laravel-正規表現ルートはすべてに一致しますが、1つ以上の単語に完全には一致しません


8

私はのようなルートを作ります

Route::get('/{url1}', function ($url1) {
    return ' url1: '.$url1;
})
->where('url1', '^(?!(string1|string2)$)');

そして、次のようなURLにアクセスします
- domain/abc 見つかりません=>間違っていますか?
- domain/string1見つかりません=>正しい

そして、私がするとき

Route::get('/{url1}/{url2}', function ($url1) {
    return ' url1: '.$url1;
})
->where('url1', '^(?!(string1|string2)$)');

アクセスURLのように:
- domain/abc/abc =>が間違っていません
- domain/string1/abc見つかりません=>正しい

その感謝を修正する方法


文字列が静的または動的になる場所では?
Mitesh Rathod

@MiteshRathod string1およびstring2は特別な単語(静的)
DeLe

この2つの文字列のみがURLで受け入れられません、正しいですか?
Mitesh Rathod

@MiteshRathodはい、string1またはstring2はURLで受け入れられません
DeLe

正確な正規表現を追加してください。
REVO

回答:


3

これを最初のシナリオで試してください:

Route::get('/{url1}', function ($url1) {
    return ' url1: '.$url1;
})->where('url1', '^!(string1|string2)$');

2番目のシナリオの場合:

Route::get('/{url1}/{url2}', function ($url1, $url2) {
    return ' url1: '.$url1 . ' url2: '.$url2;
})->where('url1', '^!(string1|string2)$');

私はこの助けを願っています:)


thankiuでも、1つ目を試してみますが、domain/abc見つかりませんか?
DeLe

3

これを試して

 Route::get('{url1}', function ($url1) {
    return ' url1: '.$url1;
})->where('url1','^(?!string1$|string2$)([a-zA-Z0-9-]+)');

これを達成するための汚れた方法

Route::get('{url1}/{url2?}', function ($url1,$url2 = null) {
        if ($url2 == "string1" || $url2 == "string2" || $url1 == "string1" || $url1 == "string2") {
            return "false";
        } else {
            return "true";
        }
});

私が使用して試したもう1つの方法 RouteServiceProvider.php

boot()このように変更してください。

public function boot()
    {
        //
        Route::pattern('url1', '^(?!string1$|string2$)([a-zA-Z0-9-]+)');
        Route::pattern('url2', '^(?!string1$|string2$)([a-zA-Z0-9-]+)');
        parent::boot();
    }

ありがとう、でもうまくいきません。私は試すだけですdomain/string1=>それはまだ見つかります
DeLe

@DeLeおかしい同じコードを試しましたが、s excluding 127.0.0.1: 8000 / domain / string2 , 127.0.0.1:8000/domain/string1 `と動作しますhttp://127.0.0.1:8000/domain/abc
Prashant Deshmukh .....

申し訳ありませんのためにdomaindomain同様にhttp://127.0.0.1:8000あなたは試してみてくださいと127.0.0.1:8000/string1、...
DELE

@DeLe更新されました。今すぐ確認してください。
Prashant Deshmukh .....

1
@DeLeを使用して、更新された回答を確認してくださいRouteServiceProvider
Prashant Deshmukh .....

3

テストの後、私はあなたが望むものを正確に達成することは不可能だと思います。除外したいとき、それはそうですstring1し、string2あなたは、文字列で始まることに同意する必要がありますstring1し、string2(そう例えば除外されますstring1aaa)。

そのようなルートを使用する場合:

Route::get('/{url1}', function ($url1) {
    return ' url1: '.$url1;
})->where('url1', '(?!string1|string2)[^\/]+');


Route::get('/{url1}/{url2}', function ($url1, $url2) {
    return ' url1: '.$url1. ' # '.$url2;
})->where('url1', '(?!string1|string2)[^\/]+');

結果は次のようになります:

domain/abc - found, correct
domain/string1 - not found, correct
domain/abc/abc - found, correct
domain/string1/abc - not found, correct
domain/string1aaa - not found, I believe you need to accept this
domain/string1aaa/abc - not found, I believe you need to accept this

私はそのような制限が正規表現からではなくLaravelから来ていると思います。あなたも始まるパラメータを受け入れる必要がある場合string1string2、私はあなたがそうのような手動の方法でそれを行う必要があると考えています:

Route::get('/{url1}', function ($url1) {
    if (!preg_match('#^(?!string1$|string2$)[^\/]*$#', $url1)) {
        abort(404);
    }

    return ' url1: '.$url1;
});


Route::get('/{url1}/{url2}', function ($url1, $url2) {
    if (!preg_match('#^(?!string1$|string2$)[^\/]*$#', $url1)) {
        abort(404);
    }

    return ' url1: '.$url1. ' # '.$url2;
});

1

この正規表現を試してください:

    Route::get('/{url1}', function ($url1) {
        return 'url: '.url1;
    })->where('url1', '^(?!(string1|string2)$)(\S+)');

thankiu、しかし私がhttp://domain/string1/abcそれを試してみると、まだ見つかりますか?
DeLe

1

特定の静的文字列以外に一致するルートを作成するよりも、2つのルートを作成する方が明確です。

// route that matches forbidden static strings, optionally with a postfix slug
$router->get('/{forbidden}/{optional_path?}', function () {
    return response('Not found', 404);
})->where([ 'forbidden' => '(?:string1|string2)', 'optional_path' => '.*' ]);

// route that matches anything else (order of definition matters, must be last)
// might also consider using Route::fallback(), but I prefer to leave that
// alone in case my future self changes this below and opens up a hole
$router->get('/{anything?}', function () {
    return response('Found', 200);
})->where([ 'anything' => '.*' ]);

結果は*

  • domain => 200件見つかりました
  • domain/ => 200件見つかりました
  • domain/abc => 200件見つかりました
  • domain/string1 => 404見つかりません
  • domain/string1/ => 404見つかりません
  • domain/string1/abc => 404見つかりません
  • domain/string10 => 200件見つかりました
  • domain/string10/ => 200件見つかりました
  • domain/string10/abc => 200件見つかりました
  • domain/string2 => 404見つかりません
  • domain/string2/ => 404見つかりません
  • domain/string2/abc => 404見つかりません
  • domain/string20 => 200件見つかりました
  • domain/string20/ => 200件見つかりました
  • domain/string20/abc => 200件見つかりました

除外について考える必要がないので、私はこれがより明確だと思います。むしろ、私が禁止したいものと正確に一致し、Laravelに他のすべてのものに反応させる(フェールオープンポリシー)と考えることができます。これは設計基準を満たさない可能性がありますが、コードがより明確になると思います。

また、コードのパフォーマンスが向上しています。 ?!バックトラックする必要があります。これは、定義により、フォワードマッチングよりもコストが高くなります。

Laravelの環境はありませんが、あなたの試みがうまくいかなかった理由を推測するつもりです。LaravelはSymfonyルーターを使用しますが、Slugのルックアラウンドをサポートしいません。IIRC、ルックアラウンドが検出されると、Symfonyはルックアラウンドを、パターンをバインドしたスラッグではなく、URL全体に適用します。これは、アンカー(^、$)と貪欲(*)のメタ文字がどのように機能するかについての開発者の考えを混乱させます。開発者はある仮定の下で動作しているが、基礎となるライブラリは別の仮定で動作しているため、これを機能させようとすると、悪い経験につながる可能性があります。


*完全な開示。私はこれをルーメンのために書いた後、精神的にそれをララヴェル形式に変換しました。変換エラーが発生している可能性があります。これがオリジナルのルーメンです:

$router->get('/{forbidden:(?:string1|string2)}[/{optional_path:.*}]', function () {
    return response('Not found', 404);
});
$router->get('{anything:.*}', function () {                                   
    return response('Found', 200);
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.