PhpStorm 2021.3 Help

PhpStorm 高级元数据

除了内置的“代码感知”功能外,PhpStorm 还依赖于代码的外部知识,这些知识以PHP 存根和特殊的高级元数据文件的形式出现。

虽然存根涵盖标准 PHP 库组件和通用扩展,但元数据文件可用于根据您自己的需要或项目要求扩展 PhpStorm 功能。基本元数据文件.phpstorm.meta.php捆绑在 PHP 存根包中,位于meta文件夹中。

在项目中创建元数据文件

  1. 执行以下任一操作:

    • 创建一个php文件并将其命名为.phpstorm.meta.php。您可以创建多个此类文件并将它们存储在项目中的不同位置。PhpStorm 将从他们那里收集并合并所有信息。

    • 创建一个目录并将其命名为.phpstorm.meta.php。在此目录中,您可以存储任意数量的元数据文件并任意命名。

  2. 在元文件中,声明一个PHPSTORM_META命名空间并提供元数据指令。

    命名空间 PHPSTORM_META { //元数据指令 }

    元数据指令指定应如何处理某个函数或方法。指令被编写为常规的 PHP 代码,允许使用现有的代码编辑器功能,例如代码完成 Ctrl+Space导航用法搜索重构等。

    元文件中的代码完成
  • 如果通过expectedArgumentsexitPointoverride指令更改函数的行为,PhpStorm 会元数据图标在函数声明旁边的编辑器装订线中显示图标。

    单击该元数据图标图标可导航到元文件中的相应指令。

    编辑器装订线中的元指标

定义方法接受的参数

expectedArguments指令指示 PhpStorm 某个函数接受某组参数。该指令是通过提供您正在使用的函数、参数的从零开始的索引以及实际的期望值集来指定的,如下所示:

预期参数(函数FQN,argumentsIndex,...argumentsList);

,您可以通过逗号或管道| 按位运算符枚举预期的参数。前者用于期望值集中的单个值的函数,而后者用于期望常量位掩码的函数,例如json_encode

举个例子,假设你正在实现一个基于symfony/console组件的控制台命令。有时会有你想传递给命令的参数。在此示例中,Symfony\Component\Console\Command::configure()正在实现一个方法:

设置预期参数之前的代码完成

有了expectedArguments适当的位置,您可以建议 PhpStorm 在InputArgument::*这里期待常量。为此,将以下行添加到元数据文件:

预期参数(\Symfony\Component\Console\Command\Command::addArgument(),1,\Symfony\Component\Console\Input\InputArgument::可选,\Symfony\Component\Console\Input\InputArgument::REQUIRED,\Symfony \Component\Console\Input\InputArgument::IS_ARRAY );

现在,当您调用代码完成Ctrl+Space时,添加的常量会显示在建议列表中:

设置预期参数之前的代码完成

定义可能的返回值

expectedReturnValues指令指示 PhpStorm,它为某个函数或方法返回值。该指令的指定与expectedArguments类似:您为其提供一个函数和一组实际值(这些集合也可以通过ArgumentsSet注册),如下所示:

预期返回值(函数FQN,...参数列表);

指定函数后,PhpStorm 将为条件语句中的函数和静态方法调用提供代码补全。

json_last_error 的元内容和代码完成

例如,假设您正在使用可用的PSR-7 兼容客户端之一执行 HTTP 请求,结果,您将获得一个$response实现\Psr\Http\Message\ResponseInterface的类的对象。然后,您可能想要检查状态代码并执行一些合适的操作。指示ResponseInterface::getStatusCode()返回一组 HTTP 状态代码的 PhpStorm 可能会很方便:

命名空间 PHPSTORM_META { expectedReturnValues(\Psr\Http\Message\ResponseInterface::getStatusCode(), \Symfony\Component\HttpFoundation\Response::HTTP_OK, \Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST, \Symfony\Component\HttpFoundation\响应::HTTP_INTERNAL_SERVER_ERROR); }

当您Ctrl+Space在条件语句中调用代码完成时,添加的常量将在建议列表中可用:

具有预期返回值的 http 请求的代码完成

创建命名的参数集或返回值

对于某些函数,可能的参数值列表可能非常大。更重要的是,不同的函数可以接受相同的值集。如果您提供此类函数的预期参数列表,元数据文件将变得过大。它还将包含重复的条目,维护它所需的工作量也将增加一倍。

为了处理这个问题,在元数据文件中,您可以使用两个指令:registerArgumentsSetargumentsSet. 该registerArgumentsSet指令接受两个参数:参数集的任意名称和该集中包含的实际值列表。值的指定方式与预期参数列表相同:根据您正在使用的函数或方法,您可以通过逗号,或管道| 位运算符枚举它们。

要注册参数集,请按如下方式指定指令:

registerArgumentsSet('argumentsSetName', ...argumentsList);

注册了一组参数后,您可以expectedArguments使用argumentsSet指令从内部引用它:

预期参数(函数FQN,0,参数集('argumentsSetName'));

例如,考虑ini_getini_set函数都接受同一组php.ini 指令

您可以按如下方式注册参数集:

registerArgumentsSet('ini_values', ...iniValuesList);

完成后,您可以在expectedArgumentsforini_get和中引用该集合ini_set

预期参数(\ini_get(), 0, argumentsSet('ini_values')); 预期参数(\ini_set(), 0, argumentsSet('ini_values'));

定义退出点

通过使用该exitPoint指令,您可以明确指示 PhpStorm 指定的函数充当退出点。此类函数的调用被视为终止调用,类似于 PHP 内置exitdie函数的调用。该指令指定如下:

exitPoint(functionFQN([optionalArguments]));

whereoptionalArguments可以是字符串文字或类常量。如果提供了可选参数,则只有带有此参数的函数调用将被视为退出点。否则,将继续正常执行。

例如,考虑以下代码示例:

类应用程序{公共函数终止($param){退出();} 公共函数 run() { $this->terminate('foo'); 回声“你好”;$this->terminate('bar'); 回声“世界!”;} }

要将terminate('bar')方法调用标记为退出点,请将以下行添加到元数据文件中:

exitPoint(Application::terminate('bar'));

结果,terminate带有提供的参数的调用bar将充当退出点。因此,该方法的最后一行run将被视为不可访问:

退出点方法调用

定义方法的返回类型

在很多情况下,无法根据函数的代码本身清楚地推断出函数的返回类型。通过使用该override指令,您可以显式指示 PhpStorm 指定的函数根据提供的参数返回特定类型的实体。

该指令指定如下:

覆盖(函数FQN,覆盖指令);

哪里overrideDirective可以是以下之一:

  • type:将函数的返回类型设置为传递参数的类型。

  • elementType:如果传递的参数是一个数组,则将函数的返回类型设置为数组中包含的元素的类型。

  • map:设置参数值和函数返回类型之间的任意映射。

使用参数的类型

type指令指示 PhpStorm 函数的返回类型与其参数的类型匹配。该指令指定如下:

覆盖(函数FQN,类型(argumentIndex));

whereargumentIndex是参数的从零开始的索引,其类型应用作函数的返回类型。

例如,考虑以下代码示例:

类 A { public function doActionA($a) { return $a; } } 类 B { 公共函数 doActionB($b) { 返回 $b; } }

最初,您不会在此表达式和类似表达式中获得代码完成:

方法返回类型未被覆盖

您可以通过将以下行添加到元数据文件来解决此问题:

覆盖(A::doActionA(0),类型(0));

这样,您指示 PhpStormdoActionA()方法的返回类型与其第一个参数的类型匹配,B在我们的例子中是类。相应的代码完成条目变为可用:

方法返回类型被覆盖

使用数组元素的类型

elementType指令适用于接受数组作为参数的函数。该指令指示 PhpStorm 函数的返回类型与数组中包含的元素的类型相匹配。请注意,它仅适用于具有相同类型元素的数组。该指令指定如下:

覆盖(函数FQN,元素类型(argumentIndex));

whereargumentIndex是包含数组的参数的从零开始的索引,该数组的元素类型用作函数的返回类型。

例如,考虑以下代码示例:

类 A { public function doActionA($a) { return $a; } } 类 B { 公共函数 doActionB($b) { 返回 $b; } } $B1 = 新 B(); $B2 = 新 B(); $arrB = [$B1, $B2];

最初,您不会在此表达式和类似表达式中获得代码完成:

方法返回元素类型未被覆盖

您可以通过将以下行添加到元数据文件来解决此问题:

覆盖(A::doActionA(0), elementType(0));

这样,您指示 PhpStorm 如果将数组传递给doActionA(),则此方法的返回类型与数组元素的类型匹配,B在我们的例子中是类。相应的代码完成条目变为可用:

方法返回元素类型被覆盖

提供任意类型映射

map指令允许您在参数的值和函数的返回类型之间设置任意映射。通过使用该指令,您可以在 PhpStorm 中实现对工厂模式的通用支持,从而在使用常见的 PHP 框架(如 Magento、Doctrine、Kohana、ZF2 等)时获得编码帮助。该指令指定如下:

覆盖(函数FQN,地图([键=>值,...]));

wherekey是字符串文字、全局常量或类常量,并且value::class常量或模式文字。在模式文字内,您可以使用@将解析为所提供参数的文字值的符号。

例如,考虑以下代码示例。

定义('myConst', 'GlobalConstant'); 类工厂 { const classConstant = 'ClassConstant'; 公共函数 get($name) { 返回 $name; } } 类 AClass {} 类 BClass {} $result = (new Factory())->get();

通过使用map元数据指令,您可以指示 PhpStorm,(new Factory())->get()根据传递的参数预期返回类型。

传递字符串文字

"special"传递字符串文字时,将\Exception返回一个实例:

覆盖(\Factory::get(), map([ "special" => \Exception::class, ]));
通过文字覆盖的方法返回类型

传递一个全局常量

myConst传递全局常量时,AClass返回一个实例:

覆盖(\Factory::get(),地图([ \myConst => \AClass::class,]));
通过文字覆盖的方法返回类型

传递类常量

classConstant传递类常量时,BClass返回一个实例:

覆盖(\Factory::get(), map([ \Factory::classConstant => \BClass::class, ]));
通过文字覆盖的方法返回类型

使用查找模式

@Class查找模式允许解析AClass是否传递了'A'文字,或者是否BClass传递'B'了:

覆盖(\Factory::get(), map([ '' => '@Class' ]));
通过文字覆盖的方法返回类型

在 SQL 语言注入中为表名设置动态前缀

许多内容管理系统和框架支持使用在应用程序配置级别定义的表前缀。在代码中,表的名称由 SQL 字符串中的前缀标记指定。当应用程序的数据库层处理这些字符串时,这些名称将替换为包含前缀的实际表名。

通过使用sql_injection_substmetadata 指令,您可以设置在注入的 SQL 字符串中用实际前缀替换前缀标记的规则。因此,PhpStorm 将为数据库表的名称提供代码补全,并在运行 SQL 查询时使用它们。

该指令指定如下:

覆盖(sql_injection_subst(),地图([“前缀标记”=>“替换”]));}

考虑以下示例:数据库包含两个表app_usersapp_products,它们使用app_表前缀。在代码中,[prefix ]#__前缀标记用于引用这些表。最初,注入的 SQL 字符串中的表名无法识别,因此无法对其进行代码完成。

SQL注入中的未知表名

要注册数据库前缀,请将以下内容添加到元数据文件中:

覆盖(sql_injection_subst(),地图([“[前缀]”=>“app_”,“#__”=>“app_”]));;

结果,PhpStorm 自动将前缀标记替换为实际前缀,并且表的名称变得可用:

SQL注入中解析的表名

旧版元数据格式(已弃用)

\globalFactoryFunction('') => [ // (4) 也适用于函数 ], // 如果没有找到键,则在所有情况下都将其用作类型名称 ]; }
最后修改:2022 年 2 月 2 日