149 votes

Ajouter de nouvelles méthodes à un contrôleur de ressources en Laravel

Je veux savoir s'il est possible d'ajouter de nouvelles méthodes à un contrôleur de ressources dans Laravel et comment vous le faites.

Je sais que ces méthodes sont les méthodes par défaut (index, créer, stocker, modifier, mettre à jour, détruire). Maintenant, je veux ajouter des méthodes et des routes supplémentaires au même contrôleur.

Est-ce possible ?

286voto

Joseph Silber Points 69582

Il suffit d'ajouter une route à cette méthode séparément, avant vous enregistrez la ressource :

Route::get('foo/bar', 'FooController@bar');
Route::resource('foo', 'FooController');

8 votes

Notez que vos nouvelles méthodes doivent aller au-dessus de le site ::resource sinon vous obtenez un message d'erreur, "No query results for model".

0 votes

Comment passer un paramètre comme {id} ? Actuellement, j'ai codé ma méthode personnalisée en ligne dans routes.php (comme l'exemple ici laravel.com/docs/5.1/routing#route-parameters ). Idéalement, je voudrais passer le paramètre à exécuter dans FooController.

1 votes

J'ai trouvé le problème - ce n'était pas dans la syntaxe de la route. Il était en fait dans un Middleware personnalisé que j'utilise ! Route::get('foo/{id}/bar', 'FooController@bar') ; passera l'id à la méthode bar($id). Merci !

33voto

Je viens de le faire, pour ajouter une méthode GET "delete".

Après avoir créé vos fichiers, il vous suffit d'ajouter

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

à "providers" dans votre app/config.php

Modifiez l'alias Route dans ce même fichier :

'Route'           => 'Illuminate\Support\Facades\Route',

en le changeant en

'Route'           => 'AntonioRibeiro\Facades\ExtendedRouteFacade',

Et assurez-vous que ces fichiers sont chargés automatiquement, ils doivent se trouver dans un répertoire que vous avez indiqué dans votre composer.json (section "autoload").

Alors, il vous suffit de le faire :

Route::resource('users', 'UsersController');

Et ceci (regardez la dernière ligne) est le résultat si vous exécutez php artisan routes :

routes list Ce sont mes fichiers sources :

ExtendedRouteFacade.pas

<?php namespace AntonioRibeiro\Facades;

use Illuminate\Support\Facades\Facade as IlluminateFacade;

class ExtendedRouteFacade extends IlluminateFacade {

    /**
     * Determine if the current route matches a given name.
     *
     * @param  string  $name
     * @return bool
     */
    public static function is($name)
    {
        return static::$app['router']->currentRouteNamed($name);
    }

    /**
     * Determine if the current route uses a given controller action.
     *
     * @param  string  $action
     * @return bool
     */
    public static function uses($action)
    {
        return static::$app['router']->currentRouteUses($action);
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'router'; }

}

ExtendedRouter.pas

<?php namespace AntonioRibeiro\Routing;

class ExtendedRouter extends \Illuminate\Routing\Router {

    protected $resourceDefaults = array('index', 'create', 'store', 'show', 'edit', 'update', 'destroy', 'delete');

    /**
     * Add the show method for a resourceful route.
     *
     * @param  string  $name
     * @param  string  $base
     * @param  string  $controller
     * @return void
     */
    protected function addResourceDelete($name, $base, $controller)
    {
        $uri = $this->getResourceUri($name).'/{'.$base.'}/destroy';

        return $this->get($uri, $this->getResourceAction($name, $controller, 'delete'));
    }

}

ExtendedRouteServiceProvider.pas

<?php namespace AntonioRibeiro\Routing;

use Illuminate\Support\ServiceProvider;

class ExtendedRouterServiceProvider extends ServiceProvider {

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = true;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app['router'] = $this->app->share(function() { return new ExtendedRouter($this->app); });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return array('router');
    }

}

3 votes

Pouvez-vous fournir la même chose pour Laravel 5 et plus ? J'ai essayé de reproduire ce problème... Mais je n'arrive pas à trouver où ils enregistrent l'accesseur 'route' dans le conteneur.

1 votes

Pourquoi le fichier a l'extension .pas ?

0 votes

C'est logique mais la partie fournisseur ne semble pas fonctionner avec Laravel 8.0.

29voto

Oui, c'est possible..

Dans mon cas, j'ajoute la méthode : data pour traiter la demande de /data.json en méthode HTTP POST.

C'est ce que j'ai fait.

D'abord, nous étendons Illuminez \Routing\ResourceRegistrar pour ajouter une nouvelle méthode données

<?php

namespace App\MyCustom\Routing;

use Illuminate\Routing\ResourceRegistrar as OriginalRegistrar;

class ResourceRegistrar extends OriginalRegistrar
{
    // add data to the array
    /**
     * The default actions for a resourceful controller.
     *
     * @var array
     */
    protected $resourceDefaults = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy', 'data'];

    /**
     * Add the data method for a resourceful route.
     *
     * @param  string  $name
     * @param  string  $base
     * @param  string  $controller
     * @param  array   $options
     * @return \Illuminate\Routing\Route
     */
    protected function addResourceData($name, $base, $controller, $options)
    {
        $uri = $this->getResourceUri($name).'/data.json';

        $action = $this->getResourceAction($name, $controller, 'data', $options);

        return $this->router->post($uri, $action);
    }
}

Après cela, faites votre nouveau ServiceProvider ou utiliser AppServiceProvider à la place.

En méthode démarrer , ajoutez ce code :

    public function boot()
    {
        $registrar = new \App\MyCustom\Routing\ResourceRegistrar($this->app['router']);

        $this->app->bind('Illuminate\Routing\ResourceRegistrar', function () use ($registrar) {
            return $registrar;
        });
    }

alors :

ajouter à votre itinéraire :

Route::resource('test', 'TestController');

Vérifier par php artisan route:list Et vous trouverez une nouvelle méthode données

14voto

Hassan Jamal Points 76
Route::resource('foo', 'FooController');
Route::controller('foo', 'FooController');

Essayez ceci. Mettez des méthodes supplémentaires comme getData() etc etc . Cela a fonctionné pour moi pour garder route.php propre.

0 votes

Yas this works . La documentation de Laravel 5.1 ne mentionne pas que Route::resource et Route::controller peuvent être utilisés ensemble, mais plutôt qu'il s'agit de Supplementing Resource Controllers. C'est donc une confusion. Mais votre réponse prouve que ces deux éléments peuvent être utilisés ensemble.

0 votes

Je suis désolé Hassan jamal, ces deux-là ne travaillent pas ensemble. Maintenant, comment puis-je définir une méthode de post personnalisée dans un contrôleur si j'utilise uniquement Route::resource.

3voto

Mazen Embaby Points 435

Utilisation de Laravel >5 Trouvez le fichier web.php dans le dossier routes et ajoutez vos méthodes.

Vous pouvez utiliser route::resource pour acheminer toutes ces méthodes (index, show, store, update, destroy) dans votre contrôleur en une seule ligne.

Route::get('foo/bar', 'NameController@bar');
Route::resource('foo', 'NameController');

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X