Laravel:如何针对自定义实现更改UrlGenerator(核心绑定)?

时间:2015-09-22 03:36:58

标签: php laravel ioc-container

我需要使用UrlGenerator的自定义实现。那么如何更改laravel的默认绑定,即在核心深处实现

 'url'                  => ['Illuminate\Routing\UrlGenerator', 'Illuminate\Contracts\Routing\UrlGenerator'],

反对我自己的实施?

而且我不是舒尔。我假设上面的这一行实际上有两件事。它会将bindinung存储在键“url”下,它还会将接口映射到类。所以我实际上需要覆盖两者!怎么做?更进一步,如何确定这是否必须被绑定为“共享”(单例)或“每次都有新实例”?

非常感谢!

3 个答案:

答案 0 :(得分:5)

查看服务容器指南http://laravel.com/docs/5.1/container

在这个特定情况下,我认为您需要做的就是告诉应用程序替换已存在的别名。

要做到这一点,我建议创建一个ServiceProvider,在config/app.php文件中注册并在寄存器方法中的那个文件中输入如下内容:

$this->app->bind('Illuminate\Routing\UrlGenerator', 'yourownclasshere');

告诉我们是否有效。

更新:我删除了无效的选项,只留下了有效的选项。

答案 1 :(得分:0)

我做了Nestor在他的回答中所说的,但对我来说并不奏效。所以这就是我所做的,以使其起作用。 在方法register的服务提供者内部,我首先尝试了此方法:

$this->app->bind('url', MyCustomProvider::class);

这确实注册了我的URL提供程序,而不是默认的URL提供程序。问题是我的提供商现在无法访问路线。我检查了\Illuminate\Routing\RoutingServiceProvider的Laravel代码,因为它具有用于注册URL提供程序的方法registerUrlGenerator。此方法直接实例化了Laravel URL生成器Illuminate\Routing\UrlGenerator,并在构造函数中提供了适当的参数。

因此,我在服务提供商中也做了同样的事情。我没有做$this->app->bind,而是做了$this->app->singleton('url', function ($app) { ... }),并在闭包函数中提供了与RoutingServiceProvider::registerUrlGenerator中相同的代码,但是创建了URL生成器的实例。这样便可以正常工作,现在每次都调用我的生成器。最终的代码是这样的:

// the code is copied from the \Illuminate\Routing\RoutingServiceProvider::registerUrlGenerator() method
$this->app->singleton('url', function ($app) {
    /** @var \Illuminate\Foundation\Application $app */
    $routes = $app['router']->getRoutes();

    $app->instance('routes', $routes);

    // *** THIS IS THE MAIN DIFFERENCE ***
    $url = new \My\Specific\UrlGenerator(
        $routes,
        $app->rebinding(
            'request',
            static function ($app, $request) {
                $app['url']->setRequest($request);
            }
        ),
        $app['config']['app.asset_url']
    );

    $url->setSessionResolver(function () {
        return $this->app['session'] ?? null;
    });

    $url->setKeyResolver(function () {
        return $this->app->make('config')->get('app.key');
    });

    $app->rebinding('routes', static function ($app, $routes) {
        $app['url']->setRoutes($routes);
    });

    return $url;
});

我讨厌复制代码,因此在我看来问题出在基本实现中。 URL生成器应采用正确的约定,而不是直接实例化基类。

答案 2 :(得分:0)

我尝试了 Kosta 的方法,但它并不完全适合我,因为它以某种方式在框架中创建了一个无限的递归循环。尽管如此,我还是得到了这个代码:

namespace App\Providers;

use App\Routing\UrlGenerator;
use Illuminate\Support\ServiceProvider;

class UrlGeneratorServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton("url", function($app) {
            $routes = $app['router']->getRoutes();
            return new UrlGenerator(  // this is actually my class due to the namespace above
                $routes, $app->rebinding(
                    'request', $this->requestRebinder()
                ), $app['config']['app.asset_url']
            );
        });
    }

    protected function requestRebinder()
    {
        return function ($app, $request) {
            $app['url']->setRequest($request);
        };
    }
}

当然,在 config/app.php 下的 'providers'

中注册了上述提供程序