hyperf console 执行

news2024/11/24 14:23:21

一、原理描述

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()。

二、原理总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1343468.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

楼宇智慧能源消耗监测管理系统,楼宇中的能源“管家”

随着人口的增加,楼宇数据呈上涨趋势,但是楼宇智能建设在我国普及性远远不足,相比传统楼宇控制,智能楼宇控制系统对于楼宇内部的用电设备控制,能够更加的节约能源,降低成本。对于现代化楼宇而言,…

大数据学习(29)-Spark Shuffle

&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主哦&#x1f91…

代码质量评价及设计原则

1.评价代码质量的标准 1.1 可维护性 可维护性强的代码指的是: 在不去破坏原有的代码设计以及不引入新的BUG的前提下,能够快速的修改或者新增代码. 不易维护的代码指的是: 在添加或者修改一些功能逻辑的时候,存在极大的引入新的BUG的风险,并且需要花费的时间也很长. 代码可…

winserver2008 r2服务器iis配置支持flv,f4v,mp4格式视频

很多政府单位网站一直在使用WIN服务器,大部分网站都使用多年基本使用.NET或者CMS系统建站,系统环境也一直是老版本,今天在维护过程中又出现了新问题,上传的MP4文件不支持网站上播放,顺便也分享下解决过程。当我们架设的…

分布式系统架构设计之分布式系统架构演进和版本管理

在分布式系统的生命周期中,架构演进和版本管理是很重要的两个环节。本部分会介绍分布式系统架构演进的原则、策略以及版本管理的最佳实践,以帮助研发团队更好地应对需求变化、技术发展和系统升级。 架构演进 演进原则 渐进式演进 采用渐进式演进的原…

【51单片机系列】DS1302时钟模块扩展实验之与EEPROM结合使用只进行一次初始化工作

本文是关于时钟芯片DS1302的扩展实验。 文章目录 一、实验分析二、proteus仿真原理图三、软件设计及结果 本实验实现的目的:利用AT24C02掉电不丢失的功能,存储数据用来辨别DS1302时钟是否已经初始化,如果初始化就不执行DS1302初始化函数。 一…

HTML实战演练之贪吃蛇美食大作战

导入: 一 :粉丝要求 今天一位小伙伴私信我说,想玩HTML贪吃蛇美食大作战,自己也是学HTML的,希望我能安排一下,那么好它来了 需知: 一:别着急先看需要知道的 要用HTML开发贪吃蛇美食…

腾讯云服务器租用价格表和优惠活动大全

腾讯云服务器租用价格表:轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年,540元三年、2核4G5M带宽218元一年,2核4G5M带宽756元三年、轻量4核8G12M服务器446元一年、646元15个月,云服务器CVM S5实例2核2G配置280.8元一年…

Vue(二):计算属性与 watch 监听器

03. Vue 指令拓展 3.1 指令修饰符 可以通过 . 来指明一些指令的后缀,不同的后缀中封装了不同的操作,可以帮助我们简化代码,比如之前使用过的监听 enter 键的弹起,我们需要操作事件对象,来检测用户使用了哪个键&#…

亚马逊云科技Amazon MSK基于S3云服务器实现导出导入、备份还原、迁移方案

亚马逊云科技Amazon MSK是Amazon云平台提供的托管Kafka服务。在系统升级或迁移时,用户常常需要将一个Amazon MSK集群中的数据导出(备份),然后在新集群或另一个集群中再将数据导入(还原)。通常,K…

【网络安全 | CTF】FlatScience

该题考察SQL注入 正文 后台扫到robots.txt 页面内容如下&#xff1a; 进入login.php 页面源代码如图&#xff1a; 传参debug得到php代码&#xff1a; <?php if(isset($_POST[usr]) && isset($_POST[pw])){$user $_POST[usr];$pass $_POST[pw];$db new SQLite3…

Linux(ubuntu)下git / github/gitee使用

先附上git命令 linuxchenxiao:~$ cd Templates/ 先进入一个目录&#xff0c;也可mkdir新建一个目录&#xff1a;用于接下来初始化为git可以管理的仓库 这个目录就是所说的工作目录&#xff0c;指当前正在进行开发的项目的本地目录。 linuxchenxiao:~/Templates$ git init 已…

Web自动化测试:Selenium入门到精通

前言 说到自动化测试&#xff0c;就不得不提大名鼎鼎的Selenium。Selenium 是如今最常用的自动化测试工具之一&#xff0c;支持快速开发自动化测试框架&#xff0c;且支持在多种浏览器上执行测试。 Selenium学习难度小&#xff0c;开发周期短。对测试人员来说&#xff0c;如果…

C# 使用ZXing.Net生成二维码和条码

写在前面 条码生成是一个经常需要处理的功能&#xff0c;本文介绍一个条码处理类库&#xff0c;ZXing用Java实现的多种格式的一维二维条码图像处理库&#xff0c;而ZXing.Net是其.Net版本的实现。 在WinForm下使用该类库需要从NuGet安装两个组件&#xff1a; ZXing.Net ZXing…

python+django网上银行业务综合管理系统vue_bvj8b

本课题主要研究如何用信息化技术改善传统网上银行综合管理行业的经营和管理模式&#xff0c;简化网上银行综合管理的难度&#xff0c;根据管理实际业务需求&#xff0c;调研、分析和编写系统需求文档&#xff0c;设计编写符合银行需要的系统说明书&#xff0c;绘制数据库结构模…

网络安全应急响应工具之-流量安全取证NetworkMiner

在前面的一些文章中&#xff0c;用了很多的章节介绍流量分析和捕获工具wireshark。Wireshark是一款通用的网络协议分析工具&#xff0c;非常强大&#xff0c;关于wireshark的更多介绍&#xff0c;请关注专栏&#xff0c;wireshark从入门到精通。本文将介绍一个专注于网络流量取…

Ubuntu 安装MySQL以及基本使用

前言 MySQL是一个开源数据库管理系统&#xff0c;通常作为流行的LAMP&#xff08;Linux&#xff0c;Apache&#xff0c;MySQL&#xff0c;PHP / Python / Perl&#xff09;堆栈的一部分安装。它使用关系数据库和SQL&#xff08;结构化查询语言&#xff09;来管理其数据。 安装…

Kafka:本地设置

这是设置 Kafka 将数据从 Elasticsearch 发布到 Kafka 主题的三部分系列的第一部分;该主题将被 Neo4j 使用。第一部分帮助您在本地设置 Kafka。第二部分将讨论如何设置Elasticsearch将数据发布到Kafka主题。最后 将详细介绍如何使用连接器订阅主题并使用数据。 Kafka Kafka 是…

3.云原生之kubesphere运维

文章目录 k8s节点状态介绍配置宿主机使用k8s内部域名使用KubeKey 升级kubesphere使用KubeKey添加节点使用KubeKey下架节点使用k8s命令添加新节点k8s集群备份与恢复环境准备备份与还原在集群A和B中安装Velero集群A备份操作集群B还原备份操作 注意&#xff1a;所有节点运维操作前…

TON 入门之旅:从 0 到 1 探索 TON 生态钱包开发路径

TON 区块链被设计为分布式超级计算机或“超级服务器&#xff08;superserver&#xff09;”&#xff0c;旨在提供各种产品和服务&#xff0c;以促进去中心化的发展。顺利从 TON 生态入门区块链开发世界需要理解哪些智能合约语言&#xff0c;掌握哪些应用搭建技巧&#xff1f;第…