为什么 phpstan 在 macos 和 ubuntu 上完全相同的 src 上报告更多错误?

问题描述 投票:0回答:1

我已经分叉 CodeIgniter 3 来处理 PHP 8.2 兼容性。我正在使用 PHPStan 进行静态分析,以尝试识别所有对未定义类属性的引用,这似乎是主要缺点。不幸的是,我在 MacOS 上的输出与在 Ubuntu 上的输出截然不同,我不知道为什么。 MacOS 上的 phpstan 似乎无法识别一个类的定义,

CI_DB
,这导致报告了大约 800 多个错误。我的问题是为什么 MacOS 上的错误比 Ubuntu 上的多,我该如何解决这个问题?

注意: 两台机器都安装了 PHP 8.2:

MacOS::

$ php -v
PHP 8.2.3 (cli) (built: Feb 24 2023 10:25:18) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.3, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.3, Copyright (c), by Zend Technologies

Ubuntu:

$ php -v
PHP 8.2.3 (cli) (built: Feb 14 2023 16:57:50) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.3, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.3, Copyright (c), by Zend Technologies

要重现问题,您可以从命令行运行此脚本:

mkdir ci3-dev
cd ci3-dev
### fetch CI3
curl -o ci.zip https://codeload.github.com/bcit-ci/CodeIgniter/zip/refs/heads/develop
unzip ci.zip
mv CodeIgniter-develop codeigniter
rm ci.zip
### install composer 
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
### install phpstan
./composer.phar require --dev phpstan/phpstan
### configure and run phpstan
echo -e "parameters:" >> ci.neon
echo -e "\tlevel: 2" >> ci.neon
echo -e "\tpaths:" >> ci.neon
echo -e "\t\t- codeigniter" >> ci.neon
echo -e "\texcludePaths:" >> ci.neon
echo -e "\t\tanalyse:" >> ci.neon
echo -e "\t\t\t- codeigniter/tests" >> ci.neon
echo -e "\t\t\t- codeigniter/user_guide_src" >> ci.neon
vendor/bin/phpstan clear-result-cache -c ci.neon
vendor/bin/phpstan analyse -c ci.neon > phpstan.txt

注意: 如果 composer 或 CI3 更新,此代码可能会过时。如果此脚本有问题,您可能需要手动检索 CI3调整作曲家安装步骤

phpstan 分析的输出可以在 ci3-dev/phpstan.txt 中找到。在我的 Ubuntu 机器上,这会报告 1044 错误。在我的 MacOS 机器上,它报告 1830 错误。我有一个包含 phpstan-ubuntu.txt、phpstan-mac.txt 的 zip 文件,以及这两个文件的差异文件 phpstan-diff.txt,但这些文件每个大约 200K,太大而无法在此处发布。我提供了这个示例差异来尝试表达我认为的主要问题,即 MacOS 不知何故看不到类的声明

CI_DB
system/libraries/Profiler.php:

的 ubuntu 输出
 ------ -----------------------------------------------------
  Line   system/libraries/Profiler.php
 ------ -----------------------------------------------------
  166    Call to an undefined method object::elapsed_time().
  521    Access to an undefined property object::$lang.
  521    Access to an undefined property object::$lang.
  521    Access to an undefined property object::$lang.
  521    Access to an undefined property object::$lang.
  521    Access to an undefined property object::$lang.
 ------ -----------------------------------------------------

很短,而 MacOS 输出要长一些,因为它不知何故找不到 CI_DB:

 ------ ---------------------------------------------------------------------
  Line   system/libraries/Profiler.php
 ------ ---------------------------------------------------------------------
  166    Call to an undefined method object::elapsed_time().
  207    Class CI_DB not found.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  215    Class CI_DB not found.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  247    Access to property $queries on an unknown class CI_DB.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  248    Access to property $query_times on an unknown class CI_DB.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  260    Access to property $database on an unknown class CI_DB.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  261    Access to property $queries on an unknown class CI_DB.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  264    Access to property $queries on an unknown class CI_DB.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  271    Access to property $queries on an unknown class CI_DB.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  273    Access to property $query_times on an unknown class CI_DB.
         💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
  521    Access to an undefined property object::$lang.
  521    Access to an undefined property object::$lang.
  521    Access to an undefined property object::$lang.
  521    Access to an undefined property object::$lang.
  521    Access to an undefined property object::$lang.
 ------ ---------------------------------------------------------------------
macos ubuntu codeigniter-3 phpstan php-8.2
1个回答
0
投票

我不确定 Linux 和 macOS 之间的区别,但我认为 macOS 上的行为更符合预期。

CI_DB 类在

codeigniter/system/database/DB.php
内部以非常非常规的方式定义
function &DB
声明:

if ( ! class_exists('CI_DB', FALSE))
    {
        /**
         * CI_DB
         *
         * Acts as an alias for both CI_DB_driver and CI_DB_query_builder.
         *
         * @see CI_DB_query_builder
         * @see CI_DB_driver
         */
        class CI_DB extends CI_DB_query_builder {}
    }

这与使用 PSR-4 的现代 PHP 项目标准相去甚远,或者至少将类声明作为其文件中的顶级符号。这就是为什么 PHPStan 没有开箱即用的类。

但是通过查看 CodeIgniter 是自举的,定义全局常量,然后手动加载文件,我能够走得更远。您可以在名为

phpstan-bootstrap.php
的文件中使用以下代码进行尝试:

// copied and modified from codeigniter/index.php

define('ENVIRONMENT', 'development');

// The name of THIS file
define('SELF', __DIR__ . '/codeigniter/index.php');

// Path to the system directory
define('BASEPATH', __DIR__ . '/codeigniter/system/');

// Path to the front controller (this file) directory
define('FCPATH', __DIR__ . '/codeigniter/');

// Name of the "system" directory
define('SYSDIR', basename(BASEPATH));

define('APPPATH', __DIR__ . '/codeigniter/application/');

define('VIEWPATH', __DIR__ . '/codeigniter/application/views/');


require_once __DIR__ . '/codeigniter/system/core/Common.php';
require_once __DIR__ . '/codeigniter/system/database/DB.php';
DB();

然后将其放入您的

ci.neon
中的
parameters
部分:

    bootstrapFiles:
        - phpstan-bootstrap.php

在我的电脑上,分析现在失败了:

PHP Warning:  mysqli::real_connect(): (HY000/2002): No such file or directory in /Users/ondrej/Downloads/ci3-dev/codeigniter/system/database/drivers/mysqli/mysqli_driver.php on line 211
Warning: mysqli::real_connect(): (HY000/2002): No such file or directory in /Users/ondrej/Downloads/ci3-dev/codeigniter/system/database/drivers/mysqli/mysqli_driver.php on line 211
RuntimeException thrown in /Users/ondrej/Downloads/ci3-dev/codeigniter/system/database/DB_driver.php on line 434 while loading bootstrap file /Users/ondrej/Downloads/ci3-dev/phpstan-bootstrap.php: Unable to connect to the database.

不幸的是,我无法进一步了解,因为我的机器上没有任何数据库,但如果你设法解决了这个问题,你应该能够进一步分析。

© www.soinside.com 2019 - 2024. All rights reserved.