PhpStorm 高级元数据
除了内置的“代码感知”功能外,PhpStorm 还依赖于代码的外部知识,这些知识以 PHP stubs和特殊的高级元数据文件的形式存在。
虽然 stubs 覆盖了标准 PHP 库组件和常见扩展,但元数据文件可用于根据您的需求或项目要求扩展 PhpStorm 的功能。 基本元数据文件 .phpstorm.meta.php 包含在 PHP stubs 包中,并位于 元信息 文件夹中。
在项目中创建元数据文件
执行以下任意操作:
创建一个 php 文件并将其命名为 .phpstorm.meta.php 。 您可以创建多个这样的文件,并将它们存储在项目中的不同位置。 PhpStorm 将收集并合并其中的所有信息。
创建一个目录并将其命名为 .phpstorm.meta.php 。 在此目录中,您可以存储任意数量的元数据文件,并任意命名它们。
在元文件中,声明一个
PHPSTORM_META命名空间并提供元数据指令。namespace PHPSTORM_META { //metadata directives }元数据 指令指定应如何处理某个函数或方法。 指令以常规 PHP 代码的形式编写,这允许使用现有的代码编辑器功能,例如 代码补全 Ctrl+Space、 导航和 用法搜索、 重构等。

导航到元数据指令
如果函数的行为通过 expectedArguments、 exitPoint或 override指令被更改,PhpStorm 会在编辑器边栏的函数声明旁显示
图标。单击
图标以导航到元文件中的相应指令。

定义方法接受的参数
expectedArguments 指令告知 PhpStorm 某个函数接受一组特定的参数。 通过提供您正在处理的函数、参数的零基索引以及实际的预期值集合来指定指令,如下所示:
您可以通过逗号 , 或管道符 | 按位或运算符枚举预期参数。 前者用于期望从值集合中选择单个值的函数,而后者用于期望常量位掩码的函数,例如 json_encode。
例如,假设您正在基于 symfony/console组件实现一个 Console 命令。 有时会有一些参数需要传递给命令。 在此示例中,正在实现一个 Symfony\Component\Console\Command::configure() 方法:

通过 expectedArguments ,您可以建议 PhpStorm 在此处预期 InputArgument::* 常量。 为此,请将以下行添加到元数据文件中:
现在,当您调用代码补全 Ctrl+Space 时,添加的常量会显示在建议列表中:

定义可能的返回值
expectedReturnValues 指令告知 PhpStorm 某个函数或方法返回哪些值。 该指令的指定方式与 expectedArguments类似:您为其提供一个函数和实际值的集合(此类集合也可以通过 ArgumentsSet注册),如下所示:
指定函数后,PhpStorm 将在条件语句中为函数和静态方法调用提供代码补全。

例如,假设您正在使用一个可用的 PSR-7 兼容客户端执行 HTTP 请求,结果将获得一个实现 \Psr\Http\Message\ResponseInterface的类的 $response 对象。 然后,您可能希望检查状态码并执行一些适当的操作。 告知 PhpStorm ResponseInterface::getStatusCode() 返回一组 HTTP 状态码可能会很方便:
当您在条件语句中调用代码补全 Ctrl+Space 时,添加的常量会在建议列表中可用:

创建命名的参数集或返回值集
对于某些函数,可能的参数值列表可能非常大。 更重要的是,不同的函数可以接受相同的值集合。 如果您为此类函数提供 预期参数的列表,元数据文件将变得过于庞大。 它还会包含重复条目,并且维护所需的工作量也会加倍。
为了解决这个问题,在元数据文件中,您可以使用两个指令: registerArgumentsSet 和 argumentsSet。 registerArgumentsSet 指令接受两个参数:参数集的任意名称和该集中包含的实际值列表。 值的指定方式与 预期参数的列表相同:根据您正在处理的函数或方法,您可以通过逗号 , 或管道符 | 按位或运算符枚举它们。
要注册参数集,请按以下方式指定指令:
注册单个参数集后,您可以通过使用 argumentsSet 指令从 expectedArguments 中引用它:
例如,考虑 ini_get 和 ini_set 函数,它们都接受相同的 php.ini 指令集合。
您可以按以下方式注册参数集:
完成后,您可以从 expectedArguments 中引用此集合,用于 ini_get 和 ini_set:
定义退出点
通过使用 exitPoint 指令,您可以明确告知 PhpStorm 指定的函数充当退出点。 此类函数的调用被视为终止调用,类似于 PHP 内置的 exit或 die函数的调用。 指令的指定方式如下:
其中 optionalArguments 可以是字符串字面量或类常量。 如果提供了可选参数,则只有带有此参数的函数调用会被视为退出点。 否则,执行将正常继续。
例如,考虑以下代码示例:
要将 terminate('bar') 方法调用标记为退出点,请将以下行添加到元数据文件中:
结果是,带有 bar 参数的 terminate 调用将充当退出点。 运行 方法的最后一行因此将被视为不可达:

定义方法的返回类型
在许多情况下,无法根据函数本身的代码清楚地推断出函数的返回类型。 通过使用 override 指令,您可以明确告知 PhpStorm 指定的函数根据提供的参数返回某种类型的实体。
指令的指定方式如下:
其中:
functionFQN是函数或类方法的完全限定名称。__get()、__call()和__callStatic()魔术方法也受支持。overrideDirective是以下之一:type :将函数的返回类型设置为传递参数的类型。
elementType :如果传递的参数是数组,则将函数的返回类型设置为数组中包含的元素的类型。
map :在参数值和函数的返回类型之间设置任意映射。
使用参数的类型
type 指令告知 PhpStorm 函数的返回类型与其参数的类型匹配。 指令的指定方式如下:
其中 argumentIndex 是参数的零基索引,其类型应用作函数的返回类型。
例如,考虑以下代码示例:
最初,您不会在此类表达式中获得代码补全:

您可以通过将以下行添加到元数据文件中来解决此问题:
通过这种方式,您告知 PhpStorm doActionA() 方法的返回类型与其第一个参数的类型匹配,在我们的例子中是类 B。 相应的代码补全条目变得可用:

使用数组元素的类型
elementType 指令适用于接受数组作为参数的函数。 该指令告知 PhpStorm 函数的返回类型与数组中包含的元素的类型匹配。 请注意,它仅适用于具有相同类型元素的数组。 指令的指定方式如下:
其中 argumentIndex 是包含数组的参数的零基索引,其元素的类型用作函数的返回类型。
例如,考虑以下代码示例:
最初,您不会在此类表达式中获得代码补全:

您可以通过将以下行添加到元数据文件中来解决此问题:
通过这种方式,您告知 PhpStorm 如果将数组传递给 doActionA() ,则此方法的返回类型与数组元素的类型匹配,在我们的例子中是类 B。 相应的代码补全条目变得可用:

提供任意类型映射
map 指令允许您在参数值和函数的返回类型之间设置任意映射。 通过使用此指令,您可以在 PhpStorm 中实现对 工厂模式的通用支持,从而在使用常见 PHP 框架(如 Magento、Doctrine、Kohana、ZF2 等)时获得编码辅助。 指令的指定方式如下:
其中 key 是字符串字面量、全局常量或类常量, value 是 ::class 常量或模式字面量。 在模式字面量中,您可以使用 @ 符号,该符号将解析为提供的参数的字面值。 您还可以提供 联合类型 ,即由管道符 | 分隔的多个类型。
例如,请考虑以下代码示例。
通过使用 map 元数据指令,您可以告知 PhpStorm 根据传递的参数, (new Factory())->get() 预期的返回类型。 您还可以为通过 __call() 魔术方法调用的方法指定返回类型。
传递字符串字面量
当传递 "special" 字符串字面量时,将返回 \Exception 的实例:

传递全局常量
当传递 myConst 全局常量时,将返回 AClass 的实例:

传递类常量
当传递 classConstant 类常量时,将返回 BClass 的实例:

使用查找模式
@Class 查找模式允许在传递 'A' 字面量时解析 AClass ,或在传递 'B' 时解析 BClass:

为魔术方法构造动态返回类型
@Class 查找模式允许在调用 a() 方法时解析 AClass ,或在调用 b() 时解析 BClass:

使用联合类型
AClass|BClass 联合类型声明允许同时解析 AClass 和 BClass:

为 SQL 语言注入中的表名设置动态前缀
许多内容管理系统和框架支持使用表前缀,这些前缀在应用程序配置级别定义。 在代码中,表名在 SQL 字符串中通过前缀标记指定。 当应用程序的数据库层处理这些字符串时,此类名称将替换为包含前缀的实际表名。
通过使用 sql_injection_subst 元数据指令,您可以为 注入的 SQL 字符串设置将前缀标记替换为实际前缀的规则。 结果是,PhpStorm 将为数据库表名提供代码补全,并在 运行 SQL 查询时使用它们。
指令的指定方式如下:
请考虑以下示例:数据库包含两个表, app_users 和 app_products ,它们使用 app_ 表前缀。 在代码中, [prefix ] 和 #__ 前缀标记用于引用这些表。 最初,注入的 SQL 字符串中的表名未被识别,因此无法为它们提供代码补全。

要注册数据库前缀,请将以下内容添加到元数据文件中:
结果是,PhpStorm 会自动将前缀标记替换为实际前缀,并且表名变得可用:
