Reading metadata¶
Your starting point is instance of
RunOpenCode\Component\Metadata\Contract\MetadataReaderInterface. Reader
provides you with methods to:
Check if class is marked with specific attribute.
Get instance of RunOpenCodeComponentMetadataContractClassMetadataInterface` for further processing (i.e. searching for attributes on class, properties and methods).
Find properties and methods that are marked with specific attributes. Properties and methods may be searched separately or together. Each property or method found is represented with instance of
RunOpenCode\Component\Metadata\Contract\PropertyMetadataInterfaceandRunOpenCode\Component\Metadata\Contract\MethodMetadataInterfacerespectively.
Class attributes and members resolution¶
When reading metadata from classes, getting attributes from class is simple, only attributes from the current class are considered, no inheritance is consulted.
However, should you need to read class attributes from parent classes, you may use
RunOpenCode\Component\Metadata\Contract\ClassMetadataInterface::$parent property
to traverse the class hierarchy.
When comes to members (properties and methods), library will resolve members navigating the class hierarchy, meaning that members from parent classes will be considered as well. Rules for resolving members are as follows:
Private members: All private members are considered from all classes in the hierarchy. This means that if a parent class has a private property or method, it will be included in the results, even though there is a name collision with a child class member.
Public and protected members: Only the members from the most derived class are considered. If a child class overrides a public or protected member from a parent class, only the child class member will be included in the results.
This resolution strategy can be explained with the example given below (do note that example uses properties only for brevity, but the same rules apply to methods as well):
1 <?php
2
3 declare(strict_types=1);
4
5 use RunOpenCode\Component\Metadata\Attribute as Meta;
6
7 #[Meta\Example('foo')]
8 class ParentClass
9 {
10 #[Meta\Property('foo_parent')]
11 private string $privateProperty;
12
13 #[Meta\Property('foo_parent')]
14 protected string $protectedProperty;
15
16 #[Meta\Property('foo_parent')]
17 public string $publicProperty;
18 }
19
20 #[Meta\Example('bar')]
21 class ChildClass extends ParentClass
22 {
23 #[Meta\Property('foo_child')]
24 private string $privateProperty;
25
26 #[Meta\Property('foo_child')]
27 protected string $protectedProperty; // overrides parent
28
29 #[Meta\Property('foo_child')]
30 public string $publicProperty; // overrides parent
31 }
By introspecting ChildClass, the following will be resolved:
Class attributes:
Meta\Example('bar')only.Properties:
Private properties: Both
Meta\Property('foo_parent')andMeta\Property('foo_child')will be resolved, as they are private to their respective classes.Protected properties: Only
Meta\Property('foo_child')will be resolved, as it overrides the parent class property.Public properties: Only
Meta\Property('foo_child')will be resolved, as it overrides the parent class property.
Expected results and exceptions¶
When using metadata reader methods, do note that methods properties(),
methods() and members() will always return arrays, even if no members
were found with requested attribute.
However, methods get(), property(), method() and member() may
throw:
RunOpenCode\Component\Metadata\Exception\NotExistsExceptionif there is no attribute of requested type found on class or member, or no members were found with requested attribute.RunOpenCode\Component\Metadata\Exception\UnexpectedResultException.phpif there are multiple attributes of requested type found on class, or, there are multiple members found with requested attribute.
In order to avoid exceptions, you may use methods that return arrays, and
handle the results accordingly, or use methods has() to check for existence
of attributes or members with requested attributes.