服务系统
服务系统,可以将一个类的对象注册到容器中去,方便调用执行。服务的执行优先级较高,在执行主体程序前就已经完成依赖注入。它的作用可以做一些初始化,配置一些参数,扩展插件等等均可。验证码扩展类就使用了服务系统,我们自己创建一个简单的服务:在common目录下创建一个Shut.php类,这个类是被服务的类。
//定义一个属性字段
protected static $name = 'Mr.Lee';
//设置
public static function setName($name) {
self::$name = $name;
}
//获取
public function run() {
halt(self::$name.'提醒您,系统已关闭...');
}
使用命令行,生成一个对Shut.php服务的服务类ShutSerice.php:
php think make:service ShutService
服务类有两个方法,一个是服务注册register(),一个服务启动boot()
public function register()
{
//绑定到容器,将被服务的类注册到容器中去
$this->app->bind('shut', Shut::class);
}
public function boot() {
//执行
Shut::setName('Mr.Wang');
}
最后一部,将系统服务配置到全局定义文件里,service.php:
return [
\app\service\ShutService::class,
];
最后在任意控制器测试即可,可以容易依赖注入或容器标识执行系统服务:
public function index(Shut $shut)
{
//依赖注入调用
$shut->run();
//容器标识调用
$this->app->shut->run();
return 'index';
}
事件
事件和中间件有一点相似,只不过事件更加的精准定位更细腻的业务场景。事件可定义:事件类、事件监听类、事件订阅类。我们先创建一个测试事件的类:TestEvent.php,手动创建一个测试类。
public function __construct()
{
//注册监听器
Event::listen('TestListen', function ($param) {
echo '我是监听器,我被触发了!'.$param;
});
}
public function info() {
echo '登录前准备!';
Event::trigger('TestListen', 'ok'); //触发监听器
//助手函数触发
event('TestListen');
}
我们也可以使用监听类来设计监听器,使用命令行创建:
php think make:listener TestListen
public function info() {
echo '登录前准备!';
Event::listen('TestListen', TestListen::class); //这句可以定义到配置文件
Event::trigger('TestListen');
}
在app/event.php中,listen是配置监听类的,配置方式如下:
'listen' => [
'TestListen' => [\app\listener\TestListen::class]
],
而监听类被触发会自动执行handle()方法,实现监听功能:
public function handle($event) {
echo '我是监听类!'.$event;
}
系统还内置了系统触发的事件,只要满足条件就会自动触发。
事件监听类,可以同时监听多个监听类,只要绑定到一个标识符即可:
'TestListen' => [
\app\listener\TestListen::class,
\app\listener\TestOne::class,
\app\listener\TestTwo::class
]
对于需要多个监听,监听类不够灵活,而且类会创建很多,可以使用订阅类。订阅类就是将监听事件作为内部的方法用 on+方法名来实现:
php think make:subscribe UserSub
class UserSub {
public function onUserLogin(){
echo '处理登录后的监听!';
}
public function onUserLogout(){
echo '处理退出后的监听!';
}
}
然后,直接去app/event.php注册一下:
'subscribe' => [
'UserSub' => \app\subscribe\UserSub::class,
],
然后,两个方法分别监听两个事件方法,直接调用方法名即可:
public function login(){
echo '登录成功!';
Event::trigger('UserLogin');
}
public function logout(){
echo '退出成功!';
Event::trigger('UserLogout');
}
对于事件类,很少有场景需要使用它,毕竟系统提供的各种精确方案较多:
php think make:event UserEvent
class UserEvent
{
public function __construct() {
echo '我是事件类!';
}
}
Event::trigger(new UserEvent());
多应用模式
由于多应用模式属于扩展,我们需要额外安装:
composer require topthink/think-multi-app
安装后,创建index和admin两个应用目录文件夹,只要将controller和model移入即可,修改相应的命名空间。将 view也增加index和admin两个应用目录文件夹,移入相应文件夹。默认的应用为index,在app.php修改即可。
// 默认应用
'default_app' => 'index',
举例一个多应用的目录结构:
可以做应用映射,比如将 admin目录映射为think,admin废弃:
// 应用映射(自动多应用模式有效)
'app_map' => [
'think' => 'admin'
],
我们也可以做域名绑定,比如,后台用域名绑定,直接访问:
// 域名绑定(自动多应用模式有效)
'domain_bind' => [
'news.abc.com' => 'admin',
'*' => 'index'
],
路由修改:需要在应用目录单独建立路由,内部编码不需要更改。