web-dev-qa-db-fra.com

Laravel - Utilisation du caractère générique (: any?) Pour TOUS les itinéraires?

J'ai un peu de mal avec le routage.

Je travaille sur un CMS, et j'ai besoin de deux routes principales. /admin Et /(:any). Le contrôleur admin est utilisé pour la route /admin, Et le contrôleur view doit être utilisé pour autre chose que /admin. À partir du contrôleur view, je vais ensuite analyser l'URL et afficher le contenu correct.

Voici ce que j'ai:

Route::get(array('admin', 'admin/dashboard'), array('as' => 'admin', 'uses' =>'admin.dashboard@index'));
Route::any('(:any)', 'view@index');

Le premier itinéraire fonctionne, mais le second ne fonctionne pas. J'ai un peu joué avec cela, et il semble que si j'utilise (:any) Sans point d'interrogation, cela ne fonctionne que si je mets quelque chose après /. Si i do place le point d'interrogation ici, cela ne fonctionne pas du tout.

Je veux que tous les itinéraires suivants aillent voir @ index:

/
/something
/something/something
/something/something/something
/something/something/something/something
...etc...

Est-ce possible sans coder en dur un groupe de (:any?)/(:any?)/(:any?)/(:any?) (Que je ne sais même pas qui fonctionne)?

Quelle est la meilleure façon de s'y prendre?

49
qwerty

Edit: Il y a eu une certaine confusion depuis la publication de Laravel 4 à propos de ce sujet, cette réponse ciblait Laravel 3.

Il y a plusieurs façons d'aborder cela.

La première méthode correspond à (:any)/(:all?):

Route::any('(:any)/(:all?)', function($first, $rest=''){
    $page = $rest ? "{$first}/{$rest}" : $first;
    dd($page);
});

Pas la meilleure solution car elle est divisée en plusieurs paramètres, et pour une raison quelconque (: tout) ne fonctionne pas tout seul (bug?)

La deuxième solution consiste à utiliser une expression régulière, ce qui est une meilleure méthode que ci-dessus, à mon avis.

Route::any( '(.*)', function( $page ){
    dd($page);
});

Il existe une autre méthode, qui vous permet de vérifier s'il existe des pages cms même si l'itinéraire a pu correspondre à d'autres modèles, à condition que ces itinéraires renvoient un code 404. Cette méthode modifie l'écouteur d'événements défini dans routes.php:

Event::listen('404', function() {
    $page = URI::current();
    // custom logic, else
    return Response::error('404');
});

Cependant, ma méthode préférée est la n ° 2. J'espère que ça aide. Quoi que vous fassiez, assurez-vous de définir tous vos autres itinéraires au-dessus de ceux-ci. Tous les itinéraires définis, aucun itinéraire défini après ne sera déclenché.

26

Laravel 5

Cette solution fonctionne bien sur Laravel 5:

Route::get('/admin', function () {

  // url /admin

});

Route::get('/{any}', function ($any) {

  // any other url, subfolders also

})->where('any', '.*');

Lumen 5

Ceci est pour Lumen à la place:

$app->get('/admin', function () use ($app) {
  //
});

$app->get('/{any:.*}', function ($any) use ($app) {
  //
});
81
Andrea

Frapper un statut 404 me semble un peu faux. Cela peut vous exposer à toutes sortes de problèmes lors de la journalisation des 404. J'ai récemment rencontré le même problème de routage générique dans Laravel 4) et je l'ai résolu avec l'extrait de code suivant:

Route::any('{slug}', function($slug)
{
    //do whatever you want with the slug
})->where('slug', '([A-z\d-\/_.]+)?');

Cela devrait résoudre votre problème de manière contrôlée. L'expression régulière peut être simplifiée pour:

'(.*)?'

Mais vous devriez utiliser ceci à vos risques et périls.

Edit (addition):

Comme cela écrase beaucoup de routes, vous devriez envisager de l'envelopper dans une instruction "App :: before":

    App::before(function($request) {
            //put your routes here
    });

De cette façon, les itinéraires personnalisés que vous définissez par la suite ne seront pas écrasés.

46
Eelke van den Bos
Route::get("{path}", "SomeController@serve")->where('path', '.+');

Le code ci-dessus capturera les sous-URL récursives que vous avez mentionnées:

/
/something
/something/something
/something/something/something
/something/something/something/something

Tout autre cas spécial, tel que admin/*, vous pouvez capturer avant celui-ci.

7
Guy

Ajouter ceci dans le fichier de fin d'itinéraires

App::missing(function($exception)
{
    return View::make('notfound');
});

de http://scotch.io/tutorials/simple-and-easy-laravel-routing

5
Edmhs

Expliquez simplement mon expérience au cas où cela aiderait quelqu'un à rassembler quelque chose.

J'ai construit une application auto-API React sur Laravel. Elle n'a qu'une seule vue servie par Laravel/Lumen. Elle utilise le routeur React. - Les liens dans l'application fonctionnaient toujours, mais la saisie des URL nécessitait la prise en compte suivante:

Dans Laravel j'ai utilisé ce qui suit dans mon fichier de routes web.php:

Route::view('/{path?}', 'app')
    ->where('path', '.*')
    ->name('react');

Et tout a fonctionné.

Ensuite, j'ai basculé le projet vers Lumen. Grâce à ce message, j’ai utilisé les éléments suivants dans mon fichier de routes web.php:

$router->get('/{all:.*}', function() {
    return view('app');
});

Cela a fonctionné pour les URL de premier niveau telles que:

/
/something 

Cependant,

/something/something etc.

n'a pas.

J'ai consulté l'onglet Réseau des outils de développement Google et constaté que l'URL de app.js était en train d'ajouter /quelque chose devant app.js à la seconde et URL de niveau supérieur, telles que:

myapp.com/something
app.js URL:  myapp.com/js/app.js  (as it should be)

myapp.com/something/something
app.js URL:  myapp.com/something/js/app.js  (not found)

Tout ce que je devais faire était d'ajouter une barre oblique à ma source app.js dans ma page d'affichage unique, telle que:

<script src="/js/app.js" defer></script>

Au lieu de:

<script src="js/app.js" defer></script>

alors:

Cela fonctionnait dans Laravel (c'était un fichier Blade qui aurait pu résoudre automatiquement l'URL js/app.js)

<script src="{{ asset('js/app.js') }}" defer></script>

avec

Route::view('/{path?}', 'app')
    ->where('path', '.*')
    ->name('react');

Mais, je devais le faire dans Lumen (pas un fichier Blade) :

<script src="/js/app.js" defer></script>

avec

$router->get('/{all:.*}', function() {
    return view('app');
});
2
Luke

Merci pour la solution William. Cependant, les méthodes 1 et 2 ne fonctionnent plus Laravel 4, et pour utiliser la solution n ° 3 dans Laravel 4, vous devrez déclencher l'événement 404 dans votre fichier start/global.php.

App::error(function(Exception $exception, $code)
{
    // i.o. -> this is our catchall!
    // http://stackoverflow.com/questions/13297278/laravel-using-any-wildcard-for-all-routes
    Event::fire('404');

    return View::make('error')->with('exception', $exception)->with('code', $code);

    Log::error($exception);
});

Nous pouvons maintenant gérer cela dans notre fichier routes.php:

Event::listen('404', function() {
    // url?
    $url = Request::path();

    // LOGIC HERE

    // else
    return View::make('error');
});
2
Chris Schalenborgh

Avoir un échafaudage Lumen de base. Dans mon cas, j'ai 2 applications frontend et routes api

<?php // routes/web.php
/** @var \Laravel\Lumen\Routing\Router $router */

$router->group([
    'prefix' => '/api/v1',
    'namespace' => 'App\Http\Controllers'
], function () use ($router) {

    require 'routes-group1.php';
    require 'routes-group2.php';
    // ...
});

$router->get('/admin{any:.*}', function () {
    return file_get_contents('../public/a/index.html');
});

$router->get('{any:.*}', function () {
    return file_get_contents('../public/m/index.html');
});
1
Andrew Luca