substpk/type-resolver

1.1 2017-02-04 10:35 UTC

This package is not auto-updated.

Last update: 2024-09-23 15:51:13 UTC


README

DocBlocks (PSR-5) 中关于类型的规范描述了各种关键字和特殊结构,同时也说明了如何将类的部分名称静态解析为完全限定类名 (FQCN)。

PSR-5 还引入了一种描述比类、接口和特性更深层元素的方法,称为完全限定结构元素名 (FQSEN)。使用这种方法,可以引用方法、属性和类常量,也可以引用函数和全局常量。

此包提供了两个解析器,它们可以

  1. 在解析任何部分类名的同时,返回一系列给定的表达式值对象,并且
  2. 在将任何部分结构元素名解析为完全限定结构元素名后,返回一个 FQSEN 对象。

安装

安装此库的最简单方法是使用 Composer,使用以下命令

$ composer require phpdocumentor/type-resolver

示例

准备好深入探索,不想阅读下面的所有文本?只需查阅 示例 文件夹,并检查您想完成哪种类型的操作。

关于类型和元素名称

此组件可以使用两种方式之一

  1. 解析一个类型或
  2. 解析一个完全限定结构元素名

这两个之间的主要区别在于它可以解析的东西的数量。

TypeResolver 可以解析

  • 一个 php 基本类型或伪基本类型,如字符串或 void(例如 @var string@return void)。

  • 一个复合类型,如字符串数组(例如 @var string[])。

  • 一个复合类型,如字符串或整数(例如 @var string|integer)。

  • 一个对象或接口,如 TypeResolver 类(例如 @var TypeResolver@var \phpDocumentor\Reflection\TypeResolver

    请注意,如果您想传递部分类名,则需要额外的步骤,请参阅 解析部分类和 FQSEN 章节以获取更多信息。

FqsenResolver 可以解析

  • 常量表达式(例如 @see \MyNamespace\MY_CONSTANT
  • 函数表达式(例如 @see \MyNamespace\myFunction()
  • 类表达式(例如 @see \MyNamespace\MyClass
  • 接口表达式(例如 @see \MyNamespace\MyInterface
  • 特性表达式(例如 @see \MyNamespace\MyTrait
  • 类常量表达式(例如 @see \MyNamespace\MyClass::MY_CONSTANT
  • 属性表达式(例如 @see \MyNamespace\MyClass::$myProperty
  • 方法表达式(例如 @see \MyNamespace\MyClass::myMethod()

解析类型

为了解析类型,您必须实例化类 \phpDocumentor\Reflection\TypeResolver 并调用其 resolve 方法,如下所示

$typeResolver = new \phpDocumentor\Reflection\TypeResolver();
$type = $typeResolver->resolve('string|integer');

在这个示例中,您将收到一个类 \phpDocumentor\Reflection\Types\Compound 的 Value Object,它有两个元素,一个是类型 \phpDocumentor\Reflection\Types\String_,另一个是类型 \phpDocumentor\Reflection\Types\Integer

此解析器的真正力量在于其将部分类名扩展为完全限定类名的功能;但为了做到这一点,我们需要一个额外的 \phpDocumentor\Reflection\Types\Context 类,它将向解析器通知给定表达式发生的命名空间以及哪些命名空间别名(或导入)适用。

解析 FQSEN

完全限定结构元素名称是对代码库中另一个元素的引用,可以使用\phpDocumentor\Reflection\FqsenResolver类的resolve方法来解析它,如下所示:

$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
$fqsen = $fqsenResolver->resolve('\phpDocumentor\Reflection\FqsenResolver::resolve()');

在这个示例中,我们解析了一个完全限定的结构元素名称(意味着它包括完整的命名空间、类名和元素名),并接收了一个类型为\phpDocumentor\Reflection\Fqsen的值对象。

这个解析器的真正强大之处在于它能够将部分元素名称扩展为完全限定的结构元素名称;但为了做到这一点,我们需要一个额外的\phpDocumentor\Reflection\Types\Context类,它将告知解析器给定表达式发生的命名空间以及哪些命名空间别名(或导入)适用。

解析部分类和结构元素名称

这个库最出色的功能之一是它知道如何将部分类名解析为完全限定的类名。

例如,你有这个文件

<?php
namespace My\Example;

use phpDocumentor\Reflection\Types;

class Classy
{
    /**
     * @var Types\Context
     * @see Classy::otherFunction()
     */
    public function __construct($context) {}
    
    public function otherFunction(){}
}

假设你想要解析(并扩展)@var标签中的类型和@see标签中的元素名称。为了让解析器知道如何扩展部分名称,你必须通过实例化一个名为\phpDocumentor\Reflection\Types\Context的新类,并提供命名空间及其别名来实现这一点。

创建上下文

你可以手动创建一个上下文,如下所示:

$context = new \phpDocumentor\Reflection\Types\Context(
    '\My\Example', 
    [ 'Types' => '\phpDocumentor\Reflection\Types']
);

或者通过使用\phpDocumentor\Reflection\Types\ContextFactory根据反射器对象或提供你想要提取的命名空间以及给定类型表达式发生的源代码文件来实例化一个新的上下文。

$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
$context = $contextFactory->createFromReflector(new ReflectionMethod('\My\Example\Classy', '__construct'));

或者

$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
$context = $contextFactory->createForNamespace('\My\Example', file_get_contents('My/Example/Classy.php'));

使用上下文

在获得上下文之后,只需将其与解析器类的resolve方法作为第二个参数一起传递,解析器在解析部分名称时会考虑到这一点。

要获取上述示例中@var标签的解析类名,你可以这样做:

$typeResolver = new \phpDocumentor\Reflection\TypeResolver();
$type = $typeResolver->resolve('Types\Context', $context);

当你这样做时,你将收到一个\phpDocumentor\Reflection\Types\Object_类的对象,你可以调用getFqsen方法来接收一个表示完整FQSEN的值对象。因此,将是phpDocumentor\Reflection\Types\Context

为什么FQSEN被包装在另一个对象Object_中?

类型解析器的解析方法只返回具有Type接口的对象,而FQSEN是一个常见的类型,它不代表类型。此外:在某些情况下,类型可以表示一个“无类型对象”,这意味着它是一个对象(由object关键字表示),但它不使用FQSEN引用特定元素。

另一个例子是解析方法FQSEN,如上例中的@see标签所示。要解析它,你可以这样做:

$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
$type = $fqsenResolver->resolve('Classy::otherFunction()', $context);

因为Classy是当前命名空间中的类,它的FQSEN将具有My\Example命名空间,通过调用FQSEN解析器的resolve方法,你将收到一个Fqsen对象,它指向\My\Example\Classy::otherFunction()