Add new methods to a resource controller in Laravel

Laravel

Laravel Problem Overview


I want to know if it is possible to add new methods to a resource controller in Laravel and how you do it.

I know that these methods are the default (index, create, store, edit, update, destroy). Now I want to add additional methods and routes to the same controller.

Is that possible?

Laravel Solutions


Solution 1 - Laravel

Just add a route to that method separately, before you register the resource:

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

Solution 2 - Laravel

Yeah, It's possible..

In my case I add method : data to handle request for /data.json in HTTP POST method.

This what I did.

First we extends Illuminate\Routing\ResourceRegistrar to add new method data

<?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);
    }
}

After that, make your new ServiceProvider or use AppServiceProvider instead.

In method boot, add this code :

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

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

then :

add to your route :

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

Check by php artisan route:list And you will find new method 'data'

Solution 3 - Laravel

I just did that, to add a GET "delete" method.

After creating your files, you just need to add

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

to 'providers' in your app/config.php

Edit the Route alias in this same file:

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

changing it to

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

And make sure those files are being autoloaded, they must be in some directory that you have in your composer.json ("autoload" section).

Then you just need to:

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

And this (look at the last line) is the result if you run php artisan routes:

routes list Those are my source files:

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');
    }

}

Solution 4 - Laravel

Route::resource('foo', 'FooController');
Route::controller('foo', 'FooController');

Give this a try .Put you extra methods like getData() etc etc .. This worked for me to keep route.php clean

Solution 5 - Laravel

Using Laravel >5 Find the web.php file in routes folder add your methods

You can use route::resource to route all these methods index, show, store, update, destroy in your controller in one line

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

Solution 6 - Laravel

Just add a new method and a route to that method.

In your controller:

public function foo($bar=“default)
{
      //do stuff
}

And in your web routes

Route::get(“foo/{$bar}”, “MyController@foo”);

Just be sure the method in the controller is public.

Solution 7 - Laravel

I solve by

Create a custom router file that extends the BaseRouter

// src/app/Custom/Router.php


<?php

namespace App\Custom;

use Illuminate\Routing\Router as BaseRouter;
use Illuminate\Support\Str;

class Router extends BaseRouter
{
    public function customResource($name, $controller, array $options = [])
    {
        $model = Str::singular($name); // this is optional, i need it for Route Model Binding

        $this
            ->get( // set the http methods
                $name .'/{' . $model . '}/audit',
                $controller . '@audit'
            )->name($name . '.audit');

        return $this->resource($name, $controller, $options);
    }
}

Then register at src/bootstrap/app.php

$app->singleton('router', function ($app) {
    return new \App\Custom\Router($app['events'], $app);
});

And use it on /routes/web.php

Route::customResource(
    'entries',
    'EntryController'
);

Solution 8 - Laravel

Previously I defined my route as:

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

It gave the error: >route foo.bar is not defined

And then after some Googling I added name

Route::get('foo/bar', 'FooController@bar')->name('foo.bar');

And it worked fine.

Solution 9 - Laravel

This works pretty good too. No need to add more routes just use show method of the resource controller like this :

public function show($name){
 
 switch ($name){
   case 'foo':
    $this -> foo();
    break;
   case 'bar':
    $this ->bar();
    break; 
  defautlt:
    abort(404,'bad request');
    break;
 }

}
public function foo(){}
publcc function bar(){}

I use the default to throw custom error page.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2403824View Question on Stackoverflow
Solution 1 - LaravelJoseph SilberView Answer on Stackoverflow
Solution 2 - LaravelMokhamad Rofi'udinView Answer on Stackoverflow
Solution 3 - LaravelAntonio Carlos RibeiroView Answer on Stackoverflow
Solution 4 - LaravelHassan JamalView Answer on Stackoverflow
Solution 5 - LaravelMazen EmbabyView Answer on Stackoverflow
Solution 6 - LaravelPatrick LumenusView Answer on Stackoverflow
Solution 7 - LaravelDev LimView Answer on Stackoverflow
Solution 8 - LaravelPradeep ParmarView Answer on Stackoverflow
Solution 9 - LaravelmdamiaView Answer on Stackoverflow