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

时间:2017-09-14 04:52:56

标签: php class instantiation

请注意以下所有示例中<form> Escriba el Mensaje:<br><br> <input type="text" id="1" name="mensaje" rows="10" cols="40"> <br><br> <br><br> Elige una opción: <br><br> <input type="button" name="cifra" value="Cifrar" onclick="code()"> <input type="button" name="decifra" value="Decifrar" onclick="decode()"> <br><br> <textarea id="2" rows="5" cols="40"></textarea> </form>语句的位置:

这有效:

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,代码就能正常工作。

是吗?

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

2 个答案:

答案 0 :(得分:2)

use语句不会调用自动加载器,或者检查类是否存在,它只是拉出&#34; name&#34;进入当前命名空间。在您尝试使用它之前,不会调用自动加载器,PHP也不会查找该类是否存在。

答案 1 :(得分:1)

PHP脚本的执行分两个阶段进行:首先编译脚本,如果没有语法错误,编译器会生成一系列所谓的&#34;操作码&#34;。然后,解释器启动并开始执行脚本;这意味着它逐个接受操作码,解释它们并执行由它们编码的操作。

在开始执行之前只编译主脚本,在执行期间编译包含的文件(使用include函数之一)。

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

include_once

include/include_once/require/require_once语句生成告诉解释器的代码:&#34;停止执行当前脚本,加载并编译此文件,如果它不包含语法错误,在继续此脚本之前执行其代码&#34;

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

if (false) {
    include 'a.php';
}

永远不会读取文件a.php的内容;更重要的是,如果文件存在与否,翻译甚至不关心。只有在即将执行a.php语句时才开始关注include,但由于if (false)测试,这种情况永远不会发生。

使用

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

使用声明:

use Symfony\Component\HttpFoundation\Request;

程序员告诉编译器:&#34;嘿,我想让你知道,当你找到令牌Request之后,我会在\Symfony\Component\HttpFoundation\Request中找到令牌Request,但我更喜欢使用仅限use,因为它更短&#34;

use Symfony\Component\HttpFoundation\Request; $request = new Request(); 语句不允许在生成的代码中进行任何跟踪。它们在运行时不存在。代码:

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

与:

相同
vendor/autoload.php

为它们生成相同的代码;在编译过程中,第一个表格是&#34;转换&#34;进入第二个。

自动加载器

文件include_once __DIR__ . '/vendor/autoload.php'; $request = \Symfony\Component\HttpFoundation\Request::createFromGlobals(); echo $request->getMethod(); 的内容(可能)是Composer生成的自动加载器。 autoloader是使用spl_autoload_register()注册的可调用(函数或类方法),当代码到达对未知类的引用时,由解释器执行。自动加载器接收完整的类名(带命名空间),其目的是使类可用。它通常知道在哪里找到类(在文件中)。可以注册多个自动加载器,解释器逐个调用它们,直到类可用或全部失败。

如何运行

让我们替换代码变体中的别名,看看我们得到了什么。

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

include_once

在运行时:

  • $request = \Symfony\Component\HttpFoundation\Request::createFromGlobals()语句加载并注册自动加载器;
  • \Symfony\Component\HttpFoundation\Request - 类createFromGlobals未知,解释器调用自动加载器,其中包含声明该类的文件;然后执行类的方法\Symfony\Component\HttpFoundation\Request并返回类型为$request的对象;
  • null不是getMethod(),其类实现方法echo;调用该方法时,它返回的值由$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals(); include_once __DIR__ . '/vendor/autoload.php'; echo $request->getMethod(); 显示,每个人都很高兴。

变体#3:

$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals();

如何运行:

  • \Symfony\Component\HttpFoundation\Request - 类include_once __DIR__ . '/vendor/autoload.php'; $request = Request::createFromGlobals(); echo $request->getMethod(); 尚未宣布且没有注册自动加载器 - 解释器无法找到类,无法继续。

      

    PHP致命错误:Class&#39; Symfony \ Component \ HttpFoundation \ Request&#39;没找到。

变体#4:

include_once

别名未被替换,因为它是在使用后声明的。

在运行时:

  • $request = Request::createFromGlobals();语句加载并注册自动加载器;
  • Request - 尚未定义班级{{1}};解释器调用自动加载器,但自动加载器无法找到它;口译员无法继续。

      

    致命错误:班级&#39;请求&#39;找不到