Phan es un analizador estático para PHP que prefiere minimizar los falsos positivos. Phan intenta demostrar la incorrección en lugar de la corrección.
Phan busca problemas comunes y verificará la compatibilidad de tipos en varias operaciones cuando la información de tipos esté disponible o pueda deducirse. Phan tiene un conocimiento bueno (pero no completo) del control de flujo y puede rastrear valores en algunos casos de uso (por ejemplo, matrices, números enteros y cadenas).
La forma más sencilla de utilizar Phan es a través de Composer.
composer require phan/phan
Con Phan instalado, querrás crear un archivo .phan/config.php
en tu proyecto para decirle a Phan cómo analizar tu código fuente. Una vez configurado, puede ejecutarlo a través de ./vendor/bin/phan
.
Phan 5 depende de PHP 7.2+ con la extensión php-ast (se prefiere 1.1.1+) y admite el análisis de la sintaxis de la versión PHP 7.0-8.2. Las instrucciones de instalación para php-ast se pueden encontrar aquí. (Phan se puede usar sin php-ast usando la opción CLI --allow-polyfill-parser
, pero existen ligeras diferencias en el análisis de los comentarios del documento)
La Wiki tiene más información sobre el uso de Phan.
Phan puede realizar los siguientes tipos de análisis:
object
, void
, iterable
, ?T
, [$x] = ...;
, compensaciones de cadenas negativas, múltiples capturas de excepciones, etc.)--dead-code-detection
)--unused-variable-detection
)--redundant-condition-detection
)use
no utilizadas. Estos y algunos otros tipos de problemas se pueden solucionar automáticamente con --automatic-fix
.@template
).int[]
, UserObject[]
, array<int,UserObject>
, etc.array{key:string,otherKey:?stdClass}
, etc. (internamente y en etiquetas PHPDoc). Esto también admite la indicación de que los campos de una forma de matriz son opcionales a través de array{requiredKey:string,optionalKey?:string}
(útil para @param
)@deprecated
para clases, métodos y funciones obsoletos@internal
para elementos (como una constante, función, clase, constante de clase, propiedad o método) como internos del paquete en el que está definido.@suppress <ISSUE_TYPE>
para suprimir problemas.@property <union_type> <variable_name>
)@method <union_type> <method_name>(<union_type> <param1_name>)
)class_alias
(experimental, desactivada de forma predeterminada)@phan-closure-scope
(ejemplo)array_map
, array_filter
y otras funciones de matriz internas.pcntl
)Consulte Tipos de problemas de Phan para obtener descripciones y ejemplos de todos los problemas que Phan puede detectar. Eche un vistazo a PhanIssue para ver la definición de cada tipo de error.
Eche un vistazo al Tutorial para analizar una base de código grande y descuidada para tener una idea de cómo podría ser para usted el proceso de realizar un análisis continuo.
Phan se puede utilizar desde varios editores e IDE para comprobar errores, admitir "ir a definición", etc. a través del protocolo de servidor de idiomas. Los editores y las herramientas también pueden solicitar el análisis de archivos individuales en un proyecto utilizando el modo Daemon más simple.
Consulte el directorio de pruebas para ver algunos ejemplos de las distintas comprobaciones.
Phan es imperfecto y no debería usarse para demostrar que su sistema de guía de cohetes basado en PHP está libre de defectos.
Los complementos han proporcionado funciones de análisis adicionales.
{ throw new Exception("Message"); return $value; }
)*printf()
con los argumentos proporcionados (así como verificar errores comunes)preg_*()
sean válidas@suppress
que ya no son necesarias.Ejemplo: complementos de Phan para autoanálisis.
Después de instalar Phan, es necesario configurar Phan con detalles sobre dónde encontrar código para analizar y cómo analizarlo. La forma más sencilla de decirle a Phan dónde encontrar el código fuente es crear un archivo .phan/config.php
. Un archivo .phan/config.php
simple podría verse similar al siguiente.
<?php
/ * *
* This configuration will be read and overlaid on top of the
* default configuration . Command line arguments will be applied
* after this file is read .
* /
return [
// Supported values : `'5.6'` , `'7.0'` , `'7.1'` , `'7.2'` , `'7.3'` , `'7.4'` ,
// `'8.0'` , `'8.1'` , `'8.2'` , `'8.3'` , `null` .
// If this is set to `null` ,
// then Phan assumes the PHP version which is closest to the minor version
// of the php executable used to execute Phan .
" target_php_version " => null ,
// A list of directories that should be parsed for class and
// method information . After excluding the directories
// defined in exclude_analysis_directory_list , the remaining
// files will be statically analyzed for errors .
//
// Thus , both first - party and third - party code being used by
// your application should be included in this list .
' directory_list ' => [
' src ' ,
' vendor/symfony/console ' ,
],
// A directory list that defines files that will be excluded
// from static analysis , but whose class and method
// information should be included .
//
// Generally , you ' ll want to include the directories for
// third - party code ( such as "vendor/" ) in this list .
//
// n . b .: If you ' d like to parse but not analyze 3 rd
// party code , directories containing that code
// should be added to the `directory_list` as
// to `exclude_analysis_directory_list` .
" exclude_analysis_directory_list " => [
' vendor/ '
],
// A list of plugin files to execute .
// Plugins which are bundled with Phan can be added here by providing their name
// ( e . g . 'AlwaysReturnPlugin' )
//
// Documentation about available bundled plugins can be found
// at https : // github . com / phan / phan / tree / v5 / . phan / plugins
//
// Alternately , you can pass in the full path to a PHP file
// with the plugin ' s implementation .
// ( e . g . 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php' )
' plugins ' => [
// checks if a function , closure or method unconditionally returns .
// can also be written as 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'
' AlwaysReturnPlugin ' ,
' DollarDollarPlugin ' ,
' DuplicateArrayKeyPlugin ' ,
' DuplicateExpressionPlugin ' ,
' PregRegexCheckerPlugin ' ,
' PrintfCheckerPlugin ' ,
' SleepCheckerPlugin ' ,
// Checks for syntactically unreachable statements in
// the global scope or function bodies .
' UnreachableCodePlugin ' ,
' UseReturnValuePlugin ' ,
' EmptyStatementListPlugin ' ,
' LoopVariableReusePlugin ' ,
],
];
Eche un vistazo a Creación de un archivo de configuración y fortalecimiento incremental del análisis para obtener más detalles.
Al ejecutar phan --help
se mostrará información de uso y opciones de línea de comandos.
Phan lee y comprende la mayoría de las anotaciones de tipo PHPDoc, incluidos los tipos de unión (como int|MyClass|string|null
) y tipos de matrices genéricos (como int[]
o string[]|MyClass[]
o array<int,MyClass>
).
Eche un vistazo a Anotar su código fuente y Acerca de los tipos de unión para obtener ayuda para comenzar a definir tipos en su código.
Phan admite anotaciones de estilo (int|string)[]
y las representa internamente como int[]|string[]
(Ambas anotaciones se tratan como una matriz que puede tener números enteros y/o cadenas). Cuando tenga matrices de tipos mixtos, simplemente use array
.
El siguiente código muestra las diversas anotaciones que se admiten.
/ * *
* @ return void
* /
function f () {}
/ * * @ deprecated * /
class C {
/ * * @ var int * /
const C = 42 ;
/ * * @ var string [] | null * /
public $ p = null ;
/ * *
* @ param int | null $ p
* @ return string [] | null
* /
public static function f ( $ p ) {
if ( is_null ( $ p )) {
return null ;
}
return array_map (
/ * * @ param int $ i * /
function ( $ i ) {
return " thing $ i " ;
},
range ( 0 , $ p )
);
}
}
Al igual que en PHP, cualquier tipo puede anularse en la declaración de función, lo que también significa que se permite pasar un nulo para ese parámetro.
Phan verifica el tipo de cada elemento de las matrices (incluidas claves y valores). En términos prácticos, esto significa que [$int1=>$int2,$int3=>$int4,$int5=>$str6]
se ve como array<int,int|string>
, que Phan representa como array<int,int>|array<int,string>
. [$strKey => new MyClass(), $strKey2 => $unknown]
se representará como array<string,MyClass>|array<string,mixed>
.
[12,'myString']
se representarán internamente como formas de matriz como array{0:12,1:'myString'}
Este analizador estático no rastrea las inclusiones ni intenta descubrir la magia del cargador automático. Trata todos los archivos que le lanzas como una gran aplicación. Para código encapsulado en clases, esto funciona bien. Para el código que se ejecuta en el ámbito global, se vuelve un poco complicado porque el orden es importante. Si tiene un index.php
que incluye un archivo que establece un montón de variables globales y luego intenta acceder a ellas después de include(...)
en index.php
el analizador estático no sabrá nada sobre ellas.
En términos prácticos, esto simplemente significa que debe colocar sus puntos de entrada y cualquier archivo que establezca elementos en el alcance global en la parte superior de su lista de archivos. Si tiene un config.php
que establece variables globales que todo lo demás necesita, entonces debe colocarlo primero en la lista seguido de sus diversos puntos de entrada, luego todos los archivos de su biblioteca que contienen sus clases.
Echa un vistazo a la Guía del desarrollador de Phan para obtener ayuda para empezar a piratear Phan.
Cuando encuentre un problema, tómese el tiempo para crear un pequeño fragmento de código de reproducción que ilustre el error. Y una vez que hayas hecho eso, arréglalo. Luego, convierta su fragmento de código en una prueba y agréguelo a las pruebas, luego ./test
y envíe un PR con su corrección y prueba. Alternativamente, puede abrir un problema con detalles.
Para ejecutar las pruebas unitarias de Phan, simplemente ejecute ./test
.
Para ejecutar todas las pruebas unitarias y de integración de Phan, ejecute ./tests/run_all_tests.sh
Estamos comprometidos a fomentar una comunidad acogedora. Cualquier participante y colaborador debe cumplir con nuestro Código de conducta.
Esto requiere una versión actualizada de Firefox/Chrome y al menos 4 GB de RAM libre. (esta es una descarga de 15 MB)
Ejecute Phan completamente en su navegador.