hyperf console 执行
一、原理描述
hyperf中,不难发现比如自定义控制器中获取参数,hyperf.php中容器获取,传入的都是接口,而不是实体类。
这是因为框架中的配置文件有设置对应抽象类的子类,框架加载的时候将其作为数组,使用的时候通过数组对应子类。
实现这个功能就需要composer autoload 代理,即生成的composer.lock文件再处理。但是需要其余对应的composer拉取的程序在composer.json中设置对应数据。
例如
//vendor\hyperf\http-server\composer.json
"extra": {"branch-alias": {"dev-master": "2.2-dev"},"hyperf": {"config": "Hyperf\\HttpServer\\ConfigProvider"}}
//vendor\hyperf\db-connection\composer.json"extra": {"branch-alias": {"dev-master": "2.2-dev"},"hyperf": {"config": "Hyperf\\DbConnection\\ConfigProvider"}}
#vendor/hyperf/http-server/src/ConfigProvider.php
namespace Hyperf\HttpServer;use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;class ConfigProvider
{public function __invoke(): array{return ['dependencies' => [RequestInterface::class => Request::class,ServerRequestInterface::class => Request::class,ResponseInterface::class => Response::class,],'annotations' => ['scan' => ['paths' => [__DIR__,],],],];}
}#vendor\hyperf\db-connection\src\ConfigProvider.php
namespace Hyperf\DbConnection;use Hyperf\Database\Commands\Migrations\FreshCommand;
use Hyperf\Database\Commands\Migrations\GenMigrateCommand;
use Hyperf\Database\Commands\Migrations\InstallCommand;
use Hyperf\Database\Commands\Migrations\MigrateCommand;
use Hyperf\Database\Commands\Migrations\RefreshCommand;
use Hyperf\Database\Commands\Migrations\ResetCommand;
use Hyperf\Database\Commands\Migrations\RollbackCommand;
use Hyperf\Database\Commands\Migrations\StatusCommand;
use Hyperf\Database\Commands\ModelCommand;
use Hyperf\Database\Commands\Seeders\GenSeederCommand;
use Hyperf\Database\Commands\Seeders\SeedCommand;
use Hyperf\Database\ConnectionResolverInterface;
use Hyperf\Database\Connectors\ConnectionFactory;
use Hyperf\Database\Connectors\MySqlConnector;
use Hyperf\Database\Migrations\MigrationRepositoryInterface;
use Hyperf\DbConnection\Listener\RegisterConnectionResolverListener;
use Hyperf\DbConnection\Pool\PoolFactory;class ConfigProvider
{public function __invoke(): array{return ['dependencies' => [PoolFactory::class => PoolFactory::class,ConnectionFactory::class => ConnectionFactory::class,ConnectionResolverInterface::class => ConnectionResolver::class,'db.connector.mysql' => MySqlConnector::class,MigrationRepositoryInterface::class => DatabaseMigrationRepositoryFactory::class,],'commands' => [ModelCommand::class,GenMigrateCommand::class,InstallCommand::class,MigrateCommand::class,FreshCommand::class,RefreshCommand::class,ResetCommand::class,RollbackCommand::class,StatusCommand::class,GenSeederCommand::class,SeedCommand::class,],'listeners' => [RegisterConnectionResolverListener::class,],'annotations' => ['scan' => ['paths' => [__DIR__,],],],'publish' => [['id' => 'config','description' => 'The config for database.','source' => __DIR__ . '/../publish/databases.php','destination' => BASE_PATH . '/config/autoload/databases.php',],['id' => 'query-listener','description' => 'The listener of database to record log.','source' => __DIR__ . '/../publish/DbQueryExecutedListener.php','destination' => BASE_PATH . '/app/Listener/DbQueryExecutedListener.php',],],];}
}
以bin/hyperf.php为例,加载autoload.php文件,执行Hyperf\Di\ClassLoader::init()设置,执行
$application->run();输出命令。
1.1 Hyperf\Di\ClassLoader::init()
Hyperf\Di\ClassLoader::init() 加载配置文件、composer.lock,并合并数据。
主要使用Composer::getMergedExtra('hyperf')['config'],就是composer.lock中extra中的hyperf中config值。
根据config中的值,调用其__invoke()获取数组,并设置。
在上述过程中,涉及ProviderConfig::load();运行,会对ProviderConfig::$providerConfigs数据进行初始化。
ProviderConfig::load()获取的值中包括每个composer拉取的程序中ConfigProvider.php文件中的内容,当然也就包括commands。
ProviderConfig::load()在之后也会被使用。
ClassLoader::init()会调用其构造函数,打印ClassLoader构造中的$config = ScanConfig::instance($configDir);结果,可以看到类内的成员变量包括cacheable、configDir、paths、collectors、ignoreAnnotations、globalImports、dependencies、classMap。
就bin/hyperf.php而言,此时并没有使用配置中的commands数据。
1.2 /config/container.php
hyperf.php中随后加载/config/container.php。
container.php中通过$container = new Container((new DefinitionSourceFactory(true))());,调用DefinitionSourceFactory的构造和__invoke()方法。
DefinitionSourceFactory::__invoke()中通过ProviderConfig::load();加载配置,获取配置中的dependencies数组,最后返回key和object对应的数组。
container.php文件最后返回 Hyperf\Di\Container类,其构造参数的为DefinitionSourceFactory::__invoke()返回的数组。
Hyperf\Di\Container构造方法中会设置$this->definitionSource和$this->resolvedEntries。
1.3 $container->get()
$application对象通过$application = $container->get(Hyperf\Contract\ApplicationInterface::class);获取。调用$container->get()会先判断Container::resolvedEntries是否有数据,有则返回,否则使用Container::make()使用Container::definitionSource创建数据。最后返回对应的实体类。
即为,$application = $container->get(Hyperf\Contract\ApplicationInterface::class);返回ApplicationFactory类,ApplicationFactory构造最后返回Symfony\Component\Console\Application类。
Hyperf\Contract\ApplicationInterface::__invoke()会先执行。其中运行Application::__construct(),设置默认值,比如默认命令为“list”。__invoke()还会将commands数据添加到Symfony\Component\Console\Application中。
1.4 Application::run()
调用 $application->run();,就是调用Symfony\Component\Console\Application::run()。
对于配置文件中commands的处理、console的使用也是在Application::run()方法中。
Application::run()调用Application::doRun()。
doRun()中执行默认的命令“list”,运行Symfony\Component\Console\Command\ListCommand::execute(),其中运行DescriptorHelper::__construct()。
ListCommand::execute()通过DescriptorHelper::describe()运行TextDescriptor(默认)的父类Descriptor::describe()。
Descriptor::describe()中通过其子类实现的describeApplication()方法,获取项目中的commands(配置中的commands),这里即为TextDescriptor::describeApplication()。
TextDescriptor::describeApplication()中通过调用 ConsoleOutput->write()输出内容。
每个命令的execute()方法通过其父类Symfony\Component\Console\Command:run()调用。
dorun()中调用doRunCommand(),这其中会调用Command:run()。
二、原理总结

相关文章:
hyperf console 执行
一、原理描述 hyperf中,不难发现比如自定义控制器中获取参数,hyperf.php中容器获取,传入的都是接口,而不是实体类。 这是因为框架中的配置文件有设置对应抽象类的子类,框架加载的时候将其作为数组,使用的…...
第一篇 设计模式引论 - 探索软件设计的智慧结晶
1. 设计模式的定义和起源 设计模式,这个术语最初在建筑领域被广泛使用,用来描述在建筑设计中反复出现的问题及其解决方案。在软件工程中,设计模式同样指的是在软件设计过程中反复出现的、经过验证的最佳实践和解决方案。 1994年,…...
HBase基础知识(六):HBase 对接 Hive
1. HBase 与 Hive 的对比 1.Hive (1) 数据仓库 Hive 的本质其实就相当于将 HDFS 中已经存储的文件在 Mysql 中做了一个双射关系,以 方便使用 HQL 去管理查询。 (2) 用于数据分析、清洗 Hive 适用于离线的数据分析和清洗,延迟较高。 (3) 基于…...
Java连接Mysql报错:javax.net.ssl.SSLException: Received fatal alert: internal_error
大致报错日志如下: The last packet successfully received from the server was 11 milliseconds ago. The last packet sent successfully to the server was 10 milliseconds ago.at sun.reflect.GeneratedConstructorAccessor275.newInstance(Unknown Source)…...
Mixtral 8*7B + Excel + Python 超强组合玩转数据分析
Mixtral 8*7B Excel Python 超强组合玩转数据分析 0. 背景1. 使用 Mixtral 8*7B pandas 实现数据导入和导出1.1 使用 Mixtral 8*7B pandas 导入 Excel 文件中的数据1.2 使用 Mixtral 8*7B pandas 导出 Excel 文件中的数据 2. 使用 Mixtral 8*7B pandas 实现单个文件数据的…...
深入浅出理解Web认证:Session、Cookie与Token
在Web开发的世界中,理解Session、Session ID、Cookie和Token之间的区别至关重要。实际上,这些概念并不复杂,只需几句话就能澄清它们的核心区别。 首先,我们需要区分Session和Session ID。Session实际上是存储在服务器端的数据&am…...
智慧零售技术探秘:关键技术与开源资源,助力智能化零售革新
智慧零售是一种基于先进技术的零售业态,通过整合物联网、大数据分析、人工智能等技术,实现零售过程的智能化管理并提升消费者体验。 实现智慧零售的关键技术包括商品的自动识别与分类、商品的自动结算等等。 为了实现商品的自动识别与分类,…...
2012年第一届数学建模国际赛小美赛B题大规模灭绝尚未到来解题全过程文档及程序
2012年第一届数学建模国际赛小美赛 B题 大规模灭绝尚未到来 原题再现: 亚马逊是地球上现存最大的雨林,比地球上任何地方都有更多的野生动物。它位于南美洲大陆的北侧,共有9个国家:巴西、玻利维亚、厄瓜多尔、秘鲁、哥伦比亚、委…...
macos管理本地golang的多版本sdk
背景 无论你是哪个编程语言的开发者,例如 Java、Go 等,通常在本地开发过程中,你经常需要安装相应的 SDK。由于各种原因,往往需要在不同的项目中来回切换多个版本的 SDK。 安装步骤 1.安装homebrew /bin/bash -c "$(curl -…...
count distinct在spark中的运行机制
文章目录 预备 数据和执行语句Expand第一次HashAggregateShuffle and Second HashAggregate最后结果性能原文 预备 数据和执行语句 SELECT COUNT(*), SUM(items), COUNT(DISTINCT product), COUNT(DISTINCT category) FROM orders;假设源数据分布在两个1核的结点上࿰…...
创建加密分区或者文件
文章目录 [GParted 中已清除的分区与未格式化的分区](https://superuser.com/questions/706624/cleared-vs-unformatted-partition-in-gparted)创建加密分区解密创建的加密分区以便挂载格式化设备未具体的格式(这里为ext4格式)创建挂载点目录挂载加密的文…...
STL——遍历算法
1.for_each 函数原型: for_each(iterator beg, iterator end, _func);——// 遍历算法 遍历容器元素; beg 开始迭代器;end 结束迭代器; _func 函数或者函数对象 #include<iostream> using namespace std; #include<ve…...
C语言经典算法【每日一练】20
题目:有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。 1、先排序 2、插入 #include <stdio.h>// 主函数 void main() {int i,j,p,q,s,n,a[11]{127,3,6,28,54,68,87,105,162,18};//排序(选择排序)…...
Linux磁盘阵列
一.RAID磁盘阵列介绍 RAID(Redundatnt Array of lndependent Disks),全称为:独立冗余磁盘阵列 解释: RAID是一种把多块独立的硬盘(物理硬盘)按不同的方式组合起来形成一个硬盘组(逻…...
本地网络禁用了在哪里开启?
在当今数字化时代,网络已经成为人们生活中不可或缺的一部分。然而,有时我们可能需要禁用本地网络,无论是出于安全考虑、提高专注力还是其他原因。本文将探讨禁用本地网络的方法以及如何在需要时重新开启网络连接。 第一部分:禁用…...
[mysql 基于C++实现数据库连接池 连接池的使用] 持续更新中
目背景 常见的MySQL、Oracle、SQLServer等数据库都是基于C/S架构设计的,即(客户端/服务器)架构,也就是说我们对数据库的操作相当于一个客户端,这个客户端使用既定的API把SQL语句通过网络发送给服务器端,MyS…...
【Flink SQL API体验数据湖格式之paimon】
前言 随着大数据技术的普及,数据仓库的部署方式也在发生着改变,之前在部署数据仓库项目时,首先想到的是选择国外哪家公司的产品,比如:数据存储会从Oracle、SqlServer中或者Mysql中选择,ETL工具会从Informa…...
idea导入spring-framework异常:error: cannot find symbol
从github上clone代码spring-framework到本地后导入idea,点击gradle构建后控制台提示异常: 具体异常信息: /Users/ZengJun/Desktop/spring-framework/buildSrc/src/main/java/org/springframework/build/KotlinConventions.java:44: error:…...
Unity坦克大战开发全流程——开始场景——开始界面
开始场景——开始界面 step1:设置UI 反正按照这张图拼就行了 step2:写脚本 前面的拼UI都是些比较机械化的工作,直到这里写代码的时候才真正开始有点意思了,从这里开始,我们就要利用面向对象的思路来进行分析࿱…...
【SpringCloud】从实际业务问题出发去分析Eureka-Server端源码
文章目录 前言1.EnableEurekaServer2.初始化缓存3.jersey应用程序构建3.1注册jeseryFilter3.2构建JerseyApplication 4.处理注册请求5.registry() 前言 前段时间遇到了一个业务问题就是k8s滚动发布Eureka微服务的过程中接口会有很多告警,当时…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
