Додайте нові методи до контролера ресурсів у Laravel


141

Хочу знати, чи можна додати нові методи до контролера ресурсів у Laravel і як це зробити.

Я знаю, що ці методи є типовими (індексувати, створювати, зберігати, редагувати, оновлювати, знищувати). Тепер я хочу додати додаткові методи та маршрути до того ж контролера.

Це можливо?

Відповіді:


261

Просто додайте маршрут до цього методу окремо, перш ніж зареєструвати ресурс:

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

7
Зверніть увагу , що ваші нові методи повинні йти вище::resource в іншому випадку ви отримаєте повідомлення про помилку «Ні результати запиту для моделі».
квітня

Як би ви передали такий параметр, як {id}? Наразі я зашифрував свій власний метод inline у ​​route.php (як, наприклад, тут laravel.com/docs/5.1/routing#route-parameters ). В ідеалі я хотів би передати параметр для запуску у FooController.
ATutorMe

1
Знайшла проблему - не було в синтаксисі маршруту. Був насправді в якомусь спеціальному програмному забезпеченні, яке я використовую! Маршрут :: get ('foo / {id} / bar', 'FooController @ bar'); передасть метод id у бар ($ id). Дякую!
ATutorMe

Чи може хтось пояснити, чому користувацький маршрут повинен виходити вище маршруту ресурсу ??? Я зробив кілька тестів і, схоже, немає різниці між тим, як ставити вище або нижче ...
Рікардо Вігатті

3
@RicardoVigatti - Ресурс реєструє цей маршрут: Route::get('foo/{id}', ...). Це ковтає всі маршрути, починаючи з fooодного додаткового відрізка, включаючи, зокрема foo/bar.
Джозеф Сільбер

32

Я щойно це зробив, щоб додати метод GET "delete".

Створивши свої файли, вам просто потрібно додати

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

до "провайдерів" у вашому додатку / config.php

Редагуйте псевдонім маршруту в цьому самому файлі:

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

змінивши його на

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

І переконайтеся, що ці файли завантажуються автоматично, вони повинні знаходитися в деякому каталозі, який ви маєте у своєму composer.json (розділ "автозавантаження").

Тоді вам просто потрібно:

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

І це (подивіться останній рядок) - це результат, якщо ви запустите php artisan routes:

список маршрутів Це мої вихідні файли:

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
Чи можете ви надати те саме для Laravel 5 і вище? Я намагався відтворити це ... Але я, здається, не можу знайти, де вони реєструють Accessor 'route' в контейнер.
TipuZaynSultan

чому файл має розширення .pas?
Тіаго Діас

22

Так, це можливо ..

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

Це я і зробив.

Спочатку ми розширюємо Illuminate \ Routing \ ResourceRegistrar для додавання нових даних методу

<?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 .

У методі завантаження додайте цей код:

    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 І ви знайдете новий метод "Дані"


Ваше рішення працює для мене. Чи можете ви сказати мені, чи виявили ви якусь проблему через кілька місяців, використовуючи цей код?
Рікардо Вігатті

Дякую @RicardoVigatti Я використовував це з laravel 5.2, і тепер я використовую це в своєму недавньому проекті з L5.3 і не маю жодних проблем з ним. Дайте мені знати, якщо у вас є, можливо, я можу вам допомогти ..
Мокхамад Рофі'удін

приємно, я реалізую це у своєму проекті 5.0. Рішення здається дуже послідовним, але, якщо якесь питання виникне, воно буде через кілька тижнів.
Рікардо Вігатті

@ MokhamadRofi'udin Я реалізував ваше рішення, новий маршрут додано до списку маршрутів, але, схоже, відповідний метод не додано. Я щось пропускаю?
Сіавош

@Siavosh просто запишіть свій метод у контролер, тобто я додаю дані методу (): `дані загальнодоступних функцій (Запит $ запиту) {}`
Mokhamad Rofi'udin

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

Спробуйте це. Запропонуйте додаткові методи, такі як getData () тощо, тощо. Це працювало для мене, щоб зберегти route.php чистим


Ясь це працює. Документація Laravel 5.1 не згадувала, що Route :: resource та Route :: контролер можна використовувати разом, а вони згадували про доповнення контролерів ресурсів. Так це плутати. Але ваші анс довели, що їх можна використовувати разом
Амір

Мені шкода, Хассан Джамал, ці двоє не працюють разом. Отже, як я можу встановити користувальницький метод публікації у контролері, якщо я використовую лише Route :: resource
Amir

3

Використання Laravel> 5 Знайдіть файл web.php у папці маршрутів, додайте свої методи

Ви можете використовувати route :: ресурс для маршрутизації всіх цих методів індексувати, показувати, зберігати, оновлювати, знищувати у своєму контролері в одному рядку

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

1

Просто додайте новий метод і маршрут до цього методу.

У вашому контролері:

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

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

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

Просто переконайтесь, що метод у контролері є загальнодоступним.


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

Я використовую за замовчуванням, щоб перекинути користувацьку сторінку помилок.


2
Це відчувається як справжній запах коду. Я б не хотів, щоб мої контролери обробляли кілька дій.
RonnyKnoxville
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.