我已经分叉 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.
------ ---------------------------------------------------------------------
我不确定 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.
不幸的是,我无法进一步了解,因为我的机器上没有任何数据库,但如果你设法解决了这个问题,你应该能够进一步分析。