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 0Another 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.73Let’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 0This 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);