Php &引用;无法重新声明函数“;而不是",;无法重新声明类“;

Php &引用;无法重新声明函数“;而不是",;无法重新声明类“;,php,fatal-error,Php,Fatal Error,我读过: 我们有以下错误: PHP Fatal error: Cannot redeclare fcXXX() (previously declared in /xx.class.php:3007) in /xx.class.php on line 3014 对第3014行。在/xx.class.php的源代码中,函数fcXXX()前面有一些类声明,类似(简而言之): 因此,我不明白的是,在致命“无法重新声明函数PHP”之前,应该有一个类型为“PHP致命错误:无法重新声明类”的错

我读过:

我们有以下错误:

 PHP Fatal error:  Cannot redeclare fcXXX()
 (previously declared in /xx.class.php:3007) in /xx.class.php on line 3014
第3014行
。在
/xx.class.php
的源代码中,函数
fcXXX()
前面有一些类声明,类似(简而言之):

因此,我不明白的是,在致命“
无法重新声明函数PHP
”之前,应该有一个类型为“
PHP致命错误:无法重新声明类”的错误

更奇怪的是,如果仔细阅读,问题会出现在函数声明的末尾。以下是代码和行:

3007 function fcXXX($p) {
3008     $a = strpos($p, '.');
3009     if ($a) {
3010         return trim(substr($p, $a+1));
3011     } else {
3012         return trim($p);
3013     }
3014 }
两件奇怪的事:

  • 在函数中没有“包含”或“要求”之类的东西,所以理论上不可能有这种错误
  • 3014引发行3007中的错误(请仔细查看之前的详细错误)

  • 有没有人曾经遇到过这个问题,在哪里检查/测试以解决它?(请不要评论如何优化/代码有多糟糕,因为它不是我的,我不会修改它)

    您可能在递归地
    包含
    要求
    -ing定义。你设置自动装弹机了吗?您知道它们是如何工作的吗?因为您可能希望为每个类定义(尽快)创建一个文件。
    考虑这一点:

    //index.php
    include('someFile.php');
    include('xx.class.php');
    
    //someFile:
    include('xx.class.php');//ERROR
    
    //or even worse, in xx.Class.php:
    include('someFile.php');//includes file that includes this file, which will include someFile again, which includes this file, which...
    
    要避免这种情况,请使用
    包含一次
    要求一次
    。这样可以避免重复包含同一文件

    至于错误顺序的原因:
    我认为,在得到错误cannot Redecare类之前出现错误“cannot Redecare function”的主要原因是PHP编译代码的方式。
    PHP不再让您的代码保持原样。你的代码被编译成字节码,所以。。。我们应该说。。。在这个过程中发生了很大的变化
    在PHP开始解析类之前,只需解析函数。为什么?这很简单,因为PHP类方法本质上也是函数。
    使用
    zend_object_handlers
    指针调用它们,当调用一个方法时,传递
    zval
    ,并分配
    zend_class_条目
    ,以便
    zend_函数
    能够访问范围内的所有数据(所有对象属性和方法以及您拥有的内容)。我不知道您的C知识如何,但如果您想测试它:

    ZEND_API zval* zend_call_method(
        zval **object_pp,
        zend_class_entry *obj_ce,
        zend_function **fn_proxy,
        const char *function_name,
        int function_name_len,
        zval **retval_ptr_ptr,
        int param_count,
        zval* arg1,
        zval* arg2 TSRMLS_DC
    ) {
      int result;
      zend_fcall_info fci;
      zval z_fname;
      zval *retval;
      HashTable *function_table;
    
      zval **params[2];
    
      params[0] = &arg1;
      params[1] = &arg2;
    
      fci.size = sizeof(fci);
      /* fci.function_table = NULL;
       * will be read form zend_class_entry of object if needed
       */
      fci.object_ptr = object_pp ? *object_pp : NULL;
      fci.function_name = &z_fname;
      fci.retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
      fci.param_count = param_count;
      fci.params = params;
      fci.no_separation = 1;
      fci.symbol_table = NULL;
    
      if (!fn_proxy && !obj_ce) {
          /* no interest in caching and no information
           * already present that is needed later inside
           * zend_call_function.
           */
          ZVAL_STRINGL(&z_fname, function_name, function_name_len, 0);
          fci.function_table = !object_pp ? EG(function_table) : NULL;
          result = zend_call_function(&fci, NULL TSRMLS_CC);
      } else {
          zend_fcall_info_cache fcic;
    
          fcic.initialized = 1;
          if (!obj_ce) {
              obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
          }
          if (obj_ce) {
              function_table = &obj_ce->function_table;
          } else {
              function_table = EG(function_table);
          }
          if (!fn_proxy || !*fn_proxy) {
              if (zend_hash_find(
                  function_table, function_name,
                  function_name_len+1,
                  (void **) &fcic.function_handler) == FAILURE
              ) {
                  /* error at c-level */
                  zend_error(
                      E_CORE_ERROR,
                      "Couldn't find implementation for method %s%s%s",
                      obj_ce ? obj_ce->name : "",
                      obj_ce ? "::" : "", function_name
                  );
              }
              if (fn_proxy) {
                  *fn_proxy = fcic.function_handler;
              }
          } else {
              fcic.function_handler = *fn_proxy;
          }
          fcic.calling_scope = obj_ce;
          if (object_pp) {
              fcic.called_scope = Z_OBJCE_PP(object_pp);
          } else if (obj_ce &&
                     !(EG(called_scope) &&
                       instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) {
              fcic.called_scope = obj_ce;
          } else {
              fcic.called_scope = EG(called_scope);
          }
          fcic.object_ptr = object_pp ? *object_pp : NULL;
          result = zend_call_function(&fci, &fcic TSRMLS_CC);
      }
      if (result == FAILURE) {
           /* error at c-level */
           if (!obj_ce) {
               obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
           }
           if (!EG(exception)) {
               zend_error(
                   E_CORE_ERROR,
                   "Couldn't execute method %s%s%s",
                   obj_ce ? obj_ce->name : "",
                   obj_ce ? "::" : "", function_name
               );
           }
       }
       if (!retval_ptr_ptr) {
           if (retval) {
               zval_ptr_dtor(&retval);
           }
           return NULL;
       }
       return *retval_ptr_ptr;
    }
    
    正如您在这里看到的,为了使方法可以调用,必须定义所有的
    zend_函数。由于构造函数也是一个函数,我怀疑
    xx.Class.php
    文件中的所有函数都已解析。由于这些方法是在它们自己的(类)范围内定义的,因此在实际注册
    zend_对象之前,不会有名称冲突(除非存在重复的方法)

    此外,任何适当的OO代码都会注册一个自动加载函数。如果解析器不知道如何使用该
    函数
    关键字,那么对象会是什么 不仅仅如此,还有很多,但我想这就是为什么PHP会注意到为什么在它注意到您正在重新定义一个类之前,您试图重新定义一个函数

    可以找到几个有用的链接,其中包含zend引擎如何使用函数/方法的更详细描述

    在手边放一个标签也很有用,这样你就可以真正看到他们谈论的代码了

    这个文件是如何包含的?它是否从其他地方被包含、从其他地方自动加载、缓存、由框架加载等等?首先想到的是:在它下蛋之前,用火杀死它!您正在尝试使用
    包含
    要求
    加载此文件吗?如果是这样,请将其更改为
    require\u once
    include\u once
    是否可能是名称空间问题?它总是在最后一行出错,因为PHP就是在这一行完成处理该项的(我想)值得注意的是,一旦使用
    …\u
    functions@MrJamin:值得注意的是,过早优化是万恶之源。性能损失将是最小的(在编译时检查文件是否已经被需要),并且可以通过缓存(例如APC)“您是否设置了自动加载器?”=>这段代码是(1)史前的(8y.o.)(2)由一个希望获得15e+89%利润的老板编写的(=>只雇佣辍学的学生)(3)基于一个由第一个工作是考古学家的人完成的框架(一点也不开玩笑)。因此答案是:在这种情况下,不可能有干净的代码,而使用autoloader通常是经过深思熟虑的代码的一部分。简言之:“不”@OlivierPons:我向你和你的亲人表示最深切的同情。我注意到你也知道一些C。你是否同意,首先提出dupe函数错误的原因很可能是因为需要先处理函数定义,还是我应该继续寻找解释?当我读到ar时,我会问“化学学家的框架……他把它叫做什么?特罗威尔之死?@EliasVanOotegem谢谢你的回答,也谢谢你刚才所做的精彩总结。令人难以置信的是,这个家伙是我见过的所有致力于他的“框架”的人中最有技能的一个(让我们这样称呼它)。
    ZEND_API zval* zend_call_method(
        zval **object_pp,
        zend_class_entry *obj_ce,
        zend_function **fn_proxy,
        const char *function_name,
        int function_name_len,
        zval **retval_ptr_ptr,
        int param_count,
        zval* arg1,
        zval* arg2 TSRMLS_DC
    ) {
      int result;
      zend_fcall_info fci;
      zval z_fname;
      zval *retval;
      HashTable *function_table;
    
      zval **params[2];
    
      params[0] = &arg1;
      params[1] = &arg2;
    
      fci.size = sizeof(fci);
      /* fci.function_table = NULL;
       * will be read form zend_class_entry of object if needed
       */
      fci.object_ptr = object_pp ? *object_pp : NULL;
      fci.function_name = &z_fname;
      fci.retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
      fci.param_count = param_count;
      fci.params = params;
      fci.no_separation = 1;
      fci.symbol_table = NULL;
    
      if (!fn_proxy && !obj_ce) {
          /* no interest in caching and no information
           * already present that is needed later inside
           * zend_call_function.
           */
          ZVAL_STRINGL(&z_fname, function_name, function_name_len, 0);
          fci.function_table = !object_pp ? EG(function_table) : NULL;
          result = zend_call_function(&fci, NULL TSRMLS_CC);
      } else {
          zend_fcall_info_cache fcic;
    
          fcic.initialized = 1;
          if (!obj_ce) {
              obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
          }
          if (obj_ce) {
              function_table = &obj_ce->function_table;
          } else {
              function_table = EG(function_table);
          }
          if (!fn_proxy || !*fn_proxy) {
              if (zend_hash_find(
                  function_table, function_name,
                  function_name_len+1,
                  (void **) &fcic.function_handler) == FAILURE
              ) {
                  /* error at c-level */
                  zend_error(
                      E_CORE_ERROR,
                      "Couldn't find implementation for method %s%s%s",
                      obj_ce ? obj_ce->name : "",
                      obj_ce ? "::" : "", function_name
                  );
              }
              if (fn_proxy) {
                  *fn_proxy = fcic.function_handler;
              }
          } else {
              fcic.function_handler = *fn_proxy;
          }
          fcic.calling_scope = obj_ce;
          if (object_pp) {
              fcic.called_scope = Z_OBJCE_PP(object_pp);
          } else if (obj_ce &&
                     !(EG(called_scope) &&
                       instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) {
              fcic.called_scope = obj_ce;
          } else {
              fcic.called_scope = EG(called_scope);
          }
          fcic.object_ptr = object_pp ? *object_pp : NULL;
          result = zend_call_function(&fci, &fcic TSRMLS_CC);
      }
      if (result == FAILURE) {
           /* error at c-level */
           if (!obj_ce) {
               obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
           }
           if (!EG(exception)) {
               zend_error(
                   E_CORE_ERROR,
                   "Couldn't execute method %s%s%s",
                   obj_ce ? obj_ce->name : "",
                   obj_ce ? "::" : "", function_name
               );
           }
       }
       if (!retval_ptr_ptr) {
           if (retval) {
               zval_ptr_dtor(&retval);
           }
           return NULL;
       }
       return *retval_ptr_ptr;
    }