Tambahkan metode baru ke pengontrol sumber daya di Laravel

141

Saya ingin tahu apakah mungkin untuk menambahkan metode baru ke pengontrol sumber daya di Laravel dan bagaimana Anda melakukannya.

Saya tahu bahwa metode ini adalah default (indeks, buat, simpan, edit, perbarui, musnahkan). Sekarang saya ingin menambahkan metode dan rute tambahan ke pengontrol yang sama.

Apakah itu mungkin?

pengguna2403824
sumber

Jawaban:

261

Cukup tambahkan rute ke metode itu secara terpisah, sebelum Anda mendaftarkan sumber daya:

Route::get('foo/bar', 'FooController@bar');
Route::resource('foo', 'FooController');
Joseph Silber
sumber
7
Perhatikan bahwa metode baru Anda harus pergi atas yang ::resourcejika Anda mendapatkan pesan kesalahan, "Tidak ada hasil query untuk model".
mpen
Bagaimana Anda akan melewati parameter seperti {id}? Saat ini saya telah memberi kode metode kustom saya inline di routes.php (seperti contoh di sini laravel.com/docs/5.1/routing#route-parameters ). Idealnya saya ingin melewatkan parameter untuk dijalankan di FooController.
ATutorMe
1
Menemukan masalah - tidak ada dalam sintaks Route. Sebenarnya dalam beberapa Middleware kustom yang saya gunakan! Rute :: get ('foo / {id} / bar', 'FooController @ bar'); akan meneruskan metode id to bar ($ id). Terima kasih!
ATutorMe
Adakah yang bisa menjelaskan mengapa rute khusus harus di atas rute sumber daya ??? Saya telah melakukan beberapa tes dan tampaknya tidak memiliki perbedaan antara menempatkan di atas atau di bawah ...
Ricardo Vigatti
3
@RicardoVigatti - sumber daya register rute ini: Route::get('foo/{id}', ...). Ini menelan semua rute yang dimulai dengan foodan memiliki satu segmen tambahan, termasuk foo/bar.
Joseph Silber
32

Saya baru saja melakukannya, untuk menambahkan metode "hapus" DAPATKAN.

Setelah membuat file, Anda hanya perlu menambahkan

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

ke 'penyedia' di aplikasi / config.php Anda

Edit alias Rute dalam file yang sama ini:

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

mengubahnya menjadi

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

Dan pastikan file-file itu sedang dimuat secara otomatis, mereka harus ada di beberapa direktori yang Anda miliki di composer.json Anda (bagian "pengisian otomatis").

Maka Anda hanya perlu:

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

Dan ini (lihat baris terakhir) adalah hasilnya jika Anda menjalankan php artisan routes:

daftar rute Itu adalah file sumber saya:

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

}
Antonio Carlos Ribeiro
sumber
3
Bisakah Anda memberikan hal yang sama untuk Laravel 5 dan Di Atas? Saya telah mencoba untuk mereproduksi ini ... Tapi sepertinya saya tidak dapat menemukan di mana mereka mendaftarkan Accessor 'rute' dalam wadah.
TipuZaynSultan
mengapa file tersebut memiliki ekstensi .pas?
Thiago Dias
22

Ya, itu mungkin ..

Dalam kasus saya, saya menambahkan metode: data untuk menangani permintaan untuk / data.json dalam metode HTTP POST.

Ini yang saya lakukan.

Pertama kita memperluas Illuminate \ Routing \ ResourceRegistrar untuk menambahkan data metode baru

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

Setelah itu, buat ServiceProvider baru Anda atau gunakan AppServiceProvider sebagai gantinya.

Dalam metode boot , tambahkan kode ini:

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

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

kemudian :

tambahkan ke rute Anda:

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

Periksa oleh php artisan route:list Dan Anda akan menemukan 'data' metode baru

Mokhamad Rofi'udin
sumber
Solusi Anda berfungsi untuk saya .. Bisakah Anda memberi tahu saya jika Anda menemukan masalah setelah beberapa bulan menggunakan kode ini?
Ricardo Vigatti
Terima kasih @RicardoVigatti. Saya menggunakan ini sejak laravel 5.2 dan sekarang saya menggunakan ini dalam proyek terakhir saya dengan L5.3 dan tidak memiliki masalah dengannya. Biarkan saya tahu jika Anda memilikinya, mungkin saya dapat membantu Anda ..
Mokhamad Rofi'udin
bagus, saya menerapkan ini dalam proyek 5.0 saya. Solusinya tampaknya sangat konsisten, tetapi, jika ada masalah, itu akan terjadi setelah beberapa minggu.
Ricardo Vigatti
@ MokhamadRofi'udin Saya telah mengimplementasikan solusi Anda, rute baru ditambahkan ke daftar rute tetapi tampaknya metode yang sesuai tidak ditambahkan. Apakah saya melewatkan sesuatu?
Siavosh
@Siavosh hanya menulis metode Anda di controller yaitu saya menambahkan data metode (): `data fungsi publik (Permintaan $ permintaan) {}`
Mokhamad Rofi'udin
13
Route::resource('foo', 'FooController');
Route::controller('foo', 'FooController');

Cobalah ini. Tolong Anda metode tambahan seperti getData () dll. Ini berfungsi agar saya menjaga route.php tetap bersih

Hassan Jamal
sumber
Yas ini berhasil. Laravel 5.1 Dokumentasi tidak menyebutkan bahwa Route :: resource dan Route :: controller dapat digunakan bersama daripada yang mereka sebutkan tentang Tambahan Pengontrol Sumber Daya. Jadi ini bingung. Tetapi ans Anda membuktikan bahwa ini dapat digunakan bersama
Amir
Saya minta maaf Hassan jamal, keduanya tidak bekerja sama. Jadi sekarang bagaimana saya bisa mengatur metode pos kustom di controller jika saya hanya menggunakan Route :: resource
Amir
3

Menggunakan Laravel> 5 Temukan file web.php di folder rute, tambahkan metode Anda

Anda dapat menggunakan route :: resource untuk merutekan semua metode ini dengan indeks, menunjukkan, menyimpan, memperbarui, menghancurkan di controller Anda dalam satu baris

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

Cukup tambahkan metode baru dan rute ke metode itu.

Di controller Anda:

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

Dan di rute web Anda

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

Pastikan metode di pengontrol bersifat publik.

Patrick Lumenus
sumber
-1

Ini bekerja sangat bagus juga. Tidak perlu menambahkan rute lagi cukup gunakan metode show dari pengontrol sumber daya seperti ini:

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

Saya menggunakan default untuk membuang halaman kesalahan khusus.

mdamia
sumber
2
Ini terasa seperti bau kode asli. Saya tidak ingin pengendali saya menangani banyak tindakan.
RonnyKnoxville