Dodaj nowe metody do kontrolera zasobów w Laravel


141

Chcę wiedzieć, czy jest możliwe dodanie nowych metod do kontrolera zasobów w Laravel i jak to się robi.

Wiem, że te metody są domyślne (indeksuj, twórz, przechowuj, edytuj, aktualizuj, niszcz). Teraz chcę dodać dodatkowe metody i trasy do tego samego kontrolera.

Czy to jest możliwe?

Odpowiedzi:


261

Po prostu dodaj osobno trasę do tej metody, zanim zarejestrujesz zasób:

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

7
Zwróć uwagę, że nowe metody muszą być wyższe niż w ::resourceprzeciwnym razie zostanie wyświetlony komunikat o błędzie „Brak wyników zapytania dla modelu”.
— mpen

Jak przekazałbyś parametr taki jak {id}? Obecnie zakodowałem swoją niestandardową metodę inline w route.php (tak jak w przykładzie laravel.com/docs/5.1/routing#route-parameters ). Idealnie chciałbym przekazać parametr do uruchomienia w FooController.
— ATutorMe

1
Znaleziono problem - nie ma go w składni trasy. W rzeczywistości było to w jakimś niestandardowym oprogramowaniu pośrednim, którego używam! Route :: get ('foo / {id} / bar', 'FooController @ bar'); przekaże id do metody bar ($ id). Dzięki!
— ATutorMe

Czy ktoś może wyjaśnić, dlaczego trasa niestandardowa powinna przebiegać powyżej trasy zasobów? Zrobiłem kilka testów i wydaje mi się, że nie ma różnicy między umieszczaniem powyżej lub poniżej ...
— Ricardo Vigatti

3
@RicardoVigatti - Zasób rejestruje tę drogę: Route::get('foo/{id}', ...). To pochłania wszystkie trasy zaczynające się od fooi mające jeden dodatkowy segment, w tym foo/bar.
— Joseph Silber

32

Właśnie to zrobiłem, aby dodać metodę GET "usuń".

Po utworzeniu plików wystarczy dodać

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

do „dostawców” w twojej aplikacji / config.php

Edytuj alias trasy w tym samym pliku:

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

zmiana na

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

Upewnij się, że te pliki są ładowane automatycznie, muszą znajdować się w jakimś katalogu, który masz w swoim pliku composer.json (sekcja "autoload").

Następnie wystarczy:

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

A to (spójrz na ostatnią linię) jest wynikiem, jeśli uruchomisz php artisan routes:

lista tras To są moje pliki źródłowe:

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
Czy możesz podać to samo dla Laravel 5 i nowszych? Próbowałem to odtworzyć ... Ale nie mogę znaleźć miejsca, w którym rejestrują Accessor „trasy” w kontenerze.
— TipuZaynSultan

dlaczego plik ma rozszerzenie .pas?
— Thiago Dias

22

Tak, to możliwe ...

W moim przypadku dodaję metodę: dane do obsługi żądania /data.json w metodzie HTTP POST.

To co zrobiłem.

Najpierw rozszerzamy Illuminate \ Routing \ ResourceRegistrar, aby dodać nowe dane metody

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

Następnie utwórz nowy ServiceProvider lub zamiast tego użyj AppServiceProvider .

Podczas rozruchu metody dodaj ten kod:

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

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

następnie :

dodaj do swojej trasy:

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

Sprawdź przez php artisan route:list A znajdziesz nową metodę 'dane'


Twoje rozwiązanie działa dla mnie… Czy możesz mi powiedzieć, czy po kilku miesiącach używania tego kodu odkryłeś jakiś problem?
— Ricardo Vigatti

Dzięki @RicardoVigatti. Używałem tego od wersji laravel 5.2, a teraz używam tego w moim ostatnim projekcie z L5.3 i nie mam z tym problemu. Daj mi znać, jeśli taki masz, może mogę ci pomóc ..
— Mokhamad Rofi'udin

nieźle, wdrażam to w moim projekcie 5.0. Rozwiązanie wydaje się bardzo spójne, ale jeśli wystąpi jakikolwiek problem, nastąpi to po kilku tygodniach.
— Ricardo Vigatti

@ MokhamadRofi'udin Zaimplementowałem Twoje rozwiązanie, nowa trasa jest dodawana do listy tras, ale wygląda na to, że nie dodano odpowiedniej metody. Czy coś mi brakuje?
— Siavosh

@Siavosh po prostu napisz swoją metodę w kontrolerze, tj. Dodaję metodę data (): `public function data (Request $ request) {}`
— Mokhamad Rofi'udin

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

Spróbuj. Dodaj dodatkowe metody, takie jak getData () itp., Itp. Pomogło mi to zachować porządek w route.php


Tak, to działa. Laravel 5.1 Documentation nie wspomniał, że Route :: resource i Route :: controller mogą być używane razem, a raczej wspomnieli o uzupełnianiu kontrolerów zasobów. Więc to jest zdezorientowane. Ale twoje odpowiedzi udowodniły, że można ich używać razem
— Amir

Przepraszam Hassan jamal, ta dwójka nie pracuje razem. Więc teraz, jak mogę ustawić niestandardową metodę wpisu w kontrolerze, jeśli używam tylko Route :: resource
— Amir

3

Korzystanie z Laravel> 5 Znajdź plik web.php w folderze tras i dodaj swoje metody

Możesz użyć route :: resource do kierowania wszystkich tych metod do indeksowania, pokazywania, przechowywania, aktualizowania, niszczenia w kontrolerze w jednej linii

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

1

Po prostu dodaj nową metodę i trasę do tej metody.

W kontrolerze:

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

Oraz w Twoich trasach internetowych

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

Upewnij się tylko, że metoda w kontrolerze jest publiczna.


-1

To też działa całkiem nieźle. Nie ma potrzeby dodawania kolejnych tras, wystarczy użyć metody show kontrolera zasobów w następujący sposób:

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

Używam wartości domyślnej, aby wrzucić niestandardową stronę błędu.


2
To jak prawdziwy zapach kodu. Nie chciałbym, aby moje kontrolery obsługiwały wiele akcji.
— RonnyKnoxville
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.