【问题标题】:Check username exists using PHP and PDO?使用 PHP 和 PDO 检查用户名是否存在?
【发布时间】:2012-04-13 21:22:05
【问题描述】:

我有一个 db.php 文件,其中包含以下内容:

// db.php file
// creates connection to database

// DATABASE CONNECTION FUNCTION
function sql_con(){
    try{
        $dbh = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS,
            array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    } catch (PDOException $e) {
        // log error to file and display friendly error to user
        ExceptionErrorHandler($e);
        exit;
    }
}

我有一个注册页面,我想检查用户名是否已经存在,所以我事先调用我的sql_con(); 函数连接到数据库,然后执行以下查询

    // connect to database
    sql_con();

    $stmt = $dbh->prepare("SELECT `user_login` FROM `users` WHERE `user_login` = ? LIMIT 1");
    $stmt->execute(array($username));

    if ( $stmt->rowCount() > 0 ) {
        $error[] = 'Username already taken';
    }

我对 PDO 很陌生,上面我收到以下错误:

注意:未定义变量:第 64 行 C:\wamp\www\signup.php 中的 dbh

致命错误:在非对象上调用成员函数 prepare() C:\wamp\www\signup.php 第 64 行

可能是一些非常愚蠢的事情,我似乎将自己与 PDO 混淆了,因为我处于初学者阶段。谁能告诉我我做错了什么?另外我不确定这是否是正确的方法,因为我是 PDO 的新手,所以如果有更有效的方法来进行用户名查询检查,请告诉我。

【问题讨论】:

  • @Paul,是的,我使用 require_once 包含它。我有一个配置文件,在该 config.php 文件中,我使用 require_once 来包含我的 db.php、constants.php 和 functions.php 文件,并且该配置文件被加载到我的所有网站网页中。谢谢phplover
  • 这是Scope的一个很基础的概念,和PDO无关。如果你不熟悉这个概念,我建议你重读一下手册,也许会买一本好书。

标签: php pdo mysqli


【解决方案1】:

这是因为 $dbh 对象由于范围而被限制在 try catch 块和您的 sql_con() 函数内。

正确的解决方案是删除try catch,并sql_con()函数的末尾返回$dbh变量

然后:

try {
    $dbh = sql_con();

    $stmt = $dbh->prepare("SELECT `user_login` FROM `users` WHERE `user_login` = ? LIMIT 1");
    $stmt->execute(array($username));

    if ( $stmt->rowCount() > 0 ) {
        $error[] = 'Username already taken';
    }
}
catch (PDOException $e) {

    //Do stuff with $e

}

【讨论】:

  • 嗨真相,我会在一分钟内测试这个,我可以问一下,在你的代码上面的 catch 块中,这是否意味着:如果我无法连接到数据库或执行查询以任何原因捕获如果有一个错误?谢谢phplover
  • 这意味着运行整个代码,如果有任何抛出异常,停止一切并运行catch块。
  • @Vahan:阅读我的答案。我告诉他从他的函数中返回 $dbh 变量,我会突出显示它以便更清楚。
  • 所以一个异常基本上是一种方式来说明我是否对 try 块中的任何代码有问题,无论它是查询由于某种原因而没有工作,或者可能只是出现问题来捕获它在 catch 块中并用它做任何我想做的事情,在我的情况下,我有一个异常错误处理程序来将错误记录到文件中。我也在某处读到不推荐使用 try 和 catch 块之类的东西,因此我为什么不使用它,现在就试试吧!感谢php爱好者
  • 每个人都在看代码然后阅读文本:)所以我没有在代码之后阅读文本,因为我发现它错了对不起我的不好:)。但是如果你强调它会更好我是不是第一个,我也不是最后一个。
【解决方案2】:

函数执行完毕后,$dbh 变量将被销毁。

您可以尝试返回句柄:

function sql_con() {

    // your connection code

    return $dbh;

}

然后在您的注册页面中:

$dbh = sql_con();

根据您的需要,更好的选择是使用DI 容器。

【讨论】:

  • 请注意,try catch 块有自己的范围!
  • @Truth:不,它没有。 PHP 不提供任何类型的词法作用域。 codepad.viper-7.com/P71eJY
【解决方案3】:

您在函数中定义 pdo,但在函数中是不可见的。

function sql_con(){
    try{
        $dbh = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS,
            array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


        return $dbh; //this 

    } catch (PDOException $e) {
        // log error to file and display friendly error to user
        ExceptionErrorHandler($e);
        exit;
    }
}


 $dbh = sql_con();

如果你为pdo抽象创建一个类会更好。

$dbh = DB::getInstance();

【讨论】:

  • getInstance() 绝对不是要走的路。特别是如果你打算单身!
  • @Vahan,我不知道 OOP,但我会继续以程序风格编码并使用 PDO 作为数据库,还没有准备好 OOP,但谢谢!
  • @Truth,在这种情况下它不是最好的,但在其他情况下它很好,它连接一次,你可以通过获取对象实例在任何地方使用连接。
  • 让我问你这个简单的问题。如果您需要 2 个用于 2 个不同数据库的数据库连接,您会怎么做?这是一个非常可能的、非常真实的情况。单例不适合数据库连接。将 PDO 设为 OOP 是有原因的,每个数据库连接都作为不同的对象,这就是重点
  • @Vahan 不,不是。它要求您更改数据库类,如果 2 天后您决定需要从 5 个不同的数据库收集信息怎么办?您将编写额外的 3 个函数?这将在哪里结束?不。您编写一个函数,并实例化任意数量的 PDO 对象,然后将这些对象传递给信息收集方法。 这就是 OOP 的力量。不是单例。 programmers.stackexchange.com/questions/40373/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
  • 2015-03-04
相关资源
最近更新 更多