Добавить новые методы в контроллер ресурсов в Laravel

112

Я хочу знать, можно ли добавлять новые методы в контроллер ресурсов в Laravel и как вы это делаете.

Я знаю, что эти методы являются стандартными (индекс, создавать, сохранять, редактировать, обновлять, уничтожать). Теперь я хочу добавить дополнительные методы и маршруты к одному и тому же контроллеру.

Возможно ли это?

Теги:

8 ответов

208
Лучший ответ

Просто добавьте маршрут к этому методу отдельно, до, зарегистрировав ресурс:

Route::get('foo/bar', 'FooController@bar');
Route::resource('foo', 'FooController');
  • 0
    спасибо: D. Это работает потрясающе!
  • 5
    Обратите внимание, что ваши новые методы должны идти над ::resource противном случае вы получите сообщение об ошибке «Нет результатов запроса для модели».
Показать ещё 10 комментариев
29

Я просто сделал это, чтобы добавить метод GET "удалить".

После создания файлов вам просто нужно добавить

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

для "поставщиков" в вашем приложении /config.php

Отредактируйте псевдоним Route в этом же файле:

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

изменив его на

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

И убедитесь, что эти файлы загружены автоматически, они должны находиться в каком-либо каталоге, который у вас есть в разделе composer.json(раздел "Автозагрузка" ).

Тогда вам просто нужно:

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

И это (посмотрите на последнюю строку) - результат, если вы запустите php artisan routes:

Изображение 3552 Это мои исходные файлы:

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

}
  • 1
    Можете ли вы предоставить то же самое для Laravel 5 и выше? Я пытался воспроизвести это ... Но я не могу найти, где они регистрируют аксессор маршрута в контейнере.
15

Да, возможно...

В моем случае я добавляю метод: data для обработки запроса для /data.json в методе HTTP POST.

Это то, что я сделал.

Сначала мы расширяем Illuminate\Routing\ResourceRegistrar, чтобы добавить новый метод data​​strong >

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

После этого создайте новый ServiceProvider или используйте AppServiceProvider.

В методе boot добавьте этот код:

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

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

тогда:

добавить к вашему маршруту:

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

Проверить php artisan route:list И вы найдете новый метод 'data'

  • 0
    Ваше решение работает для меня .. Можете ли вы сказать мне, если вы обнаружили какую-либо проблему после нескольких месяцев использования этого кода?
  • 0
    Спасибо @RicardoVigatti. Я использовал это начиная с laravel 5.2, и теперь я использую это в своем недавнем проекте с L5.3 и не имею проблем с ним. Дайте мне знать, если у вас есть, может быть, я могу помочь вам ..
Показать ещё 4 комментария
13
Route::resource('foo', 'FooController');
Route::controller('foo', 'FooController');

Попробуй попробовать. Попробуй дополнительные методы, такие как getData() и т.д. и т.д. Это помогло мне сохранить route.php clean

  • 0
    Яс это работает. В документации Laravel 5.1 не упоминалось, что Route :: resource и Route :: controller могут использоваться вместе, а упоминалось о дополнении контроллеров ресурсов. Так что это запутано. Но ваш ответ доказал, что они могут быть использованы вместе
  • 0
    Извините, Хасан Джамал, эти двое не работают вместе. Так что теперь, как я могу установить пользовательский метод post в контроллере, если я использую только Route :: resource
Показать ещё 1 комментарий
1

Использование Laravel> 5 Найдите файл web.php в папке маршрутов и добавьте ваши методы

Вы можете использовать route :: resource для маршрутизации всех этих методов index, show, store, update, destroy в вашем контроллере в одну строку

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

Это тоже очень хорошо. Нет необходимости добавлять больше маршрутов, просто используйте метод show контроллера ресурсов следующим образом:

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(){}

Я использую значение по умолчанию, чтобы отправить страницу пользовательской ошибки.

0

просто дополнение для Джозефа Силбера ответ выше.

вот источник:

https://laravel.com/docs/5.7/controllers#restful-supplementing-resource-controllers

0

Просто добавьте новый метод и маршрут к этому методу.

В вашем контроллере:

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

И в ваших веб-маршрутах

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

Просто убедитесь, что метод в контроллере публичный.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню