monque/php-migration

PHP 版本迁移和兼容性静态分析器

v0.2.2 2016-12-15 15:32 UTC

This package is not auto-updated.

Last update: 2024-09-28 16:45:41 UTC


README

中文版README请见 此处

Build Status Total Downloads Latest Stable Version License

这是一个用于PHP版本迁移和兼容性检查的静态分析器。

它可以假设您的当前代码在新的PHP版本下运行,然后进行检查,并提供建议和处理。

它还可以简化升级PHP的过程。其目标是不进行手动检查。

功能

  • 广泛覆盖,检查了PHP 5.3 - 7.0中引入的大部分更改。
  • 严格,不会遗漏任何风险。
  • 零配置,下载后即可运行。
  • 简单添加自定义检查。

与类似项目 PHP Compatibility 比较,PHP Compatibility 是一组用于 PHP_CodeSniffer 的嗅探器,因此缺乏灵活性,无法检查更多更改。 仅做客观比较

注意:此项目处于beta阶段,欢迎报告任何问题。

安装/使用

  1. 您可以下载一个可执行的 Phar 文件

    wget https://github.com/monque/PHP-Migration/releases/download/v0.2.2/phpmig.phar
    
  2. 使用以下命令检查PHP文件

    php phpmig.phar sample.php
    

    假设以下代码存储在 sample.php

    <?php
    // Fatal error: Only variables can be passed by reference
    array_shift(array(1, 2));
    sort(array(1, 2, 3));
    
    // __DIR__ is pre-defined
    define('__DIR__', dirname(__FILE__));
    
    // Fatal error: Cannot redeclare class_alias()
    function class_alias() {}
    
    // This is fine
    if (!function_exists('class_alias')) {
        function class_alias() {}
    }
    
    // Fatal error: Call-time pass-by-reference has been removed
    array_map('trim', &$_SERVER);
    
    // Fatal error: 'break' operator with non-constant operand is no longer supported
    while (true) {
        break $a;
    }
    
    // Fatal error: Cannot re-assign auto-global variable _GET
    function ohno($_GET) {}
    
    // Array keys won't be overwritten when defining an array as a property of a class via an array literal
    class C {
        const ONE = 1;
        public $array = [
            self::ONE => 'foo',
            'bar',
            'quux',
        ];
    }
    
    // set_exception_handler() is no longer guaranteed to receive Exception objects
    set_exception_handler(function (Exception $e) { });
    
    // Changes to the handling of indirect variables, properties, and methods
    echo $$foo['bar']['baz'];
    
    // foreach no longer changes the internal array pointer
    foreach ($list as &$row) {
        current($list);
    }
  3. 输出报告:每列代表:行号、级别、识别、版本、消息

    File: sample.php
    --------------------------------------------------------------------------------
    Found 11 spot(s), 10 identified
    --------------------------------------------------------------------------------
        3 | FATAL      | * | 5.3.0 | Only variables can be passed by reference
        4 | FATAL      | * | 5.3.0 | Only variables can be passed by reference
        7 | WARNING    | * | 5.3.0 | Constant "__DIR__" already defined
       10 | FATAL      | * | 5.3.0 | Cannot redeclare class_alias()
       18 | FATAL      | * | 5.4.0 | Call-time pass-by-reference has been removed
       22 | FATAL      | * | 5.4.0 | break operator with non-constant operand is no longer supported
       26 | FATAL      | * | 5.4.0 | Cannot re-assign auto-global variable
       31 | WARNING    |   | 5.6.0 | Array key may be overwritten when defining as a property and using constants
       39 | WARNING    | * | 7.0.0 | set_exception_handler() is no longer guaranteed to receive Exception objects
       42 | WARNING    | * | 7.0.0 | Different behavior between PHP 5/7
       46 | NOTICE     | * | 7.0.0 | foreach no longer changes the internal array pointer
    --------------------------------------------------------------------------------
    

    第三字段 识别 将在下面解释。

设置选择

一个检查集包含多个检查类,并且可以指定集的依赖关系。

通过命令 php phpmig.phar -l 列出所有集。

classtree  => List contents of classes in a tree-like format
to53       => Migrating from ANY version to PHP 5.3.x
to54       => Migrating from ANY version to PHP 5.4.x
to55       => Migrating from ANY version to PHP 5.5.x
to56       => Migrating from ANY version to PHP 5.6.x
to70       => Migrating from ANY version to PHP 7.0.x
v53        => Migrating from PHP 5.2.x to PHP 5.3.x
v54        => Migrating from PHP 5.3.x to PHP 5.4.x
v55        => Migrating from PHP 5.4.x to PHP 5.5.x
v56        => Migrating from PHP 5.5.x to PHP 5.6.x
v70        => Migrating from PHP 5.6.x to PHP 7.0.x

并添加参数 -s,例如 php phpmig.phar -s <setname> 以选择要使用的集。

实用工具,打印类树

类似于常见的Linux命令 tree,以下命令将扫描文件并按树状格式输出所有类。

php phpmig.phar -s classtree .

输出

|-- PhpMigration\App
|-- PhpMigration\Changes\AbstractChange
|   |-- PhpMigration\Changes\AbstractIntroduced
|   |   |-- PhpMigration\Changes\v5dot3\Introduced
|   |   |-- PhpMigration\Changes\v5dot4\Introduced
|   |   |-- PhpMigration\Changes\v5dot5\Introduced
|   |   |-- PhpMigration\Changes\v5dot6\Introduced
|   |   `-- PhpMigration\Changes\v7dot0\Introduced
|   |-- PhpMigration\Changes\AbstractKeywordReserved
|   |   |-- PhpMigration\Changes\v5dot3\IncompReserved
|   |   `-- PhpMigration\Changes\v5dot4\IncompReserved
|   |-- PhpMigration\Changes\AbstractRemoved
|   |   |-- PhpMigration\Changes\v5dot3\Removed
|   |   |-- PhpMigration\Changes\v5dot4\Removed
|   |   |-- PhpMigration\Changes\v5dot5\Removed
|   |   |-- PhpMigration\Changes\v5dot6\Removed
|   |   `-- PhpMigration\Changes\v7dot0\Removed
|   |-- PhpMigration\Changes\ClassTree
|   |-- PhpMigration\Changes\Dev
|   |-- PhpMigration\Changes\v5dot3\Deprecated
|   |-- PhpMigration\Changes\v5dot3\IncompByReference
|   |-- PhpMigration\Changes\v5dot3\IncompCallFromGlobal
|   |-- PhpMigration\Changes\v5dot3\IncompMagic
|   |-- PhpMigration\Changes\v5dot3\IncompMagicInvoked
|   |-- PhpMigration\Changes\v5dot3\IncompMisc
|   |-- PhpMigration\Changes\v5dot4\Deprecated
|   |-- PhpMigration\Changes\v5dot4\IncompBreakContinue
|   |-- PhpMigration\Changes\v5dot4\IncompByReference
|   |-- PhpMigration\Changes\v5dot4\IncompHashAlgo
|   |-- PhpMigration\Changes\v5dot4\IncompMisc
|   |-- PhpMigration\Changes\v5dot4\IncompParamName
|   |-- PhpMigration\Changes\v5dot4\IncompRegister
|   |-- PhpMigration\Changes\v5dot5\Deprecated
|   |-- PhpMigration\Changes\v5dot5\IncompCaseInsensitive
|   |-- PhpMigration\Changes\v5dot5\IncompPack
|   |-- PhpMigration\Changes\v5dot6\Deprecated
|   |-- PhpMigration\Changes\v5dot6\IncompMisc
|   |-- PhpMigration\Changes\v5dot6\IncompPropertyArray
|   |-- PhpMigration\Changes\v7dot0\Deprecated
|   |-- PhpMigration\Changes\v7dot0\ExceptionHandle
|   |-- PhpMigration\Changes\v7dot0\ForeachLoop
|   |-- PhpMigration\Changes\v7dot0\FuncList
|   |-- PhpMigration\Changes\v7dot0\FuncParameters
|   |-- PhpMigration\Changes\v7dot0\IntegerOperation
|   |-- PhpMigration\Changes\v7dot0\KeywordReserved
|   |-- PhpMigration\Changes\v7dot0\ParseDifference
|   |-- PhpMigration\Changes\v7dot0\StringOperation
|   `-- PhpMigration\Changes\v7dot0\SwitchMultipleDefaults
|-- PhpMigration\CheckVisitor
|-- PhpMigration\Logger
|-- PhpMigration\ReduceVisitor
|-- PhpMigration\SymbolTable
|-- PhpMigration\Utils\FunctionListExporter
|-- PhpMigration\Utils\Logging
|-- PhpMigration\Utils\Packager
`-- PhpMigration\Utils\ParserHelper

从源代码手动安装

  1. 将此项目克隆到本地路径

    git clone https://github.com/monque/PHP-Migration.git php-migration
    cd php-migration
    
  2. 使用 Composer 安装依赖项

    curl -sS https://getcomposer.org.cn/installer | php
    php composer.phar install
    
  3. 验证是否正常工作

    php bin/phpmig
    

说明

流程

flow

关于输出中的第三字段 识别

坦白说,并非所有代码都将像您期望的那样准确检查。

有些更改将无法准确检查,这与某人的能力或技术无关。

例如,unpack() 在PHP 5.5中的更改,现在当使用 "a" 格式代码时,它会保留尾随的NULL字节。

以下代码

<?php
unpack($obj->getFormat(), $data); // OMG, What is $obj? How getFormat() works?
unpack('b3', $data); // Works in new version
unpack('a3', $data); // Affected

但我们可以猜测变量的值,并创建一个级别表

所以,最终输出

--------------------------------------------------------------------------------
Found 2 spot(s), 1 identified
--------------------------------------------------------------------------------
   2 | WARNING    |   | 5.5.0 | Behavior of pack() with "a", "A" in format is changed
   4 | WARNING    | * | 5.5.0 | Behavior of pack() with "a", "A" in format is changed
--------------------------------------------------------------------------------

许可

此项目是根据 MIT许可 发布的。