PhpStorm 高级元数据
除了内置的“代码感知”功能外,PhpStorm 还依赖于代码的外部知识,这些知识以PHP 存根和特殊的高级元数据文件的形式出现。
虽然存根涵盖标准 PHP 库组件和通用扩展,但元数据文件可用于根据您自己的需要或项目要求扩展 PhpStorm 功能。基本元数据文件.phpstorm.meta.php捆绑在 PHP 存根包中,位于meta文件夹中。
在项目中创建元数据文件
执行以下任一操作:
创建一个php文件并将其命名为.phpstorm.meta.php。您可以创建多个此类文件并将它们存储在项目中的不同位置。PhpStorm 将从他们那里收集并合并所有信息。
创建一个目录并将其命名为.phpstorm.meta.php。在此目录中,您可以存储任意数量的元数据文件并任意命名。
在元文件中,声明一个
PHPSTORM_META
命名空间并提供元数据指令。命名空间 PHPSTORM_META { //元数据指令 }元数据指令指定应如何处理某个函数或方法。指令被编写为常规的 PHP 代码,允许使用现有的代码编辑器功能,例如代码完成 Ctrl+Space、导航和用法搜索、重构等。
导航到元数据指令
如果通过expectedArguments、exitPoint或override指令更改函数的行为,PhpStorm 会在函数声明旁边的编辑器装订线中显示图标。
单击该图标可导航到元文件中的相应指令。
定义方法接受的参数
该expectedArguments
指令指示 PhpStorm 某个函数接受某组参数。该指令是通过提供您正在使用的函数、参数的从零开始的索引以及实际的期望值集来指定的,如下所示:
,
您可以通过逗号或管道|
按位运算符枚举预期的参数。前者用于期望值集中的单个值的函数,而后者用于期望常量位掩码的函数,例如json_encode。
举个例子,假设你正在实现一个基于symfony/console组件的控制台命令。有时会有你想传递给命令的参数。在此示例中,Symfony\Component\Console\Command::configure()
正在实现一个方法:
有了expectedArguments
适当的位置,您可以建议 PhpStorm 在InputArgument::*
这里期待常量。为此,将以下行添加到元数据文件:
现在,当您调用代码完成Ctrl+Space时,添加的常量会显示在建议列表中:
定义可能的返回值
该expectedReturnValues
指令指示 PhpStorm,它为某个函数或方法返回值。该指令的指定与expectedArguments类似:您为其提供一个函数和一组实际值(这些集合也可以通过ArgumentsSet注册),如下所示:
指定函数后,PhpStorm 将为条件语句中的函数和静态方法调用提供代码补全。
例如,假设您正在使用可用的PSR-7 兼容客户端之一执行 HTTP 请求,结果,您将获得一个$response
实现\Psr\Http\Message\ResponseInterface的类的对象。然后,您可能想要检查状态代码并执行一些合适的操作。指示ResponseInterface::getStatusCode()
返回一组 HTTP 状态代码的 PhpStorm 可能会很方便:
当您Ctrl+Space在条件语句中调用代码完成时,添加的常量将在建议列表中可用:
创建命名的参数集或返回值
对于某些函数,可能的参数值列表可能非常大。更重要的是,不同的函数可以接受相同的值集。如果您提供此类函数的预期参数列表,元数据文件将变得过大。它还将包含重复的条目,维护它所需的工作量也将增加一倍。
为了处理这个问题,在元数据文件中,您可以使用两个指令:registerArgumentsSet
和argumentsSet
. 该registerArgumentsSet
指令接受两个参数:参数集的任意名称和该集中包含的实际值列表。值的指定方式与预期参数列表相同:根据您正在使用的函数或方法,您可以通过逗号,
或管道|
位运算符枚举它们。
要注册参数集,请按如下方式指定指令:
注册了一组参数后,您可以expectedArguments
使用argumentsSet
指令从内部引用它:
例如,考虑ini_get
和ini_set
函数都接受同一组php.ini 指令。
您可以按如下方式注册参数集:
完成后,您可以在expectedArguments
forini_get
和中引用该集合ini_set
:
定义退出点
通过使用该exitPoint
指令,您可以明确指示 PhpStorm 指定的函数充当退出点。此类函数的调用被视为终止调用,类似于 PHP 内置exit或die函数的调用。该指令指定如下:
whereoptionalArguments
可以是字符串文字或类常量。如果提供了可选参数,则只有带有此参数的函数调用将被视为退出点。否则,将继续正常执行。
例如,考虑以下代码示例:
要将terminate('bar')
方法调用标记为退出点,请将以下行添加到元数据文件中:
结果,terminate
带有提供的参数的调用bar
将充当退出点。因此,该方法的最后一行run
将被视为不可访问:
定义方法的返回类型
在很多情况下,无法根据函数的代码本身清楚地推断出函数的返回类型。通过使用该override
指令,您可以显式指示 PhpStorm 指定的函数根据提供的参数返回特定类型的实体。
该指令指定如下:
哪里overrideDirective
可以是以下之一:
type:将函数的返回类型设置为传递参数的类型。
elementType:如果传递的参数是一个数组,则将函数的返回类型设置为数组中包含的元素的类型。
map:设置参数值和函数返回类型之间的任意映射。
使用参数的类型
该type
指令指示 PhpStorm 函数的返回类型与其参数的类型匹配。该指令指定如下:
whereargumentIndex
是参数的从零开始的索引,其类型应用作函数的返回类型。
例如,考虑以下代码示例:
最初,您不会在此表达式和类似表达式中获得代码完成:
您可以通过将以下行添加到元数据文件来解决此问题:
这样,您指示 PhpStormdoActionA()
方法的返回类型与其第一个参数的类型匹配,B
在我们的例子中是类。相应的代码完成条目变为可用:
使用数组元素的类型
该elementType
指令适用于接受数组作为参数的函数。该指令指示 PhpStorm 函数的返回类型与数组中包含的元素的类型相匹配。请注意,它仅适用于具有相同类型元素的数组。该指令指定如下:
whereargumentIndex
是包含数组的参数的从零开始的索引,该数组的元素类型用作函数的返回类型。
例如,考虑以下代码示例:
最初,您不会在此表达式和类似表达式中获得代码完成:
您可以通过将以下行添加到元数据文件来解决此问题:
这样,您指示 PhpStorm 如果将数组传递给doActionA()
,则此方法的返回类型与数组元素的类型匹配,B
在我们的例子中是类。相应的代码完成条目变为可用:
提供任意类型映射
该map
指令允许您在参数的值和函数的返回类型之间设置任意映射。通过使用该指令,您可以在 PhpStorm 中实现对工厂模式的通用支持,从而在使用常见的 PHP 框架(如 Magento、Doctrine、Kohana、ZF2 等)时获得编码帮助。该指令指定如下:
wherekey
是字符串文字、全局常量或类常量,并且value
是::class
常量或模式文字。在模式文字内,您可以使用@
将解析为所提供参数的文字值的符号。
例如,考虑以下代码示例。
通过使用map
元数据指令,您可以指示 PhpStorm,(new Factory())->get()
根据传递的参数预期返回类型。
传递字符串文字
"special"
传递字符串文字时,将\Exception
返回一个实例:
传递一个全局常量
myConst
传递全局常量时,AClass
返回一个实例:
传递类常量
当classConstant
传递类常量时,BClass
返回一个实例:
使用查找模式
@Class
查找模式允许解析AClass
是否传递了'A'
文字,或者是否BClass
传递'B'
了:
在 SQL 语言注入中为表名设置动态前缀
许多内容管理系统和框架支持使用在应用程序配置级别定义的表前缀。在代码中,表的名称由 SQL 字符串中的前缀标记指定。当应用程序的数据库层处理这些字符串时,这些名称将替换为包含前缀的实际表名。
通过使用sql_injection_subst
metadata 指令,您可以设置在注入的 SQL 字符串中用实际前缀替换前缀标记的规则。因此,PhpStorm 将为数据库表的名称提供代码补全,并在运行 SQL 查询时使用它们。
该指令指定如下:
考虑以下示例:数据库包含两个表app_users
和app_products
,它们使用app_
表前缀。在代码中,[prefix ]
和#__
前缀标记用于引用这些表。最初,注入的 SQL 字符串中的表名无法识别,因此无法对其进行代码完成。
要注册数据库前缀,请将以下内容添加到元数据文件中:
结果,PhpStorm 自动将前缀标记替换为实际前缀,并且表的名称变得可用: