带有循环包含的脚本中的未定义变量(第一个脚本包含另一个包含第一个的脚本)

Undefined variable in script with circular includes (first script includes another which includes the first one)

我正在处理一个 PHP 应用程序,它似乎有一个特点:它的一个文件 (helpers.php) 有几个函数,其中包括另一个文件和包含的文件(db_connection.php) 包含最初包含它的文件。

helpers.php:

<?php

function lineBreak()
{
    return "\n<br>\n";
}

function saveScoreToDB($score)
{
    //session_start(); // Already started

    $usuario_id = $_SESSION["usuario_id"];
    $etapa = $_SESSION["etapa"];

    try
    {
        $query_etapa = "SELECT id FROM etapas WHERE numero = $etapa";

        require_once "db_connection.php";

        // `$db_link` works perfectly fine here:
        $etapa_id = $db_link->query($query_etapa)->fetchColumn();

        $query_score = "INSERT INTO score
                            (
                                usuario_id,
                                etapa_id,
                                pontos
                            )
                                VALUES
                            (
                                $usuario_id,
                                $etapa_id,
                                $score
                            )";

        $db_link->query($query_score);
    }
    catch (Exception $e)
    {
        $_SESSION["error_message"] = $e->getMessage();
        header("Location: erro.php");
    }
}

function completeTest($redirectTo)
{
    unset($_SESSION["etapa"]);

    $usuarioId = $_SESSION["usuario_id"];

    // TODO: try/catch

    try
    {
        $queryEmailUsuario = "SELECT email FROM usuarios WHERE id = $usuarioId";
        $queryNomeUsuario = "SELECT nome FROM usuarios WHERE id = $usuarioId";

        require_once "db_connection.php";

        // `$db_link` does *not* work here. Why?
        $emailUsuario = $db_link->query($queryEmailUsuario)->fetchColumn();
        $nomeUsuario = $db_link->query($queryNomeUsuario)->fetchColumn();

        // Routine to send email using the variables above
    }
    catch (Exception $ex)
    {
        // TODO
    }
}

db_connection.php:

<?php

require_once "db_credentials.php";
require_once "helpers.php";

// Variables used here come from `db_credentials.php`
$dsn = "mysql:host=$host;dbname=$dbname;port=3307;charset=utf8;";

$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false
];

try
{
    $db_link = new PDO($dsn, $user, $pass, $options);
}
catch (PDOException $e)
{
    echo "Error connecting to the database.";
    echo lineBreak();
    echo $e->getMessage();
    echo lineBreak();
    echo lineBreak();
}

注意第一个脚本变量 $db_link 是如何在两个不同的函数中使用的,这两个函数都包含定义该变量的文件。在第一个函数(saveScoreToDB)中,变量可用并且函数工作正常;但在第二个 (completeTest) 内它不可用,我得到一个未定义的变量错误。

这是为什么?如何让它发挥作用?

第一个 require_once() 有效,因为那是“一次”,但它仅在该单个函数调用的范围内,因此 $db_link 在函数调用结束时被抛出并且是再也没有见过。您可以将其更改为 require(),但是为每个函数调用创建一个新连接是......在长 运行.

中效果不佳

理想情况下,您创建连接一次,然后在需要的地方通过参数传入,例如:

require_once('db_credentials.php');

saveScoreToDB($score, $db_link);
completeTest($redirectTo, $db_link)

但这可能会有点乏味,对吧?那么这就是 类 有用的地方。

class MyThing {

  protected $db;

  public function __construct(\PDO $db) {
    $this->db = $db;
  }

  public function saveScoreToDB($score) {
    $this->db->prepare(...);
  }

  public function completeTest($redirectTo) {
    $this->db->prepare(...);
  }
}

$thing = new Mything($db_link);
$thing->saveScoreToDB(42);
$thing->completeTest('yes');