官方关于Service的说明文档:
https://www.kancloud.cn/manual/thinkphp6_0/1037490
做下概念说明:
Service和Provider在TP6中扮演着不同的角色。Service是用于封装特定功能的类,而Provider是用于注册和配置Service的类。
这里的Service指的是注册到容器中的一系列可以调用的类或方法(函数)。注册后的类或方法,可以直接从容器调用(即:依赖注入),例:
app(‘test’)->show();
看下是如何做到的,以下只对开发composer扩展包进行说明,写在项目目录中的可以参考官方的说明。
1.新建一个扩展包。
2.扩展包添加composer.json文件
{
"name": "test/svs",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"Test\\Svs\\": "src/"
}
},
"extra": {
"think": {
"services": [
"Test\\Svs\\SvsService" # 这里必须写正确(写不正确TP也不会报错,只会让你搞不清楚为什么不生效...)
]
}
}
}
3.新建src目录,并添加具体的服务(即:Service)文件:Test.php
这个类将被注册到容器中:
<?php
namespace Test\Svs;
class Test
{
private $foo;
public function __construct(Foo $foo)
{
$this->foo = $foo;
}
public function show()
{
echo 'say test...';
$this->foo->show();
}
}
再建2个类用于测试依赖注入:
先来一个接口:
<?php
namespace Test\Svs;
interface IFoo
{
public function show();
}
建两个类实现接口:
这个类只是实现了接口,但由于没有注册到容器,所以不能自动注入
<?php
namespace Test\Svs;
class Foo implements IFoo
{
public function show()
{
echo 'say foo...';
}
}
Bar.php,指定用来依赖注入的:
<?php
namespace Test\Svs;
class Bar implements IFoo
{
public function show()
{
echo 'say bar...';
}
}
4.新建服务注册(即:Provider)文件:SvsService.php
这个类是用来把Test注册到容器中,并可以执行启动相关操作。register()比boot()方法先执行。
<?php
namespace Test\Svs;
use think\Service;
/**
* 定义服务类
* 安装时将被添加到vendor/services.php中
*
* @author gjw
* @created 2023-06-29 09:35:28
*/
class SvsService extends Service
{
/**
* 注册
*
* @author gjw
* @created 2023-06-29 09:36:22
*
* @return void
*/
public function register()
{
echo 'SvsService::register()';
// 注册一个类到容器
// $this->app->bind('test', Test::class); // 实例类型是确定的可以不注册,系统能根据类型找到要注入哪个类
$this->app->bind(IFoo::class, Bar::class); // 实例类型是不确定的,要明确指出要注入哪个类
// 这里只做个绑定演示,个人感觉类型不确定的不要在这里进行绑定(相当于是写死了)
// 可以在配置文件中设置绑定:app/provider.php(app/service.php虽然可以绑定,但不能指定类型--键名就是类型)
}
/**
* 启动
*
* @author gjw
* @created 2023-06-29 09:36:29
*
* @return void
*/
public function boot()
{
echo 'SvsService::boot()';
// 注册到容器的类已可以使用
app('test')->show();
}
}
SvsService这个类在composer.json中已配置过,所以运行composer安装或单独执行命令(php think service:discover)时,会被注册到vendor/services.php中。当程序运行时(包含command),这个文件会被加载,并运行注册和启动方法。
也就是说,composer方法注册的服务不需要添加到app/services.php即可使用。
接下来,项目任意位置都可以这样用了:
app(‘test’)->show();
或是在控制器方法上直接用作参数:
public function index(SvsTest $t)
{
echo '<br>';
$t->show();
return view('index', array('time' => time()));
}