为什么赢了';这不是Laravel 5.4服务提供商注册吗?
我正在尝试用新的Laravel 5.4做一个hello world服务提供商 我已创建以下服务提供商文件:为什么赢了';这不是Laravel 5.4服务提供商注册吗?,laravel,laravel-5.3,Laravel,Laravel 5.3,我正在尝试用新的Laravel 5.4做一个hello world服务提供商 我已创建以下服务提供商文件: //File: app/TestProvider/TestServiceProvider.php namespace App\TestProvider; use Illuminate\Support\ServiceProvider; class TestServiceProvider extends ServiceProvider { /** * Register
//File: app/TestProvider/TestServiceProvider.php
namespace App\TestProvider;
use Illuminate\Support\ServiceProvider;
class TestServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
$this->app->bind('Test', function ($app) {
return new Test();
});
}
}
我在同一命名空间下创建了一个简单类:
//File: app/TestProvider/Test.php
namespace App\TestProvider;
class Test
{
/**
* Register bindings in the container.
*
* @return void
*/
public function helloWorld()
{
echo "hello world";
}
}
问题是,这不是注册。寄存器方法的执行方式与我在“bind”方法之前放置一个断路器时相同,它执行:
public function register()
{
dd("BREAKER");
$this->app->bind('Test', function ($app) {
return new Test();
});
}
因此,这将输出预期的“断路器”。然而,如果我将断路器置于关闭状态,则不会发生任何事情,这表明出于某种原因,“绑定”方法没有被执行
有什么想法吗
编辑:
只是一些进一步的信息:我知道测试类已注册,并且位于正确的命名空间中,正如我所能做的:
dd(new Test());
在注册方法中,它会按预期输出资源id。尝试:
$this->app->bind(Test::class, function ($app) {
return new Test();
});
传递给
bind()
方法的闭包在您实际尝试解析绑定的别名之前不会执行
因此,如果在闭包内执行dd('breaker')
,则在解决Test
之前,不会执行此操作(无论您首选的解决方法是什么):
服务提供者:
// bind the closure to the 'Test' alias
public function register()
{
$this->app->bind('Test', function ($app) {
dd("BREAKER");
return new Test();
});
}
解析测试别名的代码:
// different ways of resolving the alias out of the container.
// any of these will execute the bound closure.
$test = resolve('Test');
$test = app('Test');
$test = app()->make('Test');
$test = \App::make('Test');
解释
提供的闭包仅在解析绑定时运行。这就是为什么它是一个闭包,它可以保存在服务容器中,并在程序运行时随时解析
解决方案
要查看已解析的绑定,请创建控制器并解析该控制器中的类:
//文件:app/Http/Controllers/TestController.php
名称空间App\Http\Controllers;
//这不是最好的方法,但它很有效。请参阅下面的最佳方式
类TestController扩展控制器{
公共职能指数()
{
return\App::make('Test')->helloWorld();
}
}
当然,不要忘记注册路线:
//文件:routes/web.php
路由::获取('/','TestController@index');
当您点击主页时,绑定将解决
然而,正如我所说,这不是最好的方法,所以在这里我准备了一个更好的方法。更改注册绑定的方式:
//文件:app/Providers/TestProvider.php
名称空间App\TestProvider;
使用Illumb\Support\ServiceProvider;
使用App\TestProvider\Test;
//更好的方法
类TestServiceProvider扩展了ServiceProvider
{
/**
*在容器中注册绑定。
*
*@返回无效
*/
公共职能登记册()
{
//注意:我们绑定了准确完整的类名!
$this->app->bind(测试::类,函数($app){
返回新测试();
});
}
}
在此之后,更改控制器,使其如下所示:
namespace-App\Http\Controllers;
使用App\TestProvider\Test;
类TestController扩展控制器{
/**
*@var Test$Test
*/
私人测试;
//让Laravel解决对构建类的依赖
公共函数构造(Test$Test)
{
$this->test=$test;
}
公共职能指数()
{
返回$this->test->helloWorld();
}
}
你会看到完全相同的事情发生,但它看起来更优雅,避免冲突
细节
Laravel只提供了服务容器的高级概述,这无助于了解它在内部是如何工作的。最好的方法是查看调用堆栈
当您这样做时,您会发现Laravel在服务容器中注册了项目中的每个类。这意味着无论您是否创建服务提供者,该类都将位于容器中。到底是怎么回事
运行php artisan optimize
时,Laravel将创建包含项目所有类的数组的文件。运行应用程序时,在注册了服务提供商提供的所有内容后,Laravel将注册该文件中的其余类
这意味着在您的情况下,如果您没有专门注册测试类,它仍然是可以解决的。基本上,您只需要注册需要解析某些特定指令的类
那么,Laravel如何解决依赖关系呢
\App::make(Test::class)
或通过构造函数中的类型暗示(我的解决方案中的“更好的方法”)注入依赖项时,Laravel会在绑定中查找该依赖项$test=newtest()代码>并期望拉威尔完成所有的魔法:)
结论
这是对Laravel服务容器的快速概述。当然,你学习它的最好方法是自己研究资料来源。它非常优雅,充分利用了PHP的功能
我真的希望这能为您提供一些关于服务容器的信息,并在将来对您有所帮助:)您在哪里使用该类?也发布该部分的代码。这并不是对问题的真正回答,但对于任何未来的谷歌用户来说:确保您试图绑定的类的名称空间正确,并且在必要时以斜杠开头。i、 例如,$this->app->bind(\Fully\Qualified\Name::class…
,而不是$this->app->bind(Fully\Qualified\Name::class…
没什么不幸的。但是您需要在u构造方法中编写回音“Hello World”,而不是helloWorld(),但它没有输出任何内容,因为它没有执行闭包,只是绑定。您可以检查Laravel的本机AuthServiceProvider的寄存器,然后