• php include 与 require 起底[转]


    转自 http://www.guangla.com/post/2014-01-24/40060857811

    起因:

    一朋友面试被问到,php的include和require的区别,这个可能是面试中出现机率比较高的问题。网上众说纷云,他说他也搞晕了。

    手册上的说明:

    require 和 include  几乎完全一样,除了处理失败的方式不同之外。require  在出错时产生 E_COMPILE_ERROR  级别的错误。换句话说将导致脚本中止而 include  只产生警告(E_WARNING),脚本会继续运行。

    从手册上明确知道他们之间的唯一区别就是,require出错会中止脚本,那为什么网上还有各种版本的区别,所以必需从源码上来终结。

    源码追踪:

    要进行源码追踪,先了解下php的大概的运行原理:php代码 ->代码扫描 ->代码翻译 -> zend vm执行 -> 输出

    1、找到 require 在代码扫描文件在地址(Zend/zend_language_scanner.l)中 1262 - 1264行:

                 <ST_IN_SCRIPTING>"require" {
                      return T_REQUIRE;
                  }

      2、继续找T_REQUIRE, 在 (Zend/zend_language_parser.y)中的 1259行

                   T_REQUIRE expr            { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }

    发现 zend_do_include_or_eval 这个函数

     3、 继续找 zend_do_include_or_eval, 在 (Zend/zend_compile.c)中的 6186行:

                         opline->opcode = ZEND_INCLUDE_OR_EVAL;

    发现把opcode设置为 ZEND_INCLUDE_OR_EVAL,

     4、继续找ZEND_INCLUDE_OR_EVAL的定义,在 (Zend/zend_vm_def.h)中的 3935行开始,发现目标在4002-4005,(3963-4001是include_once require_once的判断,发现这两也走的同一套逻辑,这里段代码里也可以明显看出 _once的处理逻辑)

                  case ZEND_INCLUDE:
                  case ZEND_REQUIRE:
                           new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC);
                  break;

     5、继续找compile_filename,定义在(Zend/zend_language_scanner.c)中的 612行中:

                    retval = zend_compile_file(&file_handle, type TSRMLS_CC);

     6、继续找zend_compile_file, 在zend.c 689行:

                       zend_compile_file = compile_file;

     7、 继续找zend api定义的compile_file方法,在(Zend/zend_language_scanner.l)中553行找到这个方法定义:

                   if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
                        if (type==ZEND_REQUIRE) {
                             zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
                            zend_bailout();
                       } else {
                            zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
                      }
                      compilation_successful=0;
                  }

     在这里终于发现  include和require的区别了,明显可以看出没有找到文件的话,require,会执行zend_bailout(); ,继续看zend_bailout();会发现,最终会退出脚本执行。

    结论:

     在1~6 步中 ,include和require始终走的是同一逻辑,只有在第7步才有区别判断,从代码中可以得出结论和手册中一致。希望这篇文章能够给这个命题下一个最终结论。

  • 相关阅读:
    IDEA在debug时修改变量值
    CSS覆盖公共样式中的某个属性
    POI获取单元格的宽和高
    MySQL将一张表的某些列数据,复制到另外一张表,并且修改某些内容
    哈希是什么?为什么哈希存取比较快?
    工厂模式
    观察者模式
    instanceof判断的对象可以是接口
    JeeSite框架中httpSession.invalidate();无效
    HSQL可视化工具
  • 原文地址:https://www.cnblogs.com/debmzhang/p/4424120.html
Copyright © 2020-2023  润新知