jared/php-docblock-parser

该包最新版本(dev-main)没有可用的许可证信息。

解析文档块

dev-main 2023-09-14 00:08 UTC

This package is auto-updated.

Last update: 2024-09-14 02:07:52 UTC


README

这是一个用于解析文档块的独立库。目前只支持PHPDoc v3。

安装

composer require jared/php-docblock-parser

用法

$raw = '/**
* The summary string
* having two lines.
* The description with a {@link proto://domain.tld The Link} element.
* @method int[]|Some\Class myMethod(int[] $param1, SomeType|null $param2) and method description
* @param int[] $param1 Param description
* @param Some\Class $param2 Param2 description
*                           having two lines
* @return mixed[] return description
* @see Something\Here
*/';

$docblock = new Falloff\DocBlock\PHPDoc( $raw );

foreach( $docblock as $index => $element )
	print_r($element);

遍历

直接访问

解析的文档块是一个递归结构,由文本块和标签结构组成。后者可能包含自己的文本块,这些文本块可能包含内联标签,可能包含...可以通过以下方式遍历此结构,而无需额外工具

$queue = [$docblock];

while( !empty( $queue ) ){

    $element = array_shift($queue);

	if( is_object($element) and get_class( $element ) == Falloff\DocBlock\PHPDoc\TextBlock::class ){
		// Gives 'The cummary string....'
		print $element->summary[0] . "\n"; 

		// Gives 'The Description...'
		print $element->text[0] . "\n"; 

		// Refers to Placeholder object, containing the Link tag
		print get_class($element->text[1]) . "\n";

		// The 'proto://domain.tld' string 
		print $element->text[1]->tag->url . "\n"; 

		// The 'The Link' string
		print $element->text[1]->tag->description[0] . "\n"; 
	}

	if( is_object($element) and get_class( $element ) == Falloff\DocBlock\PHPDoc\Tag\Method::class ){
		 // The 'int[]|Some\Class' string
		print $element->type . "\n"; ;

		 // 'myMethod'
		print $element->definition->name . "\n"; ;

		// The params are accessed like the `definition` was an array:

		// 'int[]'
		print $element->definition[0]->type . "\n";
		 // '$param1'
		print $element->definition[0]->name . "\n";
	}

	// Adding param's tags descriptions to the queue
	if( is_object($element) and get_class( $element ) == Falloff\DocBlock\PHPDoc\Tag\Param::class ){

		// Elements in the description might be objects or regular strings
		foreach( $element->description as $param_description_chunk ){
			$queue[] = $param_description_chunk;
		}
	}


	if( is_scalar($element) ){
		// Will produce following two strings:
		// 'The following is a regular scalar string: `Param description`'
		// 'The following is a regular scalar string: `Param2 description`''
		print 'The following is a regular scalar string: `' . $element . "`\n";
	}

	if( is_object($element) ){
	    foreach ($element as $child) {
	        $queue[] = $child;
	    }		
	}

}

在某些情况下可以使用这种方法,但看起来相当不方便。

通过访问者

该包包含Visitor接口,可用于简化遍历

$visitor = new class implements Falloff\DocBlock\Visitor{

	function in( Falloff\DocBlock\Entity|string|null $entity, array $payload, int|string $idx ) {

		print 'Index is: ' . $idx . "\n";

		print (
			is_object( $entity )
			? "Entity is an object of class " . get_class( $entity ) . "\n"
			: (
				is_null( $entity )
				? "Entity is NULL\n"
				: "Entity is a string containing: " . $entity . "\n"
			)			
		);

		print "Payload is: \n";
		print_r($payload);

		print "\n";

		return true;

	}

	function out( Falloff\DocBlock\Entity|string|null $entity, array $payload, int|string $idx){}
};

$docblock->visit( $visitor );

访问者必须实现inout方法。在遍历过程中,这些方法会与当前实体本身一起调用,这可能是代表文档块或其组件的实例。$payload参数是一个数组,包含当前元素的某些内部结构,例如@param标签的nametype$idx参数是当前元素在其父结构中的索引。这可能对于像Text这样的普通容器是整数,而对于像@link这样的标签是属性的名称,如urlin方法的返回值如下

  • false值表示停止遍历当前元素、其子元素或属性,并移动到树中的下一个元素
  • true值表示遍历当前元素属性,即@see标签的refdescription
  • 任何其他值将使遍历跳过元素的属性,并在有子元素的情况下移动到元素的子元素,或在没有其他元素的情况下继续前进

$payload包含处理元素所需的所有数据时,遍历而不返回值应该足够。如果不是这样,请确保返回true以在下一个迭代中访问元素的属性。