news 2026/10/15 11:57:49

PHPStan 2.0 升级全指南:从 1.x 平滑迁移的配置变更与扩展开发适配

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHPStan 2.0 升级全指南:从 1.x 平滑迁移的配置变更与扩展开发适配
  • 开发工具
  • 后端

【免费下载链接】environment

Provides functionality that helps writing PHP code that has runtime-specific execution paths

项目地址:https://gitcode.com/gh_mirrors/en/environment
点击查看免费下载

PHPStan 2.0 是 PHP 静态分析工具的一次大版本跃迁,它把过去只在 Bleeding Edge 模式下启用的新规则、新行为全面铺开,并移除了大量旧配置项与旧 API。本文以 PHPStan 官方仓库中的 UPGRADING.md 为核心骨架,逐条拆解最终用户与扩展开发者需要面对的迁移点,并结合本仓库(sebastian/environment,一个探测 PHP/HHVM 运行时环境的开源组件)中真实的 phpstan.neon 与tools/.phpstan/vendor/phpstan/依赖布局,演示 2.0 配置在实践中长什么样。读完本文,你将掌握:升级前的准备步骤、被移除配置项的官方替代写法、ignoreErrors标识符与excludePaths的新语法,以及扩展开发所需的所有破坏性 API 变更清单。

一、PHP 版本要求:PHPStan 2.0 的最低门槛

根据 UPGRADING.md 的明确说明,PHPStan 2.0 自身运行要求PHP 7.4 或更新版本。这意味着即使你被分析的代码面向的是更老的 PHP 版本,运行 PHPStan 2.0 的这台机器(或 CI 环境)也必须至少具备 PHP 7.4。注意这是"运行 PHPStan"的要求,与被分析项目的运行时 PHP 版本无关——后者由 PHPStan 的phpVersion参数控制。

二、最终用户升级指南:三步走到 2.0

2.1 第一步:先升到最新 PHPStan 1.12 并开启 Bleeding Edge

官方升级指南 给出的核心策略是不要直接跳到 2.0,而是先升到最新的 PHPStan 1.12 release,并开启Bleeding Edge。Bleeding Edge 是 PHPStan 的"预览通道":2.0 会对所有用户强制开启的新规则和新行为,在 1.12 中可以通过该开关提前启用,从而让你在 1.x 时代就把未来要面对的报错全部暴露出来。

在本仓库中,这一机制有直接对应物:根目录的 phpstan.neon 末尾以includes形式引用了phar://phpstan.phar/conf/bleedingEdge.neon。也就是说,本项目已经以 Bleeding Edge 方式运行 PHPStan,这正是 UPGRADING.md 推荐的升级前姿态。同时,项目通过 tools/phpstan 这个 Composer 生成的代理脚本调用phpstan.phar,并额外安装了phpstan-strict-rules等扩展(见tools/.phpstan/vendor/phpstan/目录),与官方建议的"在最新 1.12.x 上把构建跑到全绿"的工作流一致。

2.2 第二步:安装并启用 deprecation-rules

升级前还必须安装并启用phpstan/phpstan-deprecation-rules(文档原文)。这个扩展会把你代码中所有即将在 2.0 失效的旧 API 用法标记为弃用错误,是"提前扫雷"的关键工具。

2.3 第三步:升级 composer.json 并更新依赖

当你基于"最新 PHPStan 1.12.x + Bleeding Edge + 无任何弃用警告"拿到全绿构建后,就可以在composer.json中把相关依赖统一抬到 2.0。官方给出的完整require-dev模板如下(原文档原文):

"require-dev": { "phpstan/phpstan": "^2.0", "phpstan/phpstan-deprecation-rules": "^2.0", "phpstan/phpstan-doctrine": "^2.0", "phpstan/phpstan-nette": "^2.0", "phpstan/phpstan-phpunit": "^2.0", "phpstan/phpstan-strict-rules": "^2.0", "phpstan/phpstan-symfony": "^2.0", "phpstan/phpstan-webmozart-assert": "^2.0", ... }

除了第一方扩展,所有第三方 PHPStan 扩展也要同步升级到兼容 2.0 的版本。修改完composer.json后,运行:

composer update 'phpstan/*' -W

-W让 Composer 允许同时升级依赖链中的相关包,避免新旧版本混装。

官方特别强调:任何处于 PHPStan 1.12 的项目都应该能够升级到 2.0。至于升级后新冒出来的报错,你可以逐条消化,也可以干脆全部丢进 baseline(基线文件),两者都被官方认可。

三、代码分析行为的四大显著变化

升级到 2.0 后,即使配置不变,分析结果也会因为引擎行为变化而产生差异。官方在 Noteworthy changes to code analysis 中列出了四项:

  1. 按引用传递参数的处理增强:function foo(&$bar)这类场景下的类型推导与检查逻辑被重做,分析更精确。
  2. 内联 PHPDoc@var标签类型会被校验:/** @var string */ $x = ...;中标注的类型如果与实际推导类型矛盾,2.0 会报错,不再盲目采信。
  3. List 类型被强制:list<T>(索引连续、从 0 开始)语义在类型系统中被更严格地贯彻,数组类型的推导会区分"list"与普通数组。
  4. 恒为true的条件始终报告:之前只有开启phpstan-strict-rules才会报告的"条件恒真"问题,2.0 中默认一律报告。

四、被移除的配置项与官方替代写法

这一节是最终用户迁移的重头戏。多个旧参数被删除,官方给出的替代方案全部是"把旧行为收窄到ignoreErrors的错误标识符(identifier)"。

4.1checkMissingIterableValueType→missingType.iterableValue

旧参数checkMissingIterableValueType被移除。官方强烈建议为数组补齐元素类型标注(typehint)。如果你暂时想继续忽略"数组缺元素类型"的报错,就在ignoreErrors中按错误标识符屏蔽(原文档示例):

parameters: ignoreErrors: - identifier: missingType.iterableValue

4.2checkGenericClassInNonGenericObjectType→missingType.generics

同理,旧参数checkGenericClassInNonGenericObjectType被移除,官方强烈建议为泛型类补齐类型参数。想继续忽略时使用(原文档示例):

parameters: ignoreErrors: - identifier: missingType.generics

注意这里与 4.1 的语法一致:identifier精确匹配错误标识符,只有"该标识符对应的错误"被屏蔽,其余错误不受影响——这正是 2.0 推荐用标识符取代整条错误消息正则的原因。

4.3checkAlwaysTrue*系列:行为被固化

以下四个选项被整体移除,因为 2.0 中它们的语义恒等于true(原文档列表):

  • checkAlwaysTrueCheckTypeFunctionCall
  • checkAlwaysTrueInstanceof
  • checkAlwaysTrueStrictComparison
  • checkAlwaysTrueLooseComparison

也就是说,"instanceof恒真""严格比较恒真"等场景现在是默认检查项,配置里不需要也再无法显式开启。

4.4excludes_analyse→excludePaths

旧参数excludes_analyse被删除,统一由excludePaths承担(原文档说明)。如果你的配置还在写excludes_analyse,迁移时直接改名为excludePaths即可,语义等价。

4.5excludePaths/ignoreErrors的路径规则收紧

这是最容易踩坑的破坏性变更:excludePaths和ignoreErrors中的路径必须是一个真实存在的文件路径,或一个 fnmatch 通配模式(原文档说明)。

如果你的排除路径当前可能不存在、但希望保留在配置里,就给该条目追加(?)后缀:

parameters: excludePaths: - tests/*/data/* - src/broken - node_modules (?) # optional path, might not exist

(?)意为"可选路径,可能不存在",PHPStan 不会因为该路径缺失而报"未匹配"警告。

ignoreErrors中的情况则不同:不支持(?)后缀。如果你要在ignoreErrors里忽略某个可能不存在的路径下的错误,请改用全局开关reportUnmatchedIgnoredErrors: false:

parameters: reportUnmatchedIgnoredErrors: false

五、第一方扩展的配置变更

如果你使用了 PHPStan 官方生态的扩展,2.0 一并收紧了它们的配置参数(原文档列表):

  • phpstan-doctrine:
    • 移除searchOtherMethodsForQueryBuilderBeginning(扩展现在恒等于该值被设为true的行为);
    • 移除queryBuilderFastAlgorithm(扩展现在恒等于该值被设为false的行为)。
  • phpstan-symfony:
    • 移除所有带下划线的旧选项名,统一改为驼峰式:
    • container_xml_path→containerXmlPath
    • constant_hassers→constantHassers
    • console_application_loader→consoleApplicationLoader

六、最终用户视角的次要向后不兼容变更

以下配置参数在 2.0 中被清理(原文档清单),迁移时如果配置里还在使用,需要逐一处理:

被移除/变更项处理方式
cache.nodesByFileCountMax删除(从未生效的未用参数)
memoryLimitFile删除(未用参数)
disableRuntimeReflectionProvider功能开关删除(未用)
staticReflectionClassNamePatterns删除(未用参数)
fixerTmpDir改用pro.tmpDir
tempResultCachePath改用resultCachePath
additionalConfigFiles必须是 list(数组)类型

七、扩展开发者升级指南

如果你维护 PHPStan 扩展(自定义规则、动态返回类型扩展、类型扩展等),请先接受官方的一条强烈建议(原文档 NOTE):在扩展的下一个主版本中切换到 PHPStan 2.0,不要试图用同一份扩展代码同时兼容 1.x 与 2.x。比较现实的做法是:先在现有主版本内,用"PHPStan + phpstan-deprecation-rules + Bleeding Edge"分析你自己的扩展代码,解决所有弃用告警,尽量逼近 2.0 兼容;最终一步在composer.json中改为"phpstan/phpstan": "^2.0"并发布新的主版本。

7.1 底层依赖双升级:php-parser v5 与 phpdoc-parser v2

PHPStan 2.0 将 AST 解析器升级为nikic/php-parser v5。最值得注意的表示变化是throw语句(原文档说明):

  • 旧版:独立语句throw $e;用Stmt\Throw_节点表示;表达式内(如$x ?? throw $e)用Expr\Throw_。
  • 新版:Stmt\Throw_类被删除,throw $e;现在是一个包含Expr\Throw_的Stmt\Expression。

如果你的自定义规则通过遍历 AST 识别 throw 语句,必须按新结构重写 visitor 逻辑。

同时 PHPDoc 解析层升级为phpstan/phpdoc-parser v2,凡是直接依赖 PHPDoc AST 的扩展都要重新编译/适配。

7.2 自定义规则:字符串错误不再被支持,必须用 RuleErrorBuilder

2.0 中,自定义规则直接返回纯字符串数组作为错误的写法被移除,且错误必须携带identifier(原文档说明)。

之前(不再支持):

return ['My error'];

之后(推荐):

return [ RuleErrorBuilder::message('My error') ->identifier('my.error') ->build(), ];

标识符命名空间惯例是"厂商名.错误名"(如上例my.error),它让用户能够像第 4 节那样通过ignoreErrors.identifier精确屏蔽错误,也能让错误被 PHPStan 更好地聚合与解释。

7.3 弃用instanceof *Type:改用Type接口方法

官方明确反对在自定义扩展中通过$type instanceof XxxType判断类型,理由是这无法处理UnionType等复合类型。2.0 中这种写法被正式弃用,应改用Type接口上的方法(如Type::getArrays()、Type::isConstantValue()、Type::isCallable()等),这些方法内部已经处理了联合类型展开。

7.4ParametersAcceptorSelector::selectSingle()被移除

动态返回类型扩展中常用的selectSingle()被删除,应改用selectFromArgs(),它能结合调用点的实参和$scope选出更精确的变体(原文档示例):

$defaultReturnType = ParametersAcceptorSelector::selectFromArgs( $scope, $functionCall->getArgs(), $functionReflection->getVariants() )->getReturnType();

而如果你正在分析函数/方法体本身,不要再用selectFromArgs(),而是直接从反射对象上取getParameters()和getReturnType()。适用于以下节点类型:

  • InClassMethodNode::getMethodReflection()
  • InFunctionNode::getFunctionReflection()
  • FunctionReturnStatementsNode::getFunctionReflection()
  • MethodReturnStatementsNode::getMethodReflection()
  • Scope::getFunction()

之前:

$function = $node->getFunctionReflection(); $returnType = ParametersAcceptorSelector::selectSingle($function->getVariants())->getReturnType();

之后:

$returnType = $node->getFunctionReflection()->getReturnType();

7.5TypeSpecifier::create()与SpecifiedTypes构造参数变更

TypeSpecifier::create()现在只接受四个必填参数(原文档说明):

  • Expr $expr
  • Type $type
  • TypeSpecifierContext $context
  • Scope $scope

之前通过create()设置的$overwrite与$rootExpr,改为在返回的SpecifiedTypes对象上调用setAlwaysOverwriteTypes()与setRootExpr()。注意SpecifiedTypes是不可变对象,这两个 setter 返回的是新实例。

SpecifiedTypes构造函数同样收紧,现在只接受:

  • array $sureTypes
  • array $sureNotTypes

7.6ConstantArrayType不再继承ArrayType

类型层级发生了结构性变化:ConstantArrayType不再是ArrayType的子类(原文档说明)。Type::getArrays()现在返回list<ArrayType|ConstantArrayType>。由于instanceof ArrayType本身已被弃用(见 7.3),这一变更的实际冲击有限——正确做法是改用Type::getArrays()后逐个区分。

7.7TypeSpecifier::specifyTypesInCondition()移除$rootExpr

该方法不再接受Expr $rootExpr参数。需要修改根表达式时,对返回的SpecifiedTypes调用setRootExpr()(同样返回新对象)。

7.8 AST 节点属性parent/previous/next被移除

2.0 中,AST 节点上的parent、previous、next三个属性不再可用。如果你的自定义规则依赖它们回溯 AST 结构,需要改用 PHPStan 提供的替代机制(预处理后的节点包装)。

7.9 移除scopeClass配置参数

自定义 Scope 类的方式被废弃。官方替代方案是实现PHPStan\Type\ExpressionTypeResolverExtension接口并注册为服务,在扩展中为表达式提供类型解析逻辑。

7.10 移除PHPStan\Broker\Broker

老牌入口Broker被移除,统一使用PHPStan\Reflection\ReflectionProvider(原文档说明):

  • BrokerAwareExtension一并删除——在扩展构造函数中直接请求ReflectionProvider;
  • 测试侧:PHPStanTestCase::createBroker()改为PHPStanTestCase::createReflectionProvider()。

7.11 List 类型对所有人启用

AccessoryArrayListType的以下静态方法被移除(原文档说明):

  • isListTypeEnabled()
  • setListTypeEnabled()
  • intersectWith()

原来的AccessoryArrayListType::intersectWith($type)写法,改为:

TypeCombinator::intersect($type, new AccessoryArrayListType())

7.12 其他扩展开发相关的破坏性变更清单

以下是 UPGRADING.md 中剩余的全部次要 BC 破坏,按主题归纳:

类与接口层级

  • 原标记@final的类在 2.0 中真正变成final。
  • ConstantType接口被移除,改用Type::isConstantValue()。
  • 类常量反射重构:ClassConstantReflection更名为RealClassConstantReflection,ConstantReflection接口更名/新设为ClassConstantReflection,GlobalConstantReflection更名为ConstantReflection。
  • *WithPhpDocs系列接口全面更名为Extended*:ParametersAcceptorWithPhpDocs→ExtendedParametersAcceptor、ParameterReflectionWithPhpDocs→ExtendedParameterReflection、FunctionVariantWithPhpDocs→ExtendedFunctionVariant。
  • PHPStan\Node\ClassMethod不再是 AST 节点,需调用getNode()取回原始 AST 节点。
  • PHPStan\Node\Printer\Printer不再自动注入为PhpParser\PrettyPrinter\Standard,类型提示中必须使用PHPStan\Node\Printer\Printer。

方法签名与必填参数

  • MutatingScope::enterAnonymousFunction()与enterArrowFunction()的参数$callableParameters变为必填。
  • NodeScopeResolver::processStmtNodes()的参数StatementContext $context变为必填。
  • TypehintHelper::decideTypeFromReflection()的$selfClass不再接受string。
  • ClassPropertyNode::getNativeType()返回类型从 AST 节点改为Type|null。
  • Type::getProperty()现在返回ExtendedPropertyReflection。
  • FunctionReflection::isFinal()被移除。

类型系统方法迁移

  • 大小比较类方法要求显式传入PhpVersion:Type::getSmallerType()、getSmallerOrEqualType()、getGreaterType()、getGreaterOrEqualType()、isSmallerThan()、isSmallerThanOrEqual();CompoundType::isGreaterThan()、isGreaterThanOrEqual()同理。
  • Type::isClassStringType()更名为Type::isClassString()。
  • ConstantArrayType构造参数收紧:$isList只能传TrinaryLogic(不再接受bool),$nextAutoIndexes只能传non-empty-list<int>(不再接受int)。
  • ArrayType移除generalizeKeys()、count()(改用Type::getArraySize())、castToArrayKeyType()(改用Type::toArrayKey())。
  • ConstantArrayType移除isEmpty()(改用isIterableAtLeastOnce()->no())、getNextAutoIndex()、generalizeToArray()、removeLast()/removeFirst()/reverse()/chunk()/slice()(分别改用Type::popArray()、shiftArray()、reverseArray()、chunkArray()、sliceArray())、findTypeAndMethodName()(改用findTypeAndMethodNames())。
  • Type::accepts()与CompoundType::isAcceptedBy()返回类型从TrinaryLogic改为AcceptsResult;Type::isSuperTypeOf()、CompoundType::isSubTypeOf()、TemplateType::isValidVariance()返回IsSuperTypeOfResult。
  • RuleLevelHelper::accepts()返回类型从bool改为RuleLevelHelperAcceptsResult。
  • Scope::isSpecified()移除,改用hasExpressionType();Scope::doNotTreatPhpDocTypesAsCertain()移除,改用getNativeType()。
  • UnionType::pickTypes()移除,改用pickFromTypes()。
  • GenericTypeVariableResolver移除,改用Type::getTemplateType()。
  • ReflectionProvider::supportsAnonymousClasses()移除(所有反射提供器都支持匿名类)。
  • acceptsNamedArguments()在FunctionReflection、ExtendedMethodReflection、CallableParametersAcceptor中返回TrinaryLogic而非bool。
  • 不应被缓存序列化的对象上移除__set_state()。

TypeUtils 瘦身

TypeUtils的大量静态方法被移除,全部迁移到Type接口方法:

移除的 TypeUtils 方法替代方法
getArrays()/getAnyArrays()Type::getArrays()
getConstantArrays()/getOldConstantArrays()Type::getConstantArrays()
getConstantStrings()Type::getConstantStrings()
getConstantTypes()/getAnyConstantTypes()Type::isConstantValue()/Type::generalize()
generalizeType()Type::generalize()
getDirectClassNames()Type::getObjectClassNames()
getConstantScalars()Type::isConstantScalarValue()/Type::getConstantScalarTypes()
getEnumCaseObjects()Type::getEnumCases()
containsCallable()Type::isCallable()

反射相关方法迁移

  • ClassReflection::getFileNameWithPhpDocs()→getFileName()。
  • AnalysisResult::getInternalErrors()→getInternalErrorObjects()。
  • ConstantReflection::getValue()→getValueExpr()(从Expr取Type用Scope::getType()或InitializerExprTypeResolver::getType())。
  • PropertyTag::getType()→getReadableType()/getWritableType()。
  • RegexArrayShapeMatcher::matchType()→matchExpr()。
  • PHPStanTestCase::$useStaticReflectionProvider移除;getReflectors()改为getReflector()。
  • LevelsTestCase::dataTopics()数据提供者改为 static。

八、结合本仓库:2.0 时代配置的实战场

最后,看看 phpstan.neon 这份真实存在于本仓库的配置,它是 2.0 风格配置的活样本:

parameters: level: 10 paths: - src - tests checkTooWideReturnTypesInProtectedAndPublicMethods: true reportAlwaysTrueInLastCondition: true reportPossiblyNonexistentConstantArrayOffset: true reportPossiblyNonexistentGeneralArrayOffset: true treatPhpDocTypesAsCertain: false strictRules: allRules: false booleansInConditions: true closureUsesThis: true disallowedBacktick: true disallowedEmpty: true disallowedImplicitArrayCreation: true disallowedLooseComparison: true disallowedShortTernary: true illegalConstructorMethodCall: true matchingInheritedMethodNames: true noVariableVariables: true numericOperandsInArithmeticOperators: true overwriteVariablesWithLoop: true requireParentConstructorCall: true strictArrayFilter: true strictFunctionCalls: true switchConditionsMatchingType: true uselessCast: true ergebnis: allRules: false final: enabled: true classesNotRequiredToBeAbstractOrFinal: privateInFinalClass: enabled: true includes: - phar://phpstan.phar/conf/bleedingEdge.neon

几点值得注意:

  • reportAlwaysTrueInLastCondition等选项的存在,正对应第 3 节"恒真条件"在 2.0 中被固化为默认行为的方向——这类配置在 2.0 中会被并入默认检查。
  • includes直接加载bleedingEdge.neon,与本仓库 vendor 目录下同时安装的phpstan-strict-rules(见tools/.phpstan/vendor/phpstan/phpstan-strict-rules/)共同构成高严格度检查链。
  • treatPhpDocTypesAsCertain: false与 2.0"内联@var标签类型将被校验"的新行为相呼应:PHPDoc 不再是"说什么信什么",必须与实际推导一致。
  • 被分析对象src/与tests/(如 src/Runtime.php、src/Console.php、tests/RuntimeTest.php)本身就是大量使用运行时探测 API 的代码,其 CI 中运行 PHPStan level 10,从实践侧验证了升级路径的可行性。

升级到 2.0 的总体心法可以概括为:先在 1.12 + Bleeding Edge 下把所有新行为"剧透"一遍并处理干净,再切换依赖版本;配置层面把旧参数翻译成ignoreErrors标识符与新命名;扩展层面按本文 7.12 的清单逐项改 API 并发布新主版本。遵循这条路径,从 1.x 到 2.0 的迁移是可控、可回退、可逐步验证的。

  • 开发工具
  • 后端

【免费下载链接】environment

Provides functionality that helps writing PHP code that has runtime-specific execution paths

项目地址:https://gitcode.com/gh_mirrors/en/environment
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 11:57:45

中职计算机基础考试操作题全攻略:从文件管理到Excel实战

这些年我一直在带中职计算机基础这门课&#xff0c;每年期中期末都会看到一批学生栽在同一类问题上&#xff1a;选择题背得很熟&#xff0c;一上机操作就手忙脚乱。所以这篇笔记2&#xff0c;我打算换一种整理思路——不再按教材章节罗列概念&#xff0c;而是按考场上的真实场景…

作者头像 李华
网站建设 2026/10/15 11:57:06

qBittorrent搜索插件实战:安装调试与自写脚本

简介&#xff1a;该资源为qBittorrent下载工具配套的搜索插件合集&#xff0c;面向使用qBittorrent进行BT种子检索与下载的用户。压缩包内共44个文件&#xff0c;均为Python脚本&#xff0c;涵盖学术资源&#xff08;academictorrents&#xff09;、电影资源&#xff08;yts、y…

作者头像 李华
网站建设 2026/10/15 11:56:32

LVM命令手册:PV、VG、LV三层操作与在线扩容实战指南

1. 为什么LVM值得单独整理一份命令手册刚接手服务器运维那会儿&#xff0c;我最怕的就是磁盘空间告警。业务数据一天天涨&#xff0c;/data分区眼瞅着就要满&#xff0c;传统的分区方式要么停机加盘再重新分区&#xff0c;要么用软链接把新盘挂到某个子目录下凑合&#xff0c;时…

作者头像 李华
网站建设 2026/10/15 11:56:11

批处理脚本实战:从基础语法到自动化运维技巧

批处理文件很多人觉得是“古董技术”&#xff0c;命令行里敲几条命令还行&#xff0c;写成脚本就头大。但实际工作中&#xff0c;批量改文件名、定时清理日志、一键部署环境、自动备份数据&#xff0c;这些重复劳动用bat处理起来特别快。我这些年零零散散写了几百个批处理脚本&…

作者头像 李华
网站建设 2026/10/15 11:55:48

defuddle 中 Markdown 图片 alt 文本的方括号转义与安全转换机制

后端 【免费下载链接】defuddle Get the main content of any page as Markdown. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/de/defuddle 点击查看 免费下载 导读 本文围绕 defuddle 项目的 security--markdown-image-escaping fixture 展开&#xff0c;讲解当 H…

作者头像 李华
网站建设 2026/10/15 11:55:40

重卡变身“移动储能”入网、V2G计量标准落地、金冠签19.8亿出海大单:补能进入“重卡入网+全球出海”时代

浙江首次开展新能源重卡与电网互动响应&#xff0c;重卡充电站接入虚拟电厂、参与市场化填谷&#xff0c;最大响应负荷4.76万千瓦&#xff1b;金华10余座重卡充电站集体参与电力市场化响应&#xff1b;国家发改委"十五五"规划提出虚拟电厂最大调节能力超5000万千瓦&a…

作者头像 李华