7

我实际上有兴趣确保我们的代码库没有错误,这些错误会被 PHP 的内置错误检查警告,但我想看看 E_STRICT 究竟执行了什么。推而广之,什么是 PHP 的“严格标准”?我查看了但找不到完整的列表。

我从经验中了解到的一些严格标准:

  • 警告不要静态调用非静态方法
  • 警告不兼容的子类函数签名
  • 警告不要通过引用分配值

我所知道的关于 E_STRICT 的唯一信息是它会警告可能破坏前向兼容性的代码,但我不确定这具体意味着什么。

有没有很好的资源来提供这方面的信息?

4

1 回答 1

12

E_STRICT和“严格标准”是一回事。(并且它们在 PHP 7 中被删除。)

该文档目前没有特定警告列表,但我们可以通过搜索PHP 源代码E_STRICT轻松构建一个。

下面的列表(我认为在 PHP 5.6 中是准确的)是通过以下方法在 Unix 系统上形成的:

  1. 克隆 PHP Git 存储库:

    git clone https://github.com/php/php-src
    
  2. 签出版本 5.6.0:

    cd php-src
    git checkout PHP-5.6.0
    
  3. 搜索包含以下内容的所有 C 文件(带有.h.c扩展名的文件)E_STRICT

    grep --include=*.[ch] -rl . -e E_STRICT
    
  4. 手动查看 (21) 个匹配的文件中的每一个以查找发出E_STRICT警告的代码,尝试推断发出警告的情况(我不是 C 程序员,但对此并不难猜测东西,尤其是代码中的人类可读错误消息来指导你)然后在交互式 PHP shell 中测试它们以确保我是对的。

鉴于上述方法略显粗糙,并且取决于E_STRICT可以在所有发出警告的位置旁边的源代码中找到的假设,我可能错过了一些东西 - 但希望这E_STRICT至少接近于综合清单。

PHP 中导致 E_STRICT 警告的内容

  1. mktime()不带参数调用

    php > mktime();
    PHP 严格标准:mktime():您应该使用 time() 函数
    而是在第 1 行的 php shell 代码中
  2. 使用资源作为数组索引

    php > $file_pointer = fopen('/dev/null', 'r'); 
    php > $array = [3,4,5,6]; 
    php > $array[$file_pointer];
    PHP 严格标准:资源 ID#2 用作偏移量,转换为整数 (2)
    在第 1 行的 php shell 代码中
  3. 将 UTF-8 以外的多字节编码传递给htmlentities

    php > htmlentities('qwertyuiop', 0, 'BIG5');
    PHP 严格标准:htmlentities():只有基本的实体替换是
    支持 UTF-8 以外的多字节编码;功能是
    相当于第 1 行 php shell 代码中的 htmlspecialchars
  4. 声明一个抽象的 静态方法

    php >抽象类 Foo { 静态抽象函数 bar(); }
    PHP 严格标准:静态函数 Foo::bar() 不应该是抽象的
    第 1 行的 php shell 代码
  5. __construct用一个方法和一个以该类命名的旧式构造函数声明一个类

    php > class MyClass { 
    php {     function MyClass () {} 
    php {     function __construct () {} 
    php { }
    PHP 严格标准:为类重新定义已定义的构造函数
    第 3 行 php shell 代码中的 MyClass
  6. 调用mysqli_next_resultmysqli::next_result在没有准备下一个结果的 Mysqli 连接对象上

    php > $conn = mysqli_connect('127.0.0.1', 'root'); 
    php > mysqli_multi_query($conn, "SELECT 'first'; SELECT 'second';"); 
    php > echo mysqli_use_result($conn)->fetch_row()[0];
    第一的
    php > mysqli_next_result($conn); 
    php > echo mysqli_use_result($conn)->fetch_row()[0];
    第二
    php > mysqli_next_result($conn);
    PHP 严格标准:mysqli_next_result():没有下一个结果集。
    请调用 mysqli_more_results()/mysqli::more_results() 检查是否
    在第 1 行的 php shell 代码中调用此函数/方法
  7. 覆盖子类中的方法以将不同数量的参数传递给其父类中的同一方法

    php > class A { public function foo ($x) {} } 
    php > class B extends A { public function foo () {} }
    PHP 严格标准:B::foo() 的声明应与
    A::foo($x) 在第 1 行的 php shell 代码中
    php >类 C 扩展 A { public function foo ($x, $y) {} }
    PHP 严格标准:C::foo() 的声明应与
    A::foo($x) 在第 1 行的 php shell 代码中
  8. 在 trait 和使用它的类中以兼容的方式声明相同的属性。这个实际上有很好的记录

    如果一个 trait 定义了一个属性,那么一个类不能定义一个同名的属性,否则会发出错误。E_STRICT如果类定义兼容(相同的可见性和初始值),则为致命错误,否则为致命错误。

    Example #12 冲突解决

    <?php
    trait PropertiesTrait {
        public $same = true;
        public $different = false;
    }
    
    class PropertiesExample {
        use PropertiesTrait;
        public $same = true; // Strict Standards
        public $different = true; // Fatal error
    }
    ?>
    

    严格模式警告的示例:

    php > trait PropertiesTrait { 
    php {     public $same = true; 
    php { } 
    php >类 PropertiesExample { 
    php {    使用 PropertiesTrait; 
    php {    公共$相同=真;
    php { }
    PHP 严格标准:PropertiesExample 和 PropertiesTrait 定义
    PropertiesExample 的组成中的相同属性 ($same)。这有可能
    不兼容,为了提高可维护性考虑使用访问器
    而是使用特征中的方法。类是在第 4 行的 php shell 代码中组成的
  9. 静态调用非静态方法

    php > class Foo { function bar() {} } 
    php > Foo::bar();
    PHP 严格标准:不应调用非静态方法 Foo::bar()
    静态地在第 1 行的 php shell 代码中
  10. 非静态地引用静态属性

    php > class Cow { static public $noise = 'moo'; } 
    php > $cow = 新牛;
    php > $cow->noise = "MOOOOO";
    PHP 严格标准:将静态属性 Cow::$noise 作为非静态访问
    在第 1 行的 php shell 代码中
  11. 通过引用直接传递函数调用的结果。

    php >函数 foo () { 返回 1; } 
    php >函数 bar (&$some_arg) {} 
    php > bar(foo());
    PHP 严格标准:在 php 中只能通过引用传递变量
    第 1 行的 shell 代码
    php > $var = &foo();
    PHP 严格标准:只能通过引用分配变量
    第 1 行的 php shell 代码

    请注意,通过引用传递其他非变量,如文字或常量,是一个致命错误,而不是E_STRICT

于 2014-09-13T18:24:21.550 回答