PHP-为什么对象在代码中的不同位置会产生不同的结果?

PHP-为什么对象在代码中的不同位置会产生不同的结果?,php,class,instantiation,Php,Class,Instantiation,请注意include_once语句在以下所有示例中的位置: 这项工作: include_once __DIR__ . '/vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); echo $request->getMethod(); 我以为这不管用,但它确实管用: use Symfony\Component\Htt

请注意
include_once
语句在以下所有示例中的位置:

这项工作:

include_once __DIR__ . '/vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;    

$request = Request::createFromGlobals();

echo $request->getMethod();
我以为这不管用,但它确实管用:

use Symfony\Component\HttpFoundation\Request;

include_once __DIR__ . '/vendor/autoload.php';

$request = Request::createFromGlobals();

echo $request->getMethod();
但这失败了:

use Symfony\Component\HttpFoundation\Request;    

$request = Request::createFromGlobals();

include_once __DIR__ . '/vendor/autoload.php';

echo $request->getMethod();
这也是:

include_once __DIR__ . '/vendor/autoload.php';

$request = Request::createFromGlobals();

use Symfony\Component\HttpFoundation\Request;

echo $request->getMethod();
我猜只要在类被使用/实例化之前代码中有
use
include\u一次
,代码就可以正常工作

是这样吗


非常感谢对流程的详细解释。

use语句不调用自动加载程序,也不检查类是否存在,它只是将该“名称”拉入当前名称空间。在您尝试使用它之前,不会调用autoloader,PHP也不会查找该类以查看它是否存在。

use语句不会调用autoloader,也不会检查该类是否存在,它只是将该“名称”拉入当前名称空间。在您尝试使用它之前,不会调用自动加载程序,PHP也不会查找该类以查看它是否存在。

PHP脚本的执行分两个阶段进行:首先编译脚本,如果没有语法错误,编译器将生成一系列所谓的“操作码”。然后,解释器开始执行脚本;这意味着它将一个接一个地获取操作码,解释它们并执行它们编码的操作

在开始执行之前只编译主脚本,包括的文件(使用其中一个函数)在执行期间编译

让我们看看你的脚本会发生什么

包括一次 这些语句生成的代码告诉解释器:“在此处停止当前脚本的执行,加载并编译此文件,如果它不包含语法错误,则在继续此脚本之前执行其代码”

也就是说,在主脚本的编译阶段不会读取包含的文件,只有在运行时需要时才会读取。在这段代码中:

if (false) {
    include 'a.php';
}
从不读取文件
a.php
的内容;更重要的是,解释器甚至不关心文件是否存在。只有当
include
语句即将执行时,它才开始关心
a.php
,但由于
if(false)
测试,这种情况从未发生

使用 该语句用于创建别名。这样的别名只是程序员和编译器之间的协议,编译器不会为它生成任何代码

通过使用以下语句:

use Symfony\Component\HttpFoundation\Request;
程序员告诉编译器:“嘿,我想让您知道,稍后在这个文件中,当您找到令牌
请求
时,我的意思是
\Symfony\Component\HttpFoundation\Request
,但是我更喜欢只使用
请求
,因为它比较短。”


use
语句不允许在生成的代码中进行任何跟踪。它们在运行时不存在。守则:

use Symfony\Component\HttpFoundation\Request;
$request = new Request();
同:

$request = new \Symfony\Component\HttpFoundation\Request();
为它们生成相同的代码;在汇编过程中,第一种形式被“转换”为第二种形式

自动装弹机 文件
vendor/autoload.php
的内容(可能)是由Composer生成的自动加载器。是使用注册的可调用(函数或类方法),当代码到达对未知类的引用时,解释器将执行该方法。自动加载程序接收完整的类名(带有名称空间),其目的是使该类可用。它通常知道在哪里可以找到类(在文件中)。可以注册多个自动加载程序,解释器逐个调用它们,直到类可用或所有自动加载程序都失败

它是如何运行的 让我们替换代码变体中的别名,看看我们得到了什么

变体#1和#2产生相同的代码:

include_once __DIR__ . '/vendor/autoload.php';
$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
echo $request->getMethod();
在运行期间:

  • include_once
    语句加载并注册自动加载器
  • $request=\Symfony\Component\HttpFoundation\request::createFromGlobals()
    -类
    \Symfony\Component\HttpFoundation\request
    未知,解释器调用包含声明该类的文件的自动加载程序;然后执行类的方法
    createFromGlobals
    ,并返回类型为
    \Symfony\Component\HttpFoundation\Request
    的对象
  • $request
    不是
    null
    ,它的类实现了方法
    getMethod()
    ;方法被调用,它返回的值通过
    echo
    显示,每个人都很高兴
变体#3:

$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
include_once __DIR__ . '/vendor/autoload.php';
echo $request->getMethod();
include_once __DIR__ . '/vendor/autoload.php';
$request = Request::createFromGlobals();
echo $request->getMethod();
运行方式:

  • $request=\Symfony\Component\HttpFoundation\request::createFromGlobals()-尚未声明类
    \Symfony\Component\HttpFoundation\Request
    ,并且没有注册自动加载程序-解释器找不到该类,无法继续

    PHP致命错误:找不到类“Symfony\Component\HttpFoundation\Request”

变体#4:

$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
include_once __DIR__ . '/vendor/autoload.php';
echo $request->getMethod();
include_once __DIR__ . '/vendor/autoload.php';
$request = Request::createFromGlobals();
echo $request->getMethod();
别名不会被替换,因为它是在使用后声明的

在运行期间:

  • include_once
    语句加载并注册自动加载器
  • $request=request::createFromGlobals()-尚未定义类
    请求
    ;解释器调用自动加载器,但自动加载器找不到;口译员无法继续

    致命错误:找不到类“请求”


    • PHP脚本的执行分为两个阶段:首先编译脚本,如果没有语法错误,编译器将生成一系列所谓的“操作码”。然后,解释器开始执行脚本;这意味着它将一个接一个地获取操作码,解释它们并执行它们编码的操作

      只编译主脚本