ChatGPT解决这个技术问题 Extra ChatGPT

在 Laravel 中为资源控制器添加新方法

我想知道是否可以在 Laravel 的资源控制器中添加新方法以及如何操作。

我知道这些方法是默认的(索引、创建、存储、编辑、更新、销毁)。现在我想向同一个控制器添加其他方法和路由。

那可能吗?


J
Joseph Silber

只需在注册资源之前单独添加到该方法的路由:

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

请注意,您的新方法必须高于 ::resource,否则您会收到错误消息“No query results for model”。
你将如何传递像 {id} 这样的参数?目前我已经在 routes.php 中内联了我的自定义方法(就像这里的示例 laravel.com/docs/5.1/routing#route-parameters)。理想情况下,我想传递参数以在 FooController 中运行。
发现问题 - 不在 Route 语法中。实际上是在我正在使用的一些自定义中间件中!路线::get('foo/{id}/bar', 'FooController@bar');将 id 传递给 bar($id) 方法。谢谢!
有人可以解释为什么自定义路由应该高于资源路由吗???我做了一些测试,似乎放在上面或下面没有区别......
@RicardoVigatti - 资源注册此路由:Route::get('foo/{id}', ...)。这会吞下所有以 foo 开头并具有一个附加段的路由,包括 foo/bar
M
Mathieu Ferre

是的,有可能。。

在我的情况下,我添加方法:数据来处理 HTTP POST 方法中对 /data.json 的请求。

这就是我所做的。

首先我们扩展 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检查,您会发现新方法 'data'


您的解决方案对我有用。您能告诉我在使用此代码几个月后是否发现任何问题吗?
谢谢@RicardoVigatti。我从 laravel 5.2 开始使用它,现在我在最近的 L5.3 项目中使用它并且没有问题。如果你有的话请告诉我,也许我可以帮助你..
很好,我在我的 5.0 项目中实现了这个。解决方案似乎非常一致,但是,如果有任何问题发生,将在几周后。
@MokhamadRofi'udin 我已经实现了您的解决方案,新路由已添加到路由列表中,但似乎没有添加相应的方法。我错过了什么吗?
@Siavosh 只需在控制器中编写您的方法,即我添加方法 data() :` public function data(Request $request) { }`
A
Antonio Carlos Ribeiro

我只是这样做了,添加了一个 GET “删除”方法。

创建文件后,您只需要添加

'AntonioRibeiro\Routing\ExtendedRouterServiceProvider',

到您的 app/config.php 中的“提供者”

在同一文件中编辑 Route 别名:

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

将其更改为

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

并确保这些文件正在被自动加载,它们必须位于您的 composer.json (“自动加载”部分)中的某个目录中。

然后你只需要:

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

如果您运行 php artisan routes,则结果如下(查看最后一行):

https://i.stack.imgur.com/GIvs8.png

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

}

扩展路由器.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');
    }

}

您能否为 Laravel 5 及更高版本提供相同的内容?我一直在尝试重现这个......但我似乎无法找到他们在容器中注册“路由”访问器的位置。
为什么文件有扩展名.pas?
有道理,但提供者部分似乎不适用于 laravel 8.0。
悲哀地过于复杂
H
Hassan Jamal
Route::resource('foo', 'FooController');
Route::controller('foo', 'FooController');

试试这个。给你额外的方法,比如 getData() 等等。这对我来说保持 route.php 干净


是的,这很有效。 Laravel 5.1 文档没有提到 Route::resource 和 Route::controller 可以一起使用,而是提到了补充资源控制器。所以这很困惑。但是您的ans证明这些可以一起使用
很抱歉 Hassan jamal,这两个人没有合作。那么现在如果我只使用 Route::resource 我如何在控制器中设置自定义发布方法
M
Mazen Embaby

使用 Laravel >5 在 routes 文件夹中找到 web.php 文件添加你的方法

您可以使用 route::resource 将所有这些方法的 index、show、store、update、destroy 路由到您的控制器中的一行中

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

D
David Buck

以前我将我的路线定义为:

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

它给出了错误:

路由 foo.bar 未定义

然后在谷歌搜索后我添加了名字

Route::get('foo/bar', 'FooController@bar')->name('foo.bar');

它工作得很好。


P
Patrick Lumenus

只需添加一个新方法和该方法的路由。

在您的控制器中:

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

在您的网络路线中

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

只要确保控制器中的方法是公开的。


D
Dev Lim

我解决了

创建扩展 BaseRouter 的自定义路由器文件

// src/app/Custom/Router.php


<?php

namespace App\Custom;

use Illuminate\Routing\Router as BaseRouter;
use Illuminate\Support\Str;

class Router extends BaseRouter
{
    public function customResource($name, $controller, array $options = [])
    {
        $model = Str::singular($name); // this is optional, i need it for Route Model Binding

        $this
            ->get( // set the http methods
                $name .'/{' . $model . '}/audit',
                $controller . '@audit'
            )->name($name . '.audit');

        return $this->resource($name, $controller, $options);
    }
}

然后在 src/bootstrap/app.php 注册

$app->singleton('router', function ($app) {
    return new \App\Custom\Router($app['events'], $app);
});

并在 /routes/web.php 上使用它

Route::customResource(
    'entries',
    'EntryController'
);

m
mdamia

这也很好用。无需添加更多路由,只需使用资源控制器的 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(){}

我使用默认值来抛出自定义错误页面。


这感觉就像是真正的代码气味。我不希望我的控制器处理多个动作。
这不是打破了 REST 概念吗?
没必要做这种事!!!这就是为什么我们首先要有路线。路由逻辑不能放在控制器上。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅