【问题标题】:What is the execution flow of the following PHP script?以下PHP脚本的执行流程是什么?
【发布时间】:2020-05-27 13:47:53
【问题描述】:

这是两个文件:

this_one.php

    <?php 

    include_once("other_one.php");

    $n1 = $_POST['name'];
    $n2 = $_POST['password'];

    echo "From this_one.php ".$n1." ".$n2."<br>";
    ?>

<form action="" method="POST">
    <input type="text" name="name">
    <input type="password" name="password">
    <button type="submit" name="Submit">Login</button>
</form>

other_one.php

<?php 
$name = $_POST['name'];
$pass = $_POST['password'];

echo "From other_one.php".$name." ".$pass."<br>";
?>

现在,当我在某处阅读时,如果表单操作为空,则 POST 将发送到脚本本身。另外 other_one.php 已包含在文件 this_one.php 中

但是当我在浏览器中运行时,输出是:

From other_one.php hello pass
From this_one.php hello pass

一切工作情况如何?为什么会收到此输出?

PS:不要向我解释include_once 是如何工作的。我要说的是,对于 10 个进程,脚本将从第 1 行一直运行到最后,如果我在包含的文件中打开与数据库的连接,这样我将创建相同的 $connection 实例 10 次,这将是一个开销。有什么方法可以为所有这 10 个线程共享一个数据库实例?

【问题讨论】:

  • 你期望的输出是什么?
  • @u_mulder 我希望从文件 other_one.php 中未定义,因为 POST 去了 this_one.php 但现在我明白了一切。这意味着每次发生某些事情时,都会执行整个组合文件,这对性能来说是非常昂贵的。如果我打开一个数据库连接,而不是像 JAVA 那样创建一个实例并一次又一次地重用它,我会在每次包含 database.php 时创建一个连接。专业人士是如何度过这个难关的,还是我错过了什么?
  • include_oncerequire_once 只会抓取一次文件。如果对该文件再次尝试包含/要求,它将跳过它。
  • @aynber 是的,我明白这一点,但假设我在 login.php 中有include_once('database.php'); 并且我做了一个 POST,那么它将执行整个 database.php 以及 login.php。如果不是为什么?因为@chris-hass 的回答显示整个文件被复制并从上到下逐行执行
  • @GrumpyCrouton 道歉,我的评论更没有帮助。等等,为什么没有人产生 htmlentities?

标签: php html forms


【解决方案1】:

include 指令将指定文件中的代码带入作用域。从心理上讲,您可以将 include 指令替换为该文件中的代码块,实际上并没有什么区别。知道这一点,您的代码实际上是:

    <?php 

    //include_once("other_one.php");
    $name = $_POST['name'];
    $pass = $_POST['password'];

    echo "From other_one.php".$name." ".$pass."<br>";

    $n1 = $_POST['name'];
    $n2 = $_POST['password'];

    echo "From this_one.php ".$n1." ".$n2."<br>";
    ?>

<form action="" method="POST">
    <input type="text" name="name">
    <input type="password" name="password">
    <button type="submit" name="Submit">Login</button>
</form>

编辑

有四个指令可以将代码带入当前进程/请求的范围。在我命名它们之前,请注意我说的是当前流程/请求。如果有 10 个人点击您的登录页面,您将有 10 个进程/请求。同样,如果 1 个人点击您的登录页面 10 次,您也将有 10 个进程/请求。这就是 PHP 的本质,除非你真的注意到性能问题,否则我不会担心。

四个指令是includeinclude_oncerequirerequire_once。以_once 结尾的指令保证提供的文件只被带入进程一次。其他两个指令允许每个进程多次包含一个文件。 includerequire 之间的区别很细微,但基本上include 会在找不到文件时生成可忽略的警告,而require 会抛出致命错误。

通常我个人始终建议您对所有包含使用require_once除非您明确有理由多次引入代码。例如,如果您有一个分页器小部件需要位于表格的顶部和底部,那么多次包含同一个文件是一个很好的用途。我从来没有使用过includeinclude_once,因为我无法想象包含问题对我来说是可以接受的情况。

另外,作为旁注,PHP resolves a file's path in a potentially surprising way。例如,如果您使用include 'file.php';,实际上意味着将文件包含在当前目录中。相反,管理员可以设置一个可选的“包含路径”(就我而言,可能是出于遗留原因),并使用该语法首先搜索包含路径。如果您没有包含路径,或者在该路径中找不到该文件,则然后使用本地文件夹。出于这个原因,我建议始终包含使用“路径语义”的文件,这几乎可以归结为以句点或正斜杠或诸如 __DIR__ 之类的常量开头。

【讨论】:

  • 我假设 OPs 代码在提交表单之前默默地抛出关于那些不存在的变量的错误
  • 如果我在 login.php 中执行include_once('database.php');,每次我发布一个新的数据库实例时,都会创建一个新的数据库实例,这是一种性能开销。还是我错过了什么?
  • @kingmanas,我已经更新了我的答案,提供了更多详细信息,希望能进一步回答您的问题
  • @ChrisHaas 它仍然没有回答我的问题,我说的是对于 10 个进程,脚本将从第 1 行运行到最后,如果我打开与包含的数据库的连接怎么办文件,这样我将创建相同的 $connection 实例 10 次,这将是一个开销。有什么方法可以为所有这 10 个线程共享一个数据库实例?
  • 在技术上可能存在开销,但它通常非常小,以至于它实际上并不是什么大问题,至少在我管理的一些较大的站点上是这样。 MySQLcan handle about 4 billion simultaneous connections。如果你真的想设置它们,PHP 和 MySQL 有 connection pooling and persistent connection 选项,但我建议等到你真正遇到性能问题
猜你喜欢
  • 2014-10-24
  • 2017-07-04
  • 2014-03-01
  • 2010-12-30
  • 1970-01-01
  • 1970-01-01
  • 2011-11-15
  • 2019-03-11
  • 2013-08-08
相关资源
最近更新 更多