【问题标题】:Variables Undefined when in Function在函数中未定义的变量
【发布时间】:2012-07-18 18:38:44
【问题描述】:

我正在处理一个项目,我收到 $host、$dbname、$user 和 $pass 的未定义错误。

但只有在 dbConnect() 函数内部时才会出现错误。

这是代码(upload.php):

<?php
error_reporting(E_ALL);
require('config.php');

$filename = htmlentities($_FILES['file']['name']);
$tmpname = $_FILES['file']['tmp_name'];
$filesize = $_FILES['file']['size'];
$filetype = $_FILES['file']['type'];    

function dbConnect() {

    try {
        global $dbcon;
        $dbcon = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
    }
    catch (PDOException $e) {
        echo $e->getMessage();
    }
}

if (dbConnect()) {
    print('worked');
}

config.php:

<?php
global $host, $user, $pass, $dbname;

$host =  "localhost"; // MySQL Hostname
$user = "root"; // MySQL User
$pass = "mypass"; // MySQL Password
$dbname = "files";

【问题讨论】:

标签: php variables undefined


【解决方案1】:

您需要将变量作为参数传递给函数。在函数外部声明的变量在该函数内部不可用:

function dbConnect($user, $pass, $host, $dbname) {

    try {
        global $dbcon;
        $dbcon = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
    }
# ...

阅读更多关于Variable Scope in PHP的信息。

【讨论】:

  • 感谢您的回答!我明白你现在的意思了,但根据脚本底部的条件,它并没有按应有的方式打印“工作”。
  • 那是因为你没有从你的函数中返回任何东西。这是一个单独问题的单独问题。查找有关如何从函数返回内容的教程。
  • 我不想把整个问题都浪费在很可能很简单的事情上,我只是在放屁。
  • 我刚刚告诉了你答案。你没有返回任何东西。您正在使用 if 条件测试 void 值。如果您希望 if 条件成功,则必须返回计算结果为 true 的内容。
  • 你是说实例化一个 PDO 对象永远不会评估为真?
【解决方案2】:

我建议您使用数组来存储连接字符串信息。

首先,在您的config.php 页面中创建一个函数,该函数返回必要的数据库连接字符串信息。要使用,您只需在$dbconfigupload.php 中声明一个变量,该变量将从loadDBConfig() 函数返回的值存储在您的config.php 文件中。然后,您将通过声明$dbcon 变量并将值设置为dbConnect() 来执行dbConnect() 函数。这会将函数的结果返回给变量,然后您可以检查所需的结果。

此解决方案消除了对全局变量的需求并改进了组织。

注意:您的整个 DB 交互在技术上应该移到一个类中以提高可移植性。

上传.php

...
function dbConnect() {
    $dbconfig = loadDBConfig();
    try {
        $dburl = "mysql:host=" . $dbconfig['host'] . ";dbname=" . $dbconfig['dbname'];
        return new PDO($dburl, $dbconfig['user'], $dbconfig['pass']); 
    } catch (PDOException $e) {
        echo $e->getMessage();
    }
 }  

$dbcon = dbConnect();
...

config.php

<?php 
function loadDBConfig(){
    $host =  "localhost"; // MySQL Hostname 
    $user = "root"; // MySQL User 
    $pass = "mypass"; // MySQL Password 
    $dbname = "files"; 

    return array('host' => $host, 'user' => $user,  'pass' => $pass, 'dbname' => $dbname);
}
?> 

【讨论】:

  • 非常感谢!我非常感谢这个例子和解释!下次我会记住这一点!
【解决方案3】:

您还需要在 dbConnect 中声明这些变量 GLOBAL。

function dbConnect() {
  try {
        global $dbcon;
        global $host, $user, $pass, $dbname;
        $dbcon = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  }
  catch (PDOException $e) {
        echo $e->getMessage();
  }
}

编辑

是的,全局变量并不是一个好主意——它们会阻碍代码重用并“污染”命名空间,您永远不知道哪些变量存在哪些不存在,并且有更改在其他地方使用的变量的风险。

解决问题的更好方法是将所需信息作为“参数”传递。这同样适用于返回值,它可以是资源(如果一切顺利的话)或表示错误消息的字符串。

function dbConnect($host, $dbname, $user = 'nobody', $pass = '') {
  try {
        return new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  }
  catch (PDOException $e) {
        return $e->getMessage();
  }
}

你会调用这样一个函数来传递参数并检查它的输出,如果一切顺利的话,它应该是一个对象:

if (!is_object($conn = dbConnect($host, $dbname, $user, $pass) {
   die("There was an error: $conn");
}

参数的另一个优点是您可以为参数设置默认值(例如,如果您编写了 dbConnect($host, $dbname),该函数将“理解”并使用 'nobody' 并为其余参数使用空密码)。

【讨论】:

  • 全局变量可能在技术上解决问题,但它们不是解决此问题的方法。
  • 谢谢你,lserni,但是,我真的很想了解发生了什么,以及解决问题的正确方法,而不是简单地“修补”问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 1970-01-01
  • 2012-10-09
  • 2017-08-21
  • 1970-01-01
相关资源
最近更新 更多