Thêm phương thức mới vào bộ điều khiển tài nguyên trong Laravel


141

Tôi muốn biết liệu có thể thêm các phương thức mới vào bộ điều khiển tài nguyên trong Laravel hay không và cách bạn thực hiện nó.

Tôi biết rằng các phương thức này là mặc định (lập chỉ mục, tạo, lưu trữ, chỉnh sửa, cập nhật, hủy). Bây giờ tôi muốn thêm các phương thức và tuyến bổ sung vào cùng một bộ điều khiển.

Điều đó có thể không?

Câu trả lời:


261

Chỉ cần thêm một tuyến đường cho phương thức đó một cách riêng biệt, trước khi bạn đăng ký tài nguyên:

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

7
Lưu ý rằng phương pháp mới của bạn phải đi trên những ::resourcecách khác bạn nhận được một thông báo lỗi: "Không kết quả truy vấn cho mô hình".
mở

Làm thế nào bạn sẽ vượt qua một tham số như {id}? Hiện tại tôi đã mã hóa phương thức tùy chỉnh nội tuyến của mình trong Rout.php (như ví dụ ở đây laravel.com/docs/5.1/routing#route-parameter ). Lý tưởng nhất là tôi muốn truyền tham số để chạy trong FooControll.
ATutorMe

1
Đã tìm thấy sự cố - không nằm trong cú pháp Tuyến đường. Đã thực sự trong một số Middleware tùy chỉnh mà tôi đang sử dụng! Tuyến đường :: get ('foo / {id} / bar', 'FooControll @ bar'); sẽ chuyển id sang phương thức bar ($ id). Cảm ơn!
ATutorMe

Ai đó có thể giải thích tại sao tuyến tùy chỉnh nên đi trên tuyến tài nguyên không ??? Tôi đã thực hiện một số thử nghiệm và dường như không có sự khác biệt nào giữa việc đặt bên trên hoặc bên dưới ...
Ricardo Vigatti

3
@RicardoVigatti - Tài nguyên đăng ký tuyến này : Route::get('foo/{id}', ...). Điều này nuốt tất cả các tuyến bắt đầu bằng foovà có thêm một phân đoạn, bao gồm foo/bar.
Joseph Silber

32

Tôi chỉ làm điều đó, để thêm một phương thức "xóa".

Sau khi tạo tập tin của bạn, bạn chỉ cần thêm

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

đến 'nhà cung cấp' trong ứng dụng / config.php của bạn

Chỉnh sửa bí danh Tuyến đường trong cùng tệp này:

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

đổi nó thành

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

Và đảm bảo rằng các tệp đó đang được tự động tải, chúng phải nằm trong một số thư mục mà bạn có trong composer.json (phần "tự động tải").

Sau đó, bạn chỉ cần:

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

Và điều này (nhìn vào dòng cuối cùng) là kết quả nếu bạn chạy php artisan routes:

danh sách tuyến đường Đó là những tập tin nguồn của tôi:

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
Bạn có thể vui lòng cung cấp tương tự cho Laravel 5 trở lên không? Tôi đã cố gắng tái tạo điều này ... Nhưng dường như tôi không thể tìm thấy nơi họ đang đăng ký Accessor của 'tuyến đường' trong container.
TipuZaynSultan

Tại sao tập tin có phần mở rộng .pas?
Thiago Dias

22

Vâng, nó có thể ..

Trong trường hợp của tôi, tôi thêm phương thức: dữ liệu để xử lý yêu cầu cho /data.json trong phương thức POST HTTP.

Đây là những gì tôi đã làm.

Trước tiên, chúng tôi mở rộng Illuminate \ Routing \ ResourceRegistrar để thêm dữ liệu phương thức mới

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

Sau đó, tạo ServiceProvider mới của bạn hoặc sử dụng AppServiceProvider thay thế.

Trong phương thức khởi động , thêm mã này:

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

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

sau đó :

thêm vào tuyến đường của bạn:

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

Kiểm tra bởi php artisan route:list Và bạn sẽ tìm thấy phương pháp mới 'dữ liệu'


Giải pháp của bạn hiệu quả với tôi .. Bạn có thể cho tôi biết nếu bạn phát hiện ra bất kỳ vấn đề nào sau vài tháng sử dụng mã này không?
Ricardo Vigatti

Cảm ơn @RicardoVigatti. Tôi đã sử dụng cái này kể từ laravel 5.2 và bây giờ tôi sử dụng nó trong dự án gần đây của tôi với L5.3 và không có vấn đề gì với nó. Hãy cho tôi biết nếu bạn có một người, tôi có thể giúp bạn không ..
Mokhamad Rofi'udin

thật tuyệt, tôi đang thực hiện điều này trong dự án 5.0 của mình. Giải pháp có vẻ rất nhất quán, nhưng, nếu bất kỳ vấn đề nào được đưa ra, nó sẽ có sau một vài tuần.
Ricardo Vigatti

@ MokhamadRofi'udin Tôi đã triển khai giải pháp của mình, tuyến mới được thêm vào danh sách tuyến nhưng có vẻ như phương pháp tương ứng không được thêm vào. Tui bỏ lỡ điều gì vậy ?
Siavosh

@Siavosh chỉ cần viết phương thức của bạn vào bộ điều khiển tức là tôi thêm dữ liệu phương thức (): `dữ liệu hàm công khai (Request $ request) {}`
Mokhamad Rofi'udin

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

Hãy dùng thử. Hãy thử cho bạn các phương thức bổ sung như getData (), v.v. .. Điều này làm việc với tôi để giữ sạch lộ.php.


Yas này hoạt động. Tài liệu của Laravel 5.1 không đề cập rằng bộ điều khiển Route :: resource và Route :: có thể được sử dụng cùng nhau thay vì họ đã đề cập về Bổ sung Bộ điều khiển Tài nguyên. Vì vậy, điều này là nhầm lẫn. Nhưng ans của bạn đã chứng minh rằng những thứ này có thể được sử dụng cùng nhau
Amir

Tôi xin lỗi Hassan Jamal, hai người này không làm việc cùng nhau. Vậy bây giờ làm thế nào tôi có thể thiết lập một phương thức bài tùy chỉnh trong bộ điều khiển nếu tôi chỉ sử dụng Route :: resource
Amir

3

Sử dụng Laravel> 5 Tìm tệp web.php trong thư mục tuyến đường thêm phương thức của bạn

Bạn có thể sử dụng route :: resource để định tuyến tất cả các phương thức này lập chỉ mục, hiển thị, lưu trữ, cập nhật, hủy trong bộ điều khiển của bạn trong một dòng

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

1

Chỉ cần thêm một phương thức mới và một tuyến đường cho phương thức đó.

Trong bộ điều khiển của bạn:

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

Và trong các tuyến web của bạn

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

Chỉ cần chắc chắn rằng phương thức trong bộ điều khiển là công khai.


-1

Điều này cũng hoạt động khá tốt. Không cần thêm nhiều tuyến chỉ cần sử dụng phương thức hiển thị của bộ điều khiển tài nguyên như thế này:

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

Tôi sử dụng mặc định để ném trang lỗi tùy chỉnh.


2
Cảm giác này giống như một mùi mã thực sự. Tôi không muốn bộ điều khiển của tôi xử lý nhiều hành động.
RonnyKnoxville
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.