เพิ่มวิธีการใหม่ไปยังตัวควบคุมทรัพยากรใน Laravel


141

ฉันต้องการทราบว่าเป็นไปได้หรือไม่ที่จะเพิ่มวิธีการใหม่ในตัวควบคุมทรัพยากรใน Laravel และวิธีการที่คุณทำ

ฉันรู้ว่าวิธีการเหล่านี้เป็นค่าเริ่มต้น (ดัชนีสร้างจัดเก็บแก้ไขปรับปรุงทำลาย) ตอนนี้ฉันต้องการเพิ่มวิธีการและเส้นทางเพิ่มเติมไปยังตัวควบคุมเดียวกัน

เป็นไปได้ไหม

คำตอบ:


261

เพียงเพิ่มเส้นทางไปยังวิธีนั้นแยกจากกันก่อนที่คุณจะลงทะเบียนทรัพยากร:

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

7
โปรดทราบว่าวิธีการใหม่ของคุณต้องไปข้างต้น::resourceมิฉะนั้นคุณจะได้รับข้อความแสดงข้อผิดพลาด "ไม่มีผลการค้นหาสำหรับรูปแบบ"
mpen

คุณจะส่งผ่านพารามิเตอร์เช่น {id} อย่างไร ขณะนี้ฉันได้รหัสวิธีการกำหนดเองของฉันอินไลน์ใน routes.php (เหมือนตัวอย่างที่นี่ laravel.com/docs/5.1/routing#route-parameters ) โดยหลักการแล้วฉันต้องการส่งพารามิเตอร์เพื่อให้ทำงานใน FooController
ATutorMe

1
พบปัญหา - ไม่ได้อยู่ในไวยากรณ์เส้นทาง เป็นจริงใน Middleware ที่กำหนดเองที่ฉันใช้อยู่! เส้นทาง :: get ('foo / {id} / bar', 'FooController @ bar'); จะส่งผ่านรหัสไปยังแถบ ($ id) วิธี ขอบคุณ!
ATutorMe

มีคนอธิบายได้ไหมว่าเหตุใดเราควรกำหนดเส้นทางเองเหนือเส้นทางทรัพยากร ฉันได้ทำการทดสอบบางอย่างแล้วและดูเหมือนจะไม่มีความแตกต่างระหว่างการวางสูงหรือต่ำกว่า ...
Ricardo Vigatti

3
@RicardoVigatti - Route::get('foo/{id}', ...)ทรัพยากรลงทะเบียนเส้นทางนี้: นี้กลืนทุกเส้นทางเริ่มต้นด้วยและมีหนึ่งส่วนเพิ่มเติมรวมทั้งfoo foo/bar
Joseph Silber

32

ฉันเพิ่งทำเช่นนั้นเพื่อเพิ่มวิธีการ "ลบ" GET

หลังจากสร้างไฟล์ของคุณคุณเพียงแค่ต้องเพิ่ม

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

เป็น 'ผู้ให้บริการ' ในแอป / config.php ของคุณ

แก้ไขเส้นทางนามแฝงในไฟล์เดียวกันนี้:

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

เปลี่ยนเป็น

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

และตรวจสอบให้แน่ใจว่าไฟล์เหล่านั้นถูกโหลดอัตโนมัติต้องอยู่ในไดเรกทอรีที่คุณมีใน composer.json (ส่วน "autoload")

จากนั้นคุณเพียงแค่ต้อง:

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 ในภาชนะ
TipuZaynSultan

ทำไมไฟล์ถึงมีนามสกุล. pas
Thiago Dias

22

ใช่มันเป็นไปได้ ..

ในกรณีของฉันฉันเพิ่มวิธีการ: ข้อมูลเพื่อจัดการคำขอสำหรับ /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 และคุณจะพบวิธีการใหม่'ข้อมูล'


วิธีแก้ปัญหาของคุณใช้ได้กับฉัน .. คุณช่วยบอกฉันได้ไหมถ้าคุณค้นพบปัญหาหลังจากใช้รหัสนี้มาหลายเดือน?
Ricardo Vigatti

ขอบคุณ @RicardoVigatti ฉันใช้สิ่งนี้ตั้งแต่ laravel 5.2 และตอนนี้ฉันใช้สิ่งนี้ในโครงการล่าสุดของฉันกับ L5.3 และไม่มีปัญหากับมัน แจ้งให้เราทราบหากคุณมีอาจเป็นฉันสามารถช่วยคุณ ..
Mokhamad Rofi'udin

ดีฉันกำลังใช้สิ่งนี้ในโครงการ 5.0 ของฉัน การแก้ปัญหาดูเหมือนจะสอดคล้องกันมาก แต่ถ้ามีปัญหาใด ๆ เกิดขึ้นจะผ่านไปหลายสัปดาห์
Ricardo Vigatti

@ MokhamadRofi'udin ฉันได้ใช้งานโซลูชันของคุณแล้วเส้นทางใหม่จะถูกเพิ่มในรายการเส้นทาง แต่ดูเหมือนว่าจะไม่เพิ่มวิธีการที่สอดคล้องกัน ฉันพลาดอะไรไปรึเปล่า ?
Siavosh

@Siavosh เพียงแค่เขียนวิธีการของคุณในการควบคุมคือฉันเพิ่มข้อมูลวิธีการ (): `ข้อมูลฟังก์ชั่นสาธารณะ (ขอ $ คำขอ) {}`
Mokhamad Rofi'udin

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

ลองใช้วิธีนี้ให้คุณเพิ่มวิธีพิเศษเช่น getData () ฯลฯ ฯลฯ มันใช้งานได้ดีสำหรับฉันที่จะรักษา route.php


Yas งานนี้ Laravel 5.1 เอกสารประกอบไม่ได้กล่าวถึง Route :: resource และ Route :: controller สามารถใช้ร่วมกันได้แทนที่จะกล่าวถึงเกี่ยวกับ Supplementing Resource Controllers ดังนั้นนี่คือความสับสน แต่คำตอบของคุณพิสูจน์แล้วว่าสามารถใช้ร่วมกันได้
อาเมียร์

ฉันขอโทษฮัสซัน jamal สองคนนี้ไม่ได้ทำงานด้วยกัน ดังนั้นตอนนี้ฉันจะตั้งค่าวิธีการโพสต์ที่กำหนดเองในตัวควบคุมได้อย่างไรถ้าฉันใช้เฉพาะ Route :: resource
Amir

3

การใช้ Laravel> 5 ค้นหาไฟล์ web.php ในโฟลเดอร์เส้นทางเพิ่มวิธีการของคุณ

คุณสามารถใช้เส้นทาง :: ทรัพยากรเพื่อกำหนดเส้นทางดัชนีวิธีการเหล่านี้แสดงจัดเก็บอัปเดตทำลายในคอนโทรลเลอร์ของคุณในหนึ่งบรรทัด

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

มันใช้งานได้ค่อนข้างดีเช่นกัน ไม่จำเป็นต้องเพิ่มเส้นทางเพิ่มเติมเพียงใช้วิธีการแสดงตัวควบคุมทรัพยากรเช่นนี้:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.