En lugar de escribir una ruta para que coincida con cualquier otra cosa que no sean ciertas cadenas estáticas, me resulta más claro escribir dos rutas: una ruta para que coincida con ciertas cadenas estáticas, y otra ruta para que coincida con todo lo demás.
// 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' => '.*' ]);
Lo que resulta en * :
domain
=> 200 encontrados
domain/
=> 200 encontrados
domain/abc
=> 200 encontrados
domain/string1
=> 404 No encontrado
domain/string1/
=> 404 No encontrado
domain/string1/abc
=> 404 No encontrado
domain/string10
=> 200 encontrados
domain/string10/
=> 200 encontrados
domain/string10/abc
=> 200 encontrados
domain/string2
=> 404 No encontrado
domain/string2/
=> 404 No encontrado
domain/string2/abc
=> 404 No encontrado
domain/string20
=> 200 encontrados
domain/string20/
=> 200 encontrados
domain/string20/abc
=> 200 encontrados
Me parece más claro, porque no tengo que pensar en términos de exclusiones. Por el contrario, puedo pensar en igualar exactamente lo que quiero prohibir, y luego dejar que Laravel reaccione a todo lo demás (política abierta fallida). Es posible que esto no cumpla con sus criterios de diseño, pero creo que da como resultado un código más claro.
Además, el código es más eficiente. ?!
tiene que retroceder, que es, por definición, más costoso que la correspondencia hacia adelante.
No tengo un entorno Laravel a mano, pero me arriesgaré a adivinar por qué tus intentos no funcionaron. Laravel utiliza Symfony Router, que no admite búsquedas en babosas . IIRC, cuando se detecta una búsqueda, Symfony aplica la búsqueda a toda la URL, no a la babosa a la que ha vinculado el patrón. Esto se mete con la idea del desarrollador de cómo funcionan los metacaracteres de anclajes (^, $) y codiciosos (*). Esto puede conducir a una mala experiencia al intentar que funcione, ya que el desarrollador opera bajo una suposición pero las bibliotecas subyacentes operan en otra.
* Revelación completa, escribí esto para Lumen y luego lo convertí mentalmente al formato Laravel. Es posible que haya algunos errores de traducción. Aquí está el Lumen original:
$router->get('/{forbidden:(?:string1|string2)}[/{optional_path:.*}]', function () {
return response('Not found', 404);
});
$router->get('{anything:.*}', function () {
return response('Found', 200);
});