Table of Contents
List of Examples
This complete guide documents PHP Reflect 4.2.2, published on 2017-12-14.
This work is licensed under the Attribution-Share Alike 3.0 Unported license.
We distribute a PHP Archive (PHAR) that contains all required dependencies of PHP Reflect bundled in a single file.
Make it executable, and put it into your $PATH
.
$ chmod +x phpreflect-4.2.2.phar $ mv phpreflect-4.2.2.phar /usr/local/bin/phpreflect $ phpreflect --version
You can also immediately use the PHAR after you have downloaded it.
$ wget http://bartlett.laurent-laville.org/get/phpreflect-4.2.2.phar $ php phpreflect-4.2.2.phar --version
With both methods then you have this output :
phpReflect version 4.2.2
Other alternative installations are possible. Please refer to the Chapter 7, Installation for details on how to do this.
With the minimalist JSON file phpreflect.json
.
{ "source-providers": [ { "in": ". as current", "name": "/\\.(php|inc|phtml)$/" } ], "plugins": [ ], "analysers": [ ], "services": [ ] }
Put it in your project’s folder. Alternative locations are possible. Please refer to the Chapter 8, The Json Configuration File for details on how to do this.
The JSON configuration file is no more required for basic usage. Reserved to advanced users. |
analyser:run
command.
With the Reflect source code, invoke the following command :
$ phpreflect analyser:run .
and you should obtain something like this :
Data Source Analysed Directories 22 Files 77 Structure Namespaces 22 Interfaces 10 Traits 0 Classes 67 Abstract Classes 8 (11.94%) Concrete Classes 59 (88.06%) Methods 312 Scope Non-Static Methods 299 (95.83%) Static Methods 13 (4.17%) Visibility Public Method 268 (85.90%) Protected Method 35 (11.22%) Private Method 9 (2.88%) Functions 11 Named Functions 0 (0.00%) Anonymous Functions 11 (100.00%) Constants 21 Global Constants 0 (0.00%) Magic Constants 3 (14.29%) Class Constants 18 (85.71%) Tests Classes 0 Methods 0
Another analyser (loc
) is also available, and can be combined or not with structure
the default analyser.
With the Reflect source code, invoke the following command :
$ phpreflect analyser:run . loc
and you should obtain something like this :
Data Source Analysed Directories 22 Files 77 Size Lines of Code (LOC) 3832 Comment Lines of Code (CLOC) 137 (3.58%) Non-Comment Lines of Code (NCLOC) 3695 (96.42%) Logical Lines of Code (LLOC) 1210 (31.58%) Classes 1142 (94.38%) Average Class Length 17 Average Method Length 3 Functions 68 (5.62%) Average Function Length 6 Not in classes or functions 0 (0.00%) Complexity Cyclomatic Complexity / LLOC 0.53 Cyclomatic Complexity / Number of Methods 2.73
Let’s review what we’ve done :
First visit, you are highly recommended to follow chapters in following order. |
All you have to know if you want to upgrade from a previous version 1.x easily. |
See ???
Basic Reflect features does not match your needs. Learn how to extend or change some features/behaviors. |
Reflect may be installed in several ways, choose your favorite.
Please read the ??? in case you are upgrading from a version 1.x of PHP Reflect. |
Before you install PHP Reflect, you will need an operating system with PHP 5.4.0 or later installed,
Reflect requires the date, json, reflection, tokenizer, phar, pcre, and spl extensions. These extensions are usually compiled and enabled by default.
Put a file named composer.json at the root of your project, with the content below:
{ "require": { "bartlett/php-reflect": "4.2.2" } }
And ask Composer to install the dependencies:
$ php composer.phar install
Or just invoke Composer to install the latest version:
$ php composer.phar require bartlett/php-reflect
With composer |
You can also use Composer to create a new project from an existing Reflect package. This is the equivalent of doing a git clone checkout followed by a composer install of the vendors. $ php composer.phar create-project bartlett/php-reflect /path/to/install 4.2.2 Where |
The recommended way for newbies, or just to have a look on features of this library, is to download a PHP Archive that contain all required dependencies of PHP Reflect bundled in a single file.
$ wget http://bartlett.laurent-laville.org/get/phpreflect-4.2.2.phar $ chmod +x phpreflect-4.2.2.phar $ mv phpreflect-4.2.2.phar /usr/local/bin/phpreflect $ phpreflect
You can also immediately use the PHAR after you have downloaded it.
$ wget http://bartlett.laurent-laville.org/get/phpreflect-4.2.2.phar $ php phpreflect-4.2.2.phar
Reflect may used an optional config file in JSON format.
It could be found either in the current, By setting the E.g: And by setting the E.g: E.g: Take care of different PATH_SEPARATOR and DIRECTORY_SEPARATOR in each platform. |
The minimalist JSON file phpreflect.json
is :
{ "source-providers": [ { "in": ". as current", "name": "/\\.(php|inc|phtml)$/" } ], "plugins": [ ], "analysers": [ ], "services": [ ] }
analyser:run
command.
There are lot of way to filter your data source. Each rule follow the syntax of Symfony Finder Component.
The Location is the only mandatory criteria. It tells the Finder which directory to use for the search.
In a simple directory.
{ "in": ". as current" }
If you want to identify a data source easily by a short name, the alias (right of |
Search in several locations.
{ "in": ". as current", "in": "src/" }
Use wildcard characters to search in the directories matching a pattern:
{ "in": "src/Bartlett/R*" }
Search directly in archives (phar, zip, tar) with the phar://
protocol.
{ "in": "phar://path/to/archive.zip" }
Restrict files by name and/or extension.
{ "in": "phar://path/to/archive.zip", "name": "*.php" }
Restrict files by size.
{ "in": "phar://path/to/archive.zip", "name": "*.php", "size": "< 10K" }
Restrict files by last modified dates.
{ "in": ". as current", "date": "since yesterday" }
By default, the Finder recursively traverse directories.
Restrict the depth of traversing.
{ "in": ". as current", "depth": "< 3" }
Restrict location by only one directory.
{ "in": ". as current", "exclude": "vendor" }
Restrict location by 1 or more directories.
{ "in": ". as current", "exclude": ["vendor", "tests"] }
There are a number of optional plugins you can use along with Reflect to add more capabilities.
Take an example with the Logger
plugin.
In your phpreflect.json
configuration file, add in plugins
section the following entry:
{ "name": "Logger", "class": "Bartlett\\Reflect\\Plugin\\LogPlugin" }
name
key is (since version 3.0.0-alpha1) comment only.
class
key identify the name of the class that implement the plugin features (must be fully qualified).
The |
Available since version 2.3.0, but location changed since version 3.0.0-alpha1 |
In your phpreflect.json
configuration file, add in plugins
section the following entry:
{ "name": "Cache", "class": "Bartlett\\Reflect\\Plugin\\CachePlugin", "options": { "adapter": "DoctrineCacheAdapter", "backend": { "class": "Doctrine\\Common\\Cache\\FilesystemCache", "args": [ "%{TEMP}/bartlett/cache" ] } } }
You may use any environment variable that will be replaced, at run-time, by their value. E.g: |
Since release 2.3.0, the |
If you want to used the same options (Doctrine adapter with file cache) as above, you can used shortcut syntax like this. { "name": "Cache", "class": "Bartlett\\Reflect\\Plugin\\CachePlugin", "options": [] } |
In previous configuration we used the Doctrine Cache adapter and its File system backend. See the same configuration applied with other SAPI, in Section 19.3, “File cache”
Available since version 2.4.0, but location and options changed since version 3.0.0-alpha1 |
In your phpreflect.json
configuration file, add in plugins
section the following entry:
{ "name": "Log", "class": "Bartlett\\Reflect\\Plugin\\LogPlugin" }
Where options
key identify an optional class logger (fully qualified. E.g YourNamespace\YourLogger
).
When options
key is not provided, log plugin used the default Reflect logger bundled with distribution.
See Bartlett\Reflect\Plugin\Log\DefaultLogger
that write results to the error log system.
See the Developer Guide for definition examples of some loggers Section 20.3, “Using your private logger” or Section 20.4, “Using Monolog”
There are two default analysers you can use, but you are free to add your owns.
In your phpreflect.json
configuration file, add in analysers
section (for example) the following entry:
{ "name": "MyAnalyser", "class": "Your\\Analysers\\MyAnalyser" }
name
key is (since version 3.0.0-alpha1) comment only.
class
key identify the name of the class that implement your analyser (must be fully qualified).
Your analyser should implement both interfaces Bartlett\Reflect\Analyser\AnalyserInterface
and PhpParser\NodeVisitor
.
Then to use it in command line :
$ phpreflect analyser:run /path/to/datasource my
|
The command-line interface is the easiest way to try and learn the basic Reflect features.
For all users. |
Without plugins
and analysers
sections in your phpreflect.json
configuration file,
when you invoke the phpreflect
command, you should obtain the following commands and options :
_ ____ __ _ _ _ __ | |__ _ __ | _ \ ___ / _| | ___ ___| |_ | '_ \| '_ \| '_ \| |_) / _ \ |_| |/ _ \/ __| __| | |_) | | | | |_) | _ < __/ _| | __/ (__| |_ | .__/|_| |_| .__/|_| \_\___|_| |_|\___|\___|\__| |_| |_| phpReflect version 4.2.2 Usage: command [options] [arguments] Options: -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question --no-plugins Disables all plugins. --profile Display timing and memory usage information. --progress Show progress bar. --output=OUTPUT Write results to file or URL. --manifest Show which versions of dependencies are bundled. -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: help Displays help for a command list Lists commands analyser analyser:list List all analysers available. analyser:run Analyse a data source and display results. cache cache:clear Clear cache (any adapter and backend). config config:validate Validates a JSON configuration file. diagnose diagnose:run Diagnoses the system to identify common errors. diagram diagram:class Generates diagram about a user class present in a data source. diagram:package Generates diagram about namespaces in a data source. plugin plugin:list List all plugins installed. reflection reflection:class Reports information about a user class present in a data source. reflection:function Reports information about a user function present in a data source.
config:validate |
Validates an optional JSON config file. $ phpreflect config:validate "/etc/phpreflect.json" config file is valid. | |||
diagnose:run |
Diagnoses the system to identify common errors. $ phpreflect diagnose:run Checking php settings: - Requires PHP 5.5.0 or better OK - php.ini file loaded C:\UwAmp\bin\php\php-5.6.32\php.ini - date extension loaded YES - json extension loaded YES - pcre extension loaded YES - phar extension loaded YES - reflection extension loaded YES - spl extension loaded YES - tokenizer extension loaded YES
| |||
diagram:class |
Generates diagram about a user class present in a data source. $ phpreflect diagram:class Bartlett\Reflect\Plugin\LogPlugin ./src | |||
diagram:package |
Generates diagram about namespaces in a data source. $ phpreflect diagram:package --engine=graphviz ./src | |||
plugin:list |
List all plugins configured (and correctly installed) in Without plugins, you will get. $ phpreflect plugin:list
No plugin installed. With only $ phpreflect plugin:list
Plugin Class Events Subscribed Bartlett\Reflect\Plugin\CachePlugin reflect.progress reflect.success reflect.complete | |||
analyser:list |
List all analysers configured in With only default analysers, you will get. $ phpreflect analyser:list
Analyser Name Analyser Class loc Bartlett\Reflect\Analyser\LocAnalyser reflection Bartlett\Reflect\Analyser\ReflectionAnalyser structure Bartlett\Reflect\Analyser\StructureAnalyser | |||
analyser:run |
Parse a data source and display results. May vary depending of the data source and analyser used. With $ phpreflect analyser:run .
Possible alternative (if you use the default json config file). $ phpreflect analyser:run --alias current
Data Source Analysed Directories 22 Files 77 Structure Namespaces 22 Interfaces 10 Traits 0 Classes 67 Abstract Classes 8 (11.94%) Concrete Classes 59 (88.06%) Methods 312 Scope Non-Static Methods 299 (95.83%) Static Methods 13 (4.17%) Visibility Public Method 268 (85.90%) Protected Method 35 (11.22%) Private Method 9 (2.88%) Functions 11 Named Functions 0 (0.00%) Anonymous Functions 11 (100.00%) Constants 21 Global Constants 0 (0.00%) Magic Constants 3 (14.29%) Class Constants 18 (85.71%) Tests Classes 0 Methods 0 Filter results with a closure (available since version 3.1.0). $ phpreflect analyser:run --filter=YourFilters.php .
<?php $closure = function ($data) { $filterOnKeys = array( 'namespaces', 'interfaces', 'traits', 'classes', 'abstractClasses', 'concreteClasses', 'functions', 'namedFunctions', 'anonymousFunctions', 'classConstants', 'globalConstants', 'magicConstants', ); foreach ($data as $title => &$keys) { if (strpos($title, 'StructureAnalyser') === false) { continue; } // looking into Structure Analyser metrics only foreach ($keys as $key => $val) { if (!in_array($key, $filterOnKeys)) { unset($keys[$key]); // "removed" unsolicited values continue; } } } return $data; }; return $closure; Data Source Analysed Directories 22 Files 77 Structure Namespaces 22 Interfaces 10 Traits 0 Classes 67 Abstract Classes 8 (11.94%) Concrete Classes 59 (88.06%) Functions 11 Named Functions 0 (0.00%) Anonymous Functions 11 (100.00%) Constants 21 Global Constants 0 (0.00%) Magic Constants 3 (14.29%) Class Constants 18 (85.71%)
| |||
reflection:class |
Reports information about a user class present in a data source. With the Reflect source code ( $ phpreflect reflection:class Bartlett\Reflect ./src
Class [ <user> class Bartlett\Reflect extends Bartlett\Reflect\Event\AbstractDispatcher ] { @@ C:\home\github\php-reflect\src\Bartlett\Reflect.php 45 - 340 - Constants [0] { } - Properties [2] { Property [ private $analysers ] Property [ private $dataSourceId ] } - Methods [6] { Method [ <user> public method __construct ] { @@ C:\home\github\php-reflect\src\Bartlett\Reflect.php 53 - 57 - Parameters [0] { } } Method [ <user> public method addAnalyser ] { @@ C:\home\github\php-reflect\src\Bartlett\Reflect.php 66 - 71 - Parameters [1] { Parameter #0 [ <required> PhpParser\NodeVisitor $analyser ] } } Method [ <user> public method getAnalysers ] { @@ C:\home\github\php-reflect\src\Bartlett\Reflect.php 78 - 81 - Parameters [0] { } } Method [ <user> public method setDataSourceId ] { @@ C:\home\github\php-reflect\src\Bartlett\Reflect.php 90 - 94 - Parameters [1] { Parameter #0 [ <required> $id ] } } Method [ <user> public method getDataSourceId ] { @@ C:\home\github\php-reflect\src\Bartlett\Reflect.php 101 - 104 - Parameters [0] { } } Method [ <user> public method parse ] { @@ C:\home\github\php-reflect\src\Bartlett\Reflect.php 113 - 339 - Parameters [1] { Parameter #0 [ <required> Symfony\Component\Finder\Finder $finder ] } } } } |
Let’s review what we’ve learned about the command-line interface :
Because the version 2 is a full API rewrites, and used namespaces, your old code cannot migrate without a little change.
We will try to explain how to do in few steps.
Version 1.x used customizable containers feature to store parsing results.
For example, in version 1.x when we wanted to retrieve user functions, we could either do :
Example 11.1. With standard container
<?php require_once 'Bartlett/PHP/Reflect/Autoload.php'; $source = '/path/to/source_file.php'; $options = array(); $reflect = new PHP_Reflect($options); $reflect->scan($source); $functions = $reflect->getFunctions(); // OR $functions = $reflect['functions'];
Example 11.2. With a non standard container
<?php require_once 'Bartlett/PHP/Reflect/Autoload.php'; $source = '/path/to/source_file.php'; $options = array('containers' => array('function' => 'userFunctions'); $reflect = new PHP_Reflect($options); $reflect->scan($source); $functions = $reflect->getUserFunctions(); // OR $functions = $reflect['userFunctions'];
In version 2.x, we have collections of data models that we can enumerate and exploit.
Example 11.3. Enumerate each user functions
<?php require_once 'vendor/autoload.php'; use Bartlett\Reflect; use Bartlett\Reflect\ProviderManager; use Bartlett\Reflect\Provider\SymfonyFinderProvider; use Symfony\Component\Finder\Finder; $finder = new Finder(); $finder->files() ->name('source_file.php') ->in('/path/to/'); // Identify Data Source $pm = new ProviderManager; $pm->set('Sample', new SymfonyFinderProvider($finder)); $reflect = new Reflect; $reflect->setProviderManager($pm); $reflect->parse(); // Exploit results foreach ($reflect->getPackages() as $package) { $functions = $package->getFunctions(); }
Version 1.x may provide a variable properties list. Version 2.x provides all properties anytime. It’s up to you to decide to use them or not.
For example, in version 1.x when we wanted to retrieve only keywords and signature of each class methods of a data source.
Example 12.1. Configure interface, class and method properties
<?php require_once 'Bartlett/PHP/Reflect/Autoload.php'; $source = '/path/to/PEAR-1.9.2/PEAR.php'; $options = array( 'properties' => array( 'interface' => array( 'parent', 'methods' ), 'class' => array( 'parent', 'methods', 'interfaces', 'package' ), 'function' => array( 'signature' ), ) ); $reflect = new PHP_Reflect($options); $reflect->scan($source); $classes = $reflect->getClasses(); print_r($classes['\\']['PEAR_Error']['methods']);
Script output.
Array ( [PEAR_Error] => Array ( [signature] => PEAR_Error($message = 'unknown error', $code = null, $mode = null, $options = null, $userinfo = null) ) [getMode] => Array ( [signature] => getMode() ) [getCallback] => Array ( [signature] => getCallback() ) [getMessage] => Array ( [signature] => getMessage() ) [getCode] => Array ( [signature] => getCode() ) [getType] => Array ( [signature] => getType() ) [getUserInfo] => Array ( [signature] => getUserInfo() ) [getDebugInfo] => Array ( [signature] => getDebugInfo() ) [getBacktrace] => Array ( [signature] => getBacktrace($frame = null) ) [addUserInfo] => Array ( [signature] => addUserInfo($info) ) [__toString] => Array ( [signature] => __toString() ) [toString] => Array ( [signature] => toString() ) )
In version 2.x, when we did the same.
Example 12.2. Properties on demand
<?php require_once 'vendor/autoload.php'; use Bartlett\Reflect; use Bartlett\Reflect\ProviderManager; use Bartlett\Reflect\Provider\SymfonyFinderProvider; use Symfony\Component\Finder\Finder; $finder = new Finder(); $finder->files() ->name('PEAR.php') ->in('/path/to/PEAR-1.9.2/'); // Identify Data Source $pm = new ProviderManager; $pm->set('PEAR192', new SymfonyFinderProvider($finder)); $reflect = new Reflect; $reflect->setProviderManager($pm); $reflect->parse(); // Exploit results $out = array(); foreach ($reflect->getPackages() as $package) { foreach ($package->getClasses() as $class) { if ($class->getShortName() !== 'PEAR_Error') { continue; } foreach ($class->getMethods() as $method) { if ($method->isPrivate()) { $visibility = 'private'; } elseif ($method->isProtected()) { $visibility = 'protected'; } else { $visibility = 'public'; } $name = $method->getShortName(); $parameters = $method->getParameters(); $args = array(); foreach ($parameters as $parameter) { $args[] = sprintf( '%s%s%s', $parameter->isPassedByReference() ? '&' : '', '$' . $parameter->getName(), $parameter->isDefaultValueAvailable() ? ' = ' . $parameter->getDefaultValue() : '' ); } $out[$name] = array( 'signature' => sprintf('%s %s(%s)', $visibility, $name, implode(',', $args)) ); } } } print_r($out);
Script output.
Array ( [PEAR_Error] => Array ( [signature] => public PEAR_Error($message = 'unknown error',$code = null,$mode = null,$options = null,$userinfo = null) ) [getMode] => Array ( [signature] => public getMode() ) [getCallback] => Array ( [signature] => public getCallback() ) [getMessage] => Array ( [signature] => public getMessage() ) [getCode] => Array ( [signature] => public getCode() ) [getType] => Array ( [signature] => public getType() ) [getUserInfo] => Array ( [signature] => public getUserInfo() ) [getDebugInfo] => Array ( [signature] => public getDebugInfo() ) [getBacktrace] => Array ( [signature] => public getBacktrace($frame = null) ) [addUserInfo] => Array ( [signature] => public addUserInfo($info) ) [__toString] => Array ( [signature] => public __toString() ) [toString] => Array ( [signature] => public toString() ) )
Let’s review what we’ve did :
Because the version 3 is a full API rewrites, and used namespaces, your old code cannot migrate without a little change.
We will try to explain how to do in few steps.
Version 2.x used collections of data models that we can enumerate and exploit. Version 3.x return only a single data model that match object to reflect.
In version 2.x, we have collections of data models that we can enumerate and exploit.
Example 14.1. Exploit model collections to print methods of a user class
<?php require_once 'vendor/autoload.php'; use Bartlett\Reflect; use Bartlett\Reflect\ProviderManager; use Bartlett\Reflect\Provider\SymfonyFinderProvider; use Symfony\Component\Finder\Finder; $finder = new Finder(); $finder->files() ->name('*.php') ->in('/path/to/'); // Identify Data Source $pm = new ProviderManager; $pm->set('Sample', new SymfonyFinderProvider($finder)); $reflect = new Reflect; $reflect->setProviderManager($pm); $reflect->parse(); // Exploit results foreach ($reflect->getPackages() as $package) { foreach ($package->getClasses() as $class) { if ('VendorNamespace\\VendorClass' === $class->getName()) { $methods = array(); foreach ($class->getMethods() as $method) { $methods[] = $method->getShortName(); } printf( 'Methods are : %s' . PHP_EOL, print_r($methods, true) ); } } }
In version 3.x, we have a single data model corresponding to a user class or function.
Example 14.2. Print methods of a user class
<?php require_once 'vendor/autoload.php'; use Bartlett\Reflect\Client; // creates an instance of client $client = new Client(); // request for a Bartlett\Reflect\Api\Reflection $api = $client->api('reflection'); // perform request, on a data source $dataSource = '/path/to/'; // equivalent to CLI command `phpreflect reflection:class VendorNamespace\VendorClass /path/to` $class = $api->class('VendorNamespace\\VendorClass', $dataSource); $methods = array(); foreach ($class->getMethods() as $method) { $methods[] = $method->getShortName(); } printf( 'Methods are : %s' . PHP_EOL, print_r($methods, true) );
API
Reflect comes with a complete reflection API, almost equivalent to PHP5 reflection.
See Chapter 17, API
Plugins
Reflect uses a Symfony EventDispatcher Component to allow you to easily extend the features list.
Analysers
Reflect uses analysers that implements the Visitor pattern in a simple and effective way to make the render of your results truly customizable.
See ???
Filters
CompatInfo can filter results, since version 4.2, to make the render of your results truly customizable.
PHP5 | Reflect | Description |
---|---|---|
Class reports information about a class
http://www.php.net/manual/en/class.reflectionclass.php
| ||
__construct - Constructs a ReflectionClass | ||
__toString - Returns the string representation of the ReflectionClass object | ||
export - Exports a class | ||
getConstant - Gets defined constant | ||
getConstants - Gets constants | ||
getConstructor - Gets the constructor of the class | ||
getDefaultProperties - Gets default properties | ||
getDocComment - Gets doc comments | ||
getEndLine - Gets end line | ||
getExtension - Gets a ReflectionExtension object for the extension which defined the class | ||
getExtensionName - Gets the name of the extension which defined the class | ||
getFileName - Gets the filename of the file in which the class has been defined | ||
getInterfaceNames - Gets the interface names | ||
getInterfaces - Gets the interfaces | ||
getMethod - Gets a ReflectionMethod for a class method | ||
getMethods - Gets an array of methods | ||
getModifiers - Gets modifiers | ||
getName - Gets class name | ||
getNamespaceName - Gets namespace name | ||
getParentClass - Gets parent class | ||
getParentClassName - Gets parent class name | ||
getProperties - Gets properties | ||
getProperty - Gets a ReflectionProperty for a class’s property | ||
getShortName - Gets short name | ||
getStartLine - Gets starting line number | ||
getStaticProperties - Gets static properties | ||
getStaticPropertyValue - Gets static property value | ||
getTraitAliases - Returns an array of trait aliases | ||
getTraitNames - Returns an array of names of traits used by this class | ||
getTraits - Returns an array of traits used by this class | ||
hasConstant - Checks if constant is defined | ||
hasMethod - Checks if method is defined | ||
hasProperty - Checks if property is defined | ||
implementsInterface - Implements interface | ||
inNamespace - Checks if class in namespace | ||
isAbstract - Checks if class is abstract | ||
isCloneable - Returns whether this class is cloneable | ||
isFinal - Checks if class is final | ||
isInstance - Checks class for instance | ||
isInstantiable - Checks if the class is instantiable | ||
isInterface - Checks if the class is an interface | ||
isInternal - Checks if class is defined internally by an extension, or the core | ||
isIterateable - Checks if iterateable | ||
isSubclassOf - Checks if a subclass | ||
isTrait - Returns whether this is a trait | ||
isUserDefined - Checks if user defined | ||
newInstance - Creates a new class instance from given arguments | ||
newInstanceArgs - Creates a new class instance from given arguments | ||
newInstanceWithoutConstructor - Creates a new class instance without invoking the constructor | ||
setStaticPropertyValue - Sets static property value |
Does not exist in PHP5 Reflection API |
PHP5 | Reflect | Description |
---|---|---|
Class reports information about a constant
| ||
__construct - Constructs a Reflection Constant | ||
__toString - Returns the string representation of the Reflection Constant object | ||
getDocComment - Gets doc comments | ||
getExtension - Gets a ReflectionExtension object for the extension which defined the constant | ||
getExtensionName - Gets the name of the extension which defined the constant | ||
getFileName - Gets the filename of the file in which the constant has been defined | ||
getName - Gets constant name | ||
getNamespaceName - Gets namespace name | ||
getShortName - Gets short name | ||
getValue - Gets value | ||
inNamespace - Checks if in namespace | ||
isInternal - Checks if constant is defined internally by an extension, or the core | ||
isMagic - Checks whether it’s a magic constant |
PHP5 | Reflect | Description |
---|---|---|
Class reports information about a function
http://www.php.net/manual/en/class.reflectionfunction.php
| ||
__construct - Constructs a ReflectionFunction | ||
__toString - Returns the string representation of the ReflectionFunction object | ||
export - Exports a function | ||
getClosure - Returns a dynamically created closure for the function | ||
invoke - Invokes function | ||
invokeArgs - Invokes function with args | ||
isDisabled - Checks if function is disabled |
PHP5 | Reflect | Description |
---|---|---|
A parent class to ReflectionFunction
http://www.php.net/manual/en/class.reflectionfunctionabstract.php
| ||
__clone - Clones function | ||
getClosureScopeClass - Returns the scope associated to the closure | ||
getClosureThis - Returns this pointer bound to closure | ||
getDocComment - Gets doc comments | ||
getEndLine - Gets end line | ||
getExtension - Gets a ReflectionExtension object for the extension which defined the function | ||
getExtensionName - Gets the name of the extension which defined the function | ||
getFileName - Gets the filename of the file in which the function has been defined | ||
getName - Gets function name | ||
getNamespaceName - Gets namespace name | ||
getNumberOfParameters - Gets number of parameters | ||
getNumberOfRequiredParameters - Gets number of required parameters | ||
getParameters - Gets parameters | ||
getShortName - Gets function short name | ||
getStartLine - Gets starting line number | ||
getStaticVariables - Gets static variables | ||
inNamespace - Checks if function in namespace | ||
isClosure - Checks if closure | ||
isDeprecated - Checks if function deprecated | ||
isGenerator - Returns whether this function is a generator | ||
isInternal - Checks if function is defined internally by an extension, or the core | ||
isUserDefined - Checks if user defined | ||
returnsReference - Checks if returns reference |
PHP5 | Reflect | Description |
---|---|---|
Class reports information about a method
http://www.php.net/manual/en/class.reflectionmethod.php
| ||
__construct - Constructs a ReflectionMethod | ||
__toString - Returns the string representation of the ReflectionMethod object | ||
export - Exports a method | ||
getClosure - Returns a dynamically created closure for the method | ||
getDeclaringClass - Gets declaring class for the reflected method | ||
getModifiers - Gets the method modifiers | ||
getPrototype - Gets the method prototype | ||
invoke - Invokes method | ||
invokeArgs - Invokes method with args | ||
isAbstract - Checks if method is abstract | ||
isConstructor - Checks if method is a constructor | ||
isDestructor - Checks if method is a destructor | ||
isFinal - Checks if method is final | ||
isPrivate - Checks if method is private | ||
isProtected - Checks if method is protected | ||
isPublic - Checks if method is public | ||
isStatic - Checks if method is static | ||
setAccessible - Set method accessibility |
PHP5 | Reflect | Description |
---|---|---|
Class reports information about a parameter
http://www.php.net/manual/en/class.reflectionparameter.php
| ||
__construct - Constructs a ReflectionParameter | ||
__toString - Returns the string representation of the ReflectionParameter object | ||
__clone - Clones parameter | ||
allowsNull - Checks if null is allowed | ||
canBePassedByValue - Returns whether this parameter can be passed by value | ||
export - Exports a parameter | ||
getClass - Gets class | ||
getTypeHint - Gets the type of the parameter (callable, array, class name, or none) | ||
getDeclaringClass - Gets declaring class for the reflected parameter | ||
getDeclaringFunction - Gets declaring function for the reflected parameter | ||
getDefaultValue - Gets default parameter value | ||
getDefaultValueConstantName - Returns the default value’s constant name if default value is constant or null | ||
getName - Gets parameter name | ||
getPosition - Gets parameter position | ||
isArray - Checks if parameter expects an array | ||
isCallable - Returns whether parameter MUST be callable | ||
isDefaultValueAvailable - Checks if a default value is available | ||
isDefaultValueConstant - Returns whether the default value of this parameter is constant | ||
isOptional - Checks if the parameter is optional | ||
isPassedByReference - Checks if the parameter is passed in by reference |
PHP5 | Reflect | Description |
---|---|---|
Class reports information about classes properties
http://www.php.net/manual/en/class.reflectionproperty.php
| ||
__construct - Constructs a ReflectionProperty | ||
__toString - Returns the string representation of the ReflectionProperty object | ||
__clone - Clones property | ||
export - Exports a property | ||
getClassName - Gets class name of the reflected property | ||
getDeclaringClass - Gets declaring class for the reflected property | ||
getDocComment - Gets doc comments from a property | ||
getModifiers - Gets modifiers | ||
getName - Gets property name | ||
getValue - Gets property value | ||
isDefault - Checks if default value | ||
isPrivate - Checks if property is private | ||
isProtected - Checks if property is protected | ||
isPublic - Checks if property is public | ||
isStatic - Checks if property is static | ||
setAccessible - Set property accessibility | ||
setValue - Set property value |
Basic or Complex Strategy to identify the Data Source.
Now, and for the following chapters, we will not mention how you load the classes. Depending of the install strategy you’ve adopted, Composer or other, don’t forget to load your autoloader. |
Compare to version 2, Reflect 3 offers two simple strategies to identify the data source.
First, is to give the relative or absolute path to file or directory to parse (without limitation).
Second, is to specify options to customize parsing process, to the Symfony Finder Component.
With all SAPI, no JSON config file is required (as it was for Reflect 2). You have just to give the relative or absolute path to file or directory to parse.
It’s also possible to specify any archive (phar, zip, tar, tgz, gz, rar) as file source.
Example with a simple file or directory (absolute path).
$ phpreflect analyser:run /absolute/path/to/source
Example with a simple file or directory (relative path).
$ phpreflect analyser:run ./relative/path/to/source
Still as it was with Reflect 2, you will need to configure your data source in a JSON file.
Syntax is closed to the Symfony Finder Component that is used to limit data source contents to parse.
Example to parse an archive.
{ "source-providers": [ { "in": "phar:///var/dist/owncloud-7.0.2.tar as owncloud7", "name": "*.php", "exclude": ["3rdparty"] } ], "plugins": [ ], "analysers" : [ ] }
Do not forget the |
Use alias named here |
Example to parse a directory.
{ "source-providers": [ { "in": "/home/github/phing/ as phing2", "path": ["bin", "classes"], "exclude": ["test"], "name": "*.php" } ], "plugins": [ ], "analysers" : [ ] }
Learn more about directives, see Section 8.1, “section Source Providers”
Whatever SAPI you use, all metrics (for each analysers asked) are available at end of parse, in the same format.
With CLI, and Reflect source code, to get a structure report, you have to invoke the following command :
$ phpreflect analyser:run /home/github/php-reflect/src
With others SAPI, use example https://raw.githubusercontent.com/llaville/php-reflect/master/examples/api_analyser_run.php
and you should obtain something like this :
Data Source Analysed Directories 22 Files 77 Structure Namespaces 22 Interfaces 10 Traits 0 Classes 67 Abstract Classes 8 (11.94%) Concrete Classes 59 (88.06%) Methods 312 Scope Non-Static Methods 299 (95.83%) Static Methods 13 (4.17%) Visibility Public Method 268 (85.90%) Protected Method 35 (11.22%) Private Method 9 (2.88%) Functions 11 Named Functions 0 (0.00%) Anonymous Functions 11 (100.00%) Constants 21 Global Constants 0 (0.00%) Magic Constants 3 (14.29%) Class Constants 18 (85.71%) Tests Classes 0 Methods 0
This is the default render. But, if you want to compare with other SAPI,
activate the debug verbose mode (-vvv
) to get the raw response.
You should obtain something like this :
Array ( [files] => Array ( [0] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/AbstractAnalyser.php [1] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/AbstractSniffAnalyser.php [2] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/AnalyserInterface.php [3] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/AnalyserManager.php [4] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/LocAnalyser.php [5] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/ReflectionAnalyser.php [6] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/StructureAnalyser.php [7] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Analyser.php [8] => /home/github/php-reflect/src/Bartlett/Reflect/Api/BaseApi.php [9] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Cache.php [10] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Config.php [11] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Diagnose.php [12] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Diagram.php [13] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Plugin.php [14] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Reflection.php [15] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Analyser.php [16] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Cache.php [17] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Common.php [18] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Config.php [19] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Diagnose.php [20] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Diagram.php [21] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Plugin.php [22] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Reflection.php [23] => /home/github/php-reflect/src/Bartlett/Reflect/Client/ClientInterface.php [24] => /home/github/php-reflect/src/Bartlett/Reflect/Client/LocalClient.php [25] => /home/github/php-reflect/src/Bartlett/Reflect/Client.php [26] => /home/github/php-reflect/src/Bartlett/Reflect/Collection/ReflectionCollection.php [27] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Application.php [28] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Command.php [29] => /home/github/php-reflect/src/Bartlett/Reflect/Console/CommandFactory.php [30] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Formatter/LocOutputFormatter.php [31] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Formatter/OutputFormatter.php [32] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Formatter/StructureOutputFormatter.php [33] => /home/github/php-reflect/src/Bartlett/Reflect/Environment.php [34] => /home/github/php-reflect/src/Bartlett/Reflect/Event/AbstractDispatcher.php [35] => /home/github/php-reflect/src/Bartlett/Reflect/Event/CacheAwareEventDispatcher.php [36] => /home/github/php-reflect/src/Bartlett/Reflect/Event/DispatcherInterface.php [37] => /home/github/php-reflect/src/Bartlett/Reflect/Events.php [38] => /home/github/php-reflect/src/Bartlett/Reflect/Exception/Exception.php [39] => /home/github/php-reflect/src/Bartlett/Reflect/Exception/ModelException.php [40] => /home/github/php-reflect/src/Bartlett/Reflect/Model/AbstractFunctionModel.php [41] => /home/github/php-reflect/src/Bartlett/Reflect/Model/AbstractModel.php [42] => /home/github/php-reflect/src/Bartlett/Reflect/Model/ClassModel.php [43] => /home/github/php-reflect/src/Bartlett/Reflect/Model/ConstantModel.php [44] => /home/github/php-reflect/src/Bartlett/Reflect/Model/FunctionModel.php [45] => /home/github/php-reflect/src/Bartlett/Reflect/Model/MethodModel.php [46] => /home/github/php-reflect/src/Bartlett/Reflect/Model/ParameterModel.php [47] => /home/github/php-reflect/src/Bartlett/Reflect/Model/PropertyModel.php [48] => /home/github/php-reflect/src/Bartlett/Reflect/MonologConsoleLogger.php [49] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Analyser.php [50] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Cache.php [51] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Config.php [52] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Diagnose.php [53] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Diagram.php [54] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Plugin.php [55] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Reflection.php [56] => /home/github/php-reflect/src/Bartlett/Reflect/PhpParser/NodeProcessor.php [57] => /home/github/php-reflect/src/Bartlett/Reflect/PhpParser/NodeProcessorAbstract.php [58] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Cache/CacheAdapterInterface.php [59] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Cache/CacheStorageInterface.php [60] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Cache/DefaultCacheStorage.php [61] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Cache/DoctrineCacheAdapter.php [62] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/CachePlugin.php [63] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Log/DefaultLogger.php [64] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/LogPlugin.php [65] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Notifier/GrowlNotifier.php [66] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Notifier/NotifierInterface.php [67] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/NotifierPlugin.php [68] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/PluginInterface.php [69] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/PluginManager.php [70] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/ProfilerPlugin.php [71] => /home/github/php-reflect/src/Bartlett/Reflect/Sniffer/SniffAbstract.php [72] => /home/github/php-reflect/src/Bartlett/Reflect/Sniffer/SniffInterface.php [73] => /home/github/php-reflect/src/Bartlett/Reflect/Tokenizer/DefaultTokenizer.php [74] => /home/github/php-reflect/src/Bartlett/Reflect/Util/Timer.php [75] => /home/github/php-reflect/src/Bartlett/Reflect/Visitor/VisitorInterface.php [76] => /home/github/php-reflect/src/Bartlett/Reflect.php ) [Bartlett\Reflect\Analyser\StructureAnalyser] => Array ( [namespaces] => 22 [interfaces] => 10 [traits] => 0 [classes] => 67 [abstractClasses] => 8 [concreteClasses] => 59 [functions] => 11 [namedFunctions] => 0 [anonymousFunctions] => 11 [methods] => 312 [publicMethods] => 268 [protectedMethods] => 35 [privateMethods] => 9 [nonStaticMethods] => 299 [staticMethods] => 13 [constants] => 0 [classConstants] => 18 [globalConstants] => 0 [magicConstants] => 3 [testClasses] => 0 [testMethods] => 0 ) )
files
structure
analyser result
Each analyser as its own data structure and results, but you will always get the fully qualified class name that identify origin of analyser used.
Example with two analysers (structure
and loc
).
$ phpreflect analyser:run /home/github/php-reflect/src structure loc
Raw response Array ( [files] => Array ( ... ) [Bartlett\Reflect\Analyser\StructureAnalyser] => Array ( ... ) Array ( [files] => Array ( [0] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/AbstractAnalyser.php [1] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/AbstractSniffAnalyser.php [2] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/AnalyserInterface.php [3] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/AnalyserManager.php [4] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/LocAnalyser.php [5] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/ReflectionAnalyser.php [6] => /home/github/php-reflect/src/Bartlett/Reflect/Analyser/StructureAnalyser.php [7] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Analyser.php [8] => /home/github/php-reflect/src/Bartlett/Reflect/Api/BaseApi.php [9] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Cache.php [10] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Config.php [11] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Diagnose.php [12] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Diagram.php [13] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Plugin.php [14] => /home/github/php-reflect/src/Bartlett/Reflect/Api/Reflection.php [15] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Analyser.php [16] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Cache.php [17] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Common.php [18] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Config.php [19] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Diagnose.php [20] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Diagram.php [21] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Plugin.php [22] => /home/github/php-reflect/src/Bartlett/Reflect/Api/V3/Reflection.php [23] => /home/github/php-reflect/src/Bartlett/Reflect/Client/ClientInterface.php [24] => /home/github/php-reflect/src/Bartlett/Reflect/Client/LocalClient.php [25] => /home/github/php-reflect/src/Bartlett/Reflect/Client.php [26] => /home/github/php-reflect/src/Bartlett/Reflect/Collection/ReflectionCollection.php [27] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Application.php [28] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Command.php [29] => /home/github/php-reflect/src/Bartlett/Reflect/Console/CommandFactory.php [30] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Formatter/LocOutputFormatter.php [31] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Formatter/OutputFormatter.php [32] => /home/github/php-reflect/src/Bartlett/Reflect/Console/Formatter/StructureOutputFormatter.php [33] => /home/github/php-reflect/src/Bartlett/Reflect/Environment.php [34] => /home/github/php-reflect/src/Bartlett/Reflect/Event/AbstractDispatcher.php [35] => /home/github/php-reflect/src/Bartlett/Reflect/Event/CacheAwareEventDispatcher.php [36] => /home/github/php-reflect/src/Bartlett/Reflect/Event/DispatcherInterface.php [37] => /home/github/php-reflect/src/Bartlett/Reflect/Events.php [38] => /home/github/php-reflect/src/Bartlett/Reflect/Exception/Exception.php [39] => /home/github/php-reflect/src/Bartlett/Reflect/Exception/ModelException.php [40] => /home/github/php-reflect/src/Bartlett/Reflect/Model/AbstractFunctionModel.php [41] => /home/github/php-reflect/src/Bartlett/Reflect/Model/AbstractModel.php [42] => /home/github/php-reflect/src/Bartlett/Reflect/Model/ClassModel.php [43] => /home/github/php-reflect/src/Bartlett/Reflect/Model/ConstantModel.php [44] => /home/github/php-reflect/src/Bartlett/Reflect/Model/FunctionModel.php [45] => /home/github/php-reflect/src/Bartlett/Reflect/Model/MethodModel.php [46] => /home/github/php-reflect/src/Bartlett/Reflect/Model/ParameterModel.php [47] => /home/github/php-reflect/src/Bartlett/Reflect/Model/PropertyModel.php [48] => /home/github/php-reflect/src/Bartlett/Reflect/MonologConsoleLogger.php [49] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Analyser.php [50] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Cache.php [51] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Config.php [52] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Diagnose.php [53] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Diagram.php [54] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Plugin.php [55] => /home/github/php-reflect/src/Bartlett/Reflect/Output/Reflection.php [56] => /home/github/php-reflect/src/Bartlett/Reflect/PhpParser/NodeProcessor.php [57] => /home/github/php-reflect/src/Bartlett/Reflect/PhpParser/NodeProcessorAbstract.php [58] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Cache/CacheAdapterInterface.php [59] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Cache/CacheStorageInterface.php [60] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Cache/DefaultCacheStorage.php [61] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Cache/DoctrineCacheAdapter.php [62] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/CachePlugin.php [63] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Log/DefaultLogger.php [64] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/LogPlugin.php [65] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Notifier/GrowlNotifier.php [66] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/Notifier/NotifierInterface.php [67] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/NotifierPlugin.php [68] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/PluginInterface.php [69] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/PluginManager.php [70] => /home/github/php-reflect/src/Bartlett/Reflect/Plugin/ProfilerPlugin.php [71] => /home/github/php-reflect/src/Bartlett/Reflect/Sniffer/SniffAbstract.php [72] => /home/github/php-reflect/src/Bartlett/Reflect/Sniffer/SniffInterface.php [73] => /home/github/php-reflect/src/Bartlett/Reflect/Tokenizer/DefaultTokenizer.php [74] => /home/github/php-reflect/src/Bartlett/Reflect/Util/Timer.php [75] => /home/github/php-reflect/src/Bartlett/Reflect/Visitor/VisitorInterface.php [76] => /home/github/php-reflect/src/Bartlett/Reflect.php ) [Bartlett\Reflect\Analyser\LocAnalyser] => Array ( [llocClasses] => 1142 [llocByNoc] => 0 [llocByNom] => 0 [llocFunctions] => 68 [llocByNof] => 0 [llocGlobal] => 0 [classes] => 67 [functions] => 11 [methods] => 350 [cloc] => 137 [eloc] => 3293 [lloc] => 1210 [wloc] => 402 [loc] => 3832 [ccn] => 647 [ccnMethods] => 607 ) ) )
Reflect uses a Symfony EventDispatcher Component to allow you to easily extend the features list.
The EventDispatcher component allow Reflect components to communicate with each other by dispatching events and listening to them.
Reflect implement interface Bartlett\Reflect\Event\DispatcherInterface
.
You can add event listeners and event subscribers to this object.
listeners |
Callable functions that are registered on an event dispatcher for specific events. |
subscribers |
Classes that tell an event dispatcher what methods to listen to and what functions on the class to invoke when the event is triggered. Event subscribers subscribe event listeners to an event dispatcher. |
You can get the EventDispatcher of Bartlett\Reflect\Event\DispatcherInterface
by calling the getEventDispatcher()
method.
Here is an example :
<?php use Bartlett\Reflect\Client; // creates an instance of client $client = new Client(); // request for a Bartlett\Reflect\Api\Analyser $api = $client->api('analyser'); $dispatcher = $api->getEventDispatcher();
After you have the event dispatcher, you can register event listeners that listen to specific events.
Example 18.1. Add a listener that will echo out files when they are parsed
<?php use Bartlett\Reflect\Client; use Symfony\Component\EventDispatcher\GenericEvent; // creates an instance of client $client = new Client(); // request for a Bartlett\Reflect\Api\Analyser $api = $client->api('analyser'); $dispatcher = $api->getEventDispatcher(); $dispatcher->addListener( 'reflect.progress', function (GenericEvent $e) { printf( 'Parsing Data source "%s" in progress ... File "%s"' . PHP_EOL, $e['source'], $e['file']->getPathname() ); } );
Event subscribers are classes that implement interface Symfony\Component\EventDispatcher\EventSubscriberInterface
.
They are used to register one or more event listeners to methods of the class.
Event subscribers tell event dispatcher exactly which events to listen to and what method to invoke on the class.
Reflect plugins follow the event subscribers behaviors. Have a look on NotifierPlugin :
<?php use Bartlett\Reflect\Events; class NotifierPlugin implements PluginInterface, EventSubscriberInterface { public static function getSubscribedEvents() { $events = array( Events::PROGRESS => 'onNotification', Events::ERROR => 'onNotification', Events::COMPLETE => 'onNotification', ); return $events; } }
This plugin registers event listeners to the reflect.complete
event
of a Reflect parse request.
When the reflect.complete
event is emitted, the onNotification
instance method
of the plugin is invoked.
Event | Action | Informations available |
---|---|---|
reflect.progess | Before to parse a new file of the data source. |
|
reflect.success | After parsing the current file ( A cached request will not trigger this event ) |
|
reflect.error | When PHP Parser raise an error |
|
reflect.complete | When a parse request is over. |
|
In Reflect API 2, and other SAPI than CLI, you have to register a plugin, if you want to use it. In Reflect API 3, it’s no more necessary. All valid plugins defined in the JSON configuration file are automatically registered. |
You must define environment variables |
If you don’t want to use any plugins, and de-activated all at once, follow this pattern.
<?php use Bartlett\Reflect\Environment; use Bartlett\Reflect\Client; // set default values for BARTLETT_SCAN_DIR Environment::setScanDir() // set default value for BARTLETTRC putenv("BARTLETTRC=phpreflect.json"); // creates an instance of client $client = new Client(); // request for a Bartlett\Reflect\Api\Analyser $api = $client->api('analyser'); // de activate all plugins $api->activatePlugins(false); // perform request, on a data source with default analyser (structure) $dataSource = dirname(__DIR__) . '/src'; $analysers = array('structure'); // equivalent to CLI command `phpreflect analyser:run ../src` $metrics = $api->run($dataSource, $analysers);
If you want to use the Doctrine cache component, skip this section.
If you want to use your own version of cache plugin, use following pattern.
<?php namespace YourNamespace; use Bartlett\Reflect\Plugin\CachePlugin as BaseCachePlugin; class CachePlugin extends BaseCachePlugin { // all additional code you need }
And the configuration in JSON file :
{ "source-providers": [ ], "plugins": [ { "name": "Cache", "class": "YourNamespace\\CachePlugin", "options": [] } ], "analysers" : [ ], "services": [ ] }
Use one of the most famous caching solution, provided by the Doctrine project.
Use this shortcut version that is strictly equivalent to next in section file cache.
{ "source-providers": [ ], "plugins": [ { "name": "Cache", "class": "Bartlett\\Reflect\\Plugin\\CachePlugin", "options": [] } ], "analysers" : [ ], "services": [ ] }
Doctrine File backend to store your Reflect results in the local file system.
{ "source-providers": [ ], "plugins": [ { "name": "Cache", "class": "Bartlett\\Reflect\\Plugin\\CachePlugin", "options": { "adapter": "DoctrineCacheAdapter", "backend": { "class": "Doctrine\\Common\\Cache\\FilesystemCache", "args": [ "%{TEMP}/bartlett/cache" ] } } } ], "analysers" : [ ], "services": [ ] }
In the source code above, we use the standard Doctrine File cache provider, and store results in the default system temporary directory ( see php sys_get_temp_dir() function ).
See a full example with doctrine SQLite3Cache driver at https://raw.githubusercontent.com/llaville/php-reflect/master/examples/api_analyser_run_with_cache.php
If you want to use default logger Bartlett\Reflect\Plugin\Log\DefaultLogger
,
skip this section.
If you want to use your own version of log plugin, use following pattern.
<?php namespace YourNamespace; use Bartlett\Reflect\Plugin\LogPlugin as BaseLogPlugin; class LogPlugin extends BaseLogPlugin { // all additional code you need }
And the configuration in JSON file :
{ "source-providers": [ ], "plugins": [ { "name": "Logger", "class": "YourNamespace\\LogPlugin", "options": [] } ], "analysers" : [ ], "services": [ ] }
Use a solution similar to ErrorLogHandler of Monolog project.
{ "source-providers": [ ], "plugins": [ { "name": "Logger", "class": "Bartlett\\Reflect\\Plugin\\LogPlugin", "options": [] } ], "analysers" : [ ], "services": [ ] }
It logs records at Psr\Log\LogLevel::INFO
level or highter, identified
by channel name DefaultLoggerChannel
.
Use your own logger, that must be compatible PSR-3.
<?php namespace YourNamespace; use Psr\Log\AbstractLogger; class YourLogger extends AbstractLogger { public function log($level, $message, array $context = array()) { } }
And identify it in the JSON config file, as follow
{ "source-providers": [ ], "plugins": [ { "name": "Logger", "class": "YourNamespace\\LogPlugin" } ], "analysers" : [ ], "services": [ ] }
Or even
{ "source-providers": [ ], "plugins": [ { "name": "Logger", "class": "Bartlett\\Reflect\\Plugin\\LogPlugin", "options": "YourNamespace\\YourLogger" } ], "analysers" : [ ], "services": [ ] }
See full example at https://raw.githubusercontent.com/llaville/php-reflect/master/examples/api_analyser_run_with_logger.php
Use one of the most famous logging solution compatible PSR-3.
If you want to use Monolog with Reflect on CLI mode, then you should use a wrapper like this. |
<?php namespace YourNamespace; use Monolog\Logger; use Monolog\Handler\StreamHandler; class YourLogger extends Logger { public function __construct($name = 'YourLoggerChannel') { $stream = new StreamHandler('/var/logs/phpreflect.log'); parent::__construct($name, array($stream)); } }
And with JSON config file as follow
{ "source-providers": [ ], "plugins": [ { "name": "Logger", "class": "Bartlett\\Reflect\\Plugin\\LogPlugin", "options": "YourNamespace\\YourLogger" } ], "analysers" : [ ], "services": [ ] }
Two ways depending of SAPI used.
If you’re on Windows or Mac platform, you may have Growl. If you’re on Linux, the default bundled growl notifier is not for you. Skip this section.
|
You’ll add to configure your plugin in your phpreflect.json
file, as follow :
{ "name": "Notifier", "class": "Bartlett\\Reflect\\Plugin\\NotifierPlugin", "options" : "Bartlett\\CompatInfo\\Plugin\\Notifier\\GrowlNotifier" }
name
key is (since version 3.0.0-alpha1) comment only.
class
key identify the name of the class that implement the plugin (must be fully qualified).
options
key identify the name of the class that implement the notifier (must be fully qualified).
Default behaviors are :
reflect.progress
and reflect.success
events (enabled
option set to false)
reflect.error
and reflect.complete
events, and keep them displayed (sticky
option set to true).
gntp
protocol rather than udp
basic protocol.
If one or all of those behaviors does not match your need, here is how to change it.
Creates your own growl notifier class, (E.g: YourNamespace\MyGrowlNotifier
)
and put it in somewhere in your include_path
.
<?php namespace YourNamespace; use Bartlett\Reflect\Plugin\Notifier\GrowlNotifier as BaseGrowlNotifier; class MyGrowlNotifier extends BaseGrowlNotifier { public function __construct($application = 'myPhpReflect', $notifications = array(), $password = '', $options = array() { parent::__construct($application, $notifications, $password, $options); } }
We have changed the Growl Application Name to myPhpReflect
, and used the udp
protocol.
See http://growl.laurent-laville.org/ to learn more about PEAR/Net_Growl package. |
You have just to run the analyser:run
command, and you will be notified when parse is completed.
This is the standard analyser run process as defined in following script.
Default behavior is to activate all plugins that can be registered in the PluginManager
.
<?php use Bartlett\Reflect\Environment; use Bartlett\Reflect\Client; // set default values for BARTLETT_SCAN_DIR Environment::setScanDir() // set default value for BARTLETTRC putenv("BARTLETTRC=phpreflect.json"); // creates an instance of client $client = new Client(); // request for a Bartlett\Reflect\Api\Analyser $api = $client->api('analyser'); // perform request, on a data source with default analyser (structure) $dataSource = dirname(__DIR__) . '/src'; $analysers = array('structure'); // equivalent to CLI command `phpreflect analyser:run ../src` $metrics = $api->run($dataSource, $analysers); var_export($metrics);
Analysers implements the Visitor pattern in a simple and effective way to make the render of your results truly customizable.
Each Analyser
class must implement two interfaces Bartlett\Reflect\Analyser\AnalyserInterface
,
and PhpParser\NodeVisitor
.
Your first own analyser may start like that :
<?php namespace YourNamespace; use Bartlett\Reflect\Analyser\AnalyserInterface; use PhpParser\NodeVisitor; class YourAnalyser implements AnalyserInterface, NodeVisitor { // // AnalyserInterface methods // public function setSubject(Reflect $reflect) { } public function setTokens(array $tokens) { } public function setCurrentFile($path) { } public function getMetrics() { } public function getName() { } public function getNamespace() { } public function getShortName() { } // // NodeVisitor methods // public function beforeTraverse(array $nodes) { } public function enterNode(Node $node) { } public function leaveNode(Node $node) { } public function afterTraverse(array $nodes) { } }
An abstract class Your analyser became as simple like that: <?php namespace YourNamespace; use Bartlett\Reflect\Analyser\AbstractAnalyser; class YourAnalyser extends AbstractAnalyser { } |
Once all nodes of AST built by PHP-Parser were traversed, you have to publish your results
with the getMetrics()
method.
Results must be organized as a key
/values
pair array, where key
is the fully qualified name of your analyser
(E.g: YourNamespace\YourAnalyser
), and values
are your metrics (free organization).
At end of API analyser
/run
, your metrics are returned, and may be exploited as you want.
You are free to create a custom render or not.
If no output formatter is provided in namespace YourNamespace\Console\Formatter
, a simple PHP print_r()
format is returned.
This is the default format in debug mode (verbose level 3 in CLI). |
Here is a pattern of skeleton.
<?php namespace YourNamespace\Console\Formatter; use Symfony\Component\Console\Output\OutputInterface; class YourAnalyserOutputFormatter { // $output === instance of console output // $response === your metrics returned by the +YourNamespace\YourAnalyser\getMetrics()+ public function __invoke(OutputInterface $output, $response) { } }
If you want to restrict final results to one ore more criteria, the filter feature is what you are waiting for.
This feature was introduced in Reflect 3.1.0. |
Here, our goal is to remove some elements of the default report.
Script YourFilters.php
.
<?php $closure = function ($data) { $filterOnKeys = array( 'namespaces', 'interfaces', 'traits', 'classes', 'abstractClasses', 'concreteClasses', 'functions', 'namedFunctions', 'anonymousFunctions', 'classConstants', 'globalConstants', 'magicConstants', ); foreach ($data as $title => &$keys) { if (strpos($title, 'StructureAnalyser') === false) { continue; } // looking into Structure Analyser metrics only foreach ($keys as $key => $val) { if (!in_array($key, $filterOnKeys)) { unset($keys[$key]); // "removed" unsolicited values continue; } } } return $data; }; return $closure;
The filter’s file that host the |
Be carefull, with filter source code, or unwanted results may occured. |
You have ability to remove definitively ( |
Only one filter is allowed at same run, but you can combine one or more analyser rules. |
On CLI, invoke the analyser:run
command with the --filter
option. E.g:
$ phpreflect analyser:run --filter=YourFilters.php src
On other SAPI, follow example pattern like:
<?php use Bartlett\Reflect\Client; // creates an instance of client $client = new Client(); // request for a Bartlett\Reflect\Api\Analyser $api = $client->api('analyser'); // perform request, on a data source with two analysers (structure, loc) $dataSource = dirname(__DIR__) . '/src'; $analysers = array('structure', 'loc'); // filter rules on final results $closure = function ($data) { $filterOnKeys = array( 'classes', 'abstractClasses', 'concreteClasses', 'classConstants', 'globalConstants', 'magicConstants', ); foreach ($data as $title => &$keys) { if (strpos($title, 'StructureAnalyser') === false) { continue; } // looking into Structure Analyser metrics and keep classes and constants info foreach ($keys as $key => $val) { if (!in_array($key, $filterOnKeys)) { unset($keys[$key]); // "removed" unsolicited values continue; } } } return $data; }; // equivalent to CLI command `phpreflect analyser:run --filter=YourFilters.php ../src structure loc` //$metrics = $api->run($dataSource, $analysers, null, false, $closure = 'YourFilters.php'); // OR with embeded $closure code $metrics = $api->run($dataSource, $analysers, null, false, $closure);