6

私がしばらく取り組んできた小さなpdoの問題があります。ここで何が問題なのかわからないので、このリストに入れることを考えました。詳しい方もいらっしゃるかも…

ユーザーとパスワードをmysql駆動のデータベースと照合するログインを備えたWebサイトがあります。pdo 接続が同じファイルで行われると、すべて正常に動作し、問題なくログインできます。それが機能するはずのように...

ただし、データベース接続部分を別のファイルから含める別の関数に移動すると、pdo が失敗し、次のようになります。

SQLSTATE[28000] [1045] ユーザー '...'@'...' のアクセスが拒否されました (パスワードを使用: NO) 致命的なエラー: /.../ の非オブジェクトに対するメンバー関数 prepare() の呼び出し.../... 41 行目

わかりやすくするために、コードを次に示します。

バージョン 1:

これは機能します:

<?php
    require "./vars_and_functions.php";

    /* open database connection */
    try {
    $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);

    /* query */
    $query = "SELECT uname, passw FROM members WHERE uname = ? AND passw = ?";
    $q = $pdo->prepare($query);
    $q->execute(array($u_name, $p_word_md5));
    $result = $q->rowCount();

    if($result == 1) { /* we have a match */                       
    /* close the database connection */
               $pdo = null;  

                /* and redirect */
                header("...");

    } /* if */
    else { /* wrong credentials */
        /* close the database connection */                
                $pdo = null;

                /* and go back to the login page */ 
        header("...");
    } /* else */
        } /* try */ 
    catch(PDOException $e) {  
        echo $e->getMessage();  
    } /* catch */
?>

バージョン2はこちら

これは動作しません:

<?php
        require "./vars_and_functions.php";

        /* open database connection */
        $pdo = database_connection();



    /* query */
            $query = "SELECT uname, passw FROM members WHERE uname = ? AND passw = ?";
            $q = $pdo->prepare($query);
            $q->execute(array($u_name, $p_word_md5));
            $result = $q->rowCount();

        if($result == 1) { /* we have a match */                       
               /* close the database connection */
                   $pdo = null;  

                    /* and redirect */
                    header("...");

        } /* if */
        else { /* wrong credentials */
            /* close the database connection */                
                    $pdo = null;

                    /* and go back to the login page */ 
            header("...");
        } /* else */
            } /* try */ 
    catch(PDOException $e) {  
        echo $e->getMessage();  
    } /* catch */
?>

私のインクルードファイル vars_and_functions.php は次のようになります:

$db_host = "...";       
$db_name = "...";           
$db_user = "...";       
$db_pass = "...";       

function database_connection() {
    try {
    $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
}  
catch(PDOException $e) {  
    echo $e->getMessage();  
}  

return $pdo;
}

私が思う唯一の違いは、ここでは pdo 接続が関数呼び出しによって行われているのに対し、関数はインクルード ファイル vars_and_functions.php にあるということです。

ここで何が問題なのですか?

4

2 に答える 2

3

関数database_connection()は正しいスコープで接続変数を受信しないため、接続が試行されたときに設定されず、したがって として渡されNULL、PDO はデフォルトで接続ホストを にしlocalhostます。

それらをパラメーターとして関数に渡します。

// Defined at global scope...
$db_host = "...";       
$db_name = "...";           
$db_user = "...";       
$db_pass = "...";       

// Pass the 4 variables as parameters to the function, since they were defined at global
// scope.
function database_connection($db_host, $db_name, $db_user, $db_pass) {
    try {
    $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
}  

// Called as:
$pdo = database_connection($db_host, $db_name, $db_user, $db_pass);

これらの変数を接続関数内でのみ使用していて、他の場所では必要ない場合は、それらを関数のスコープで定義することを検討してください。これにより、変数をパラメーターとして渡す必要がなくなります。

function database_connection() {
    // Only needed here, so define in function scope
    $db_host = "...";       
    $db_name = "...";           
    $db_user = "...";       
    $db_pass = "...";       

    try {
    $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
}  

最後の、そしてしばしば最も望ましくないオプションは、あなたが行ったようにグローバルスコープで変数を定義することですが、関数内の$GLOBALS[](またはglobalキーワード) を介してそれらにアクセスします:

function database_connection() {
    try {
    $pdo = new PDO("mysql:host={$GLOBALS['db_host']};dbname={$GLOBALS['db_name']}", $GLOBALS['db_user'], $GLOBALS['db_pass']);
} 

error_reportingオンにして開発している場合はdisplay_errors、未定義の変数に関する通知が表示されることに注意してください。

error_reporting(E_ALL);
ini_set('display_errors', 1);
于 2012-11-06T17:36:38.657 に答える
0

Michael Berkowski の回答に加えて、グローバル キーワードを次のように渡すこともできます。

function database_connection() {
    global $db_host, $db_name, etc;
    // your code here
}

PHP の変数スコープの詳細については、 http://php.net/manual/en/language.variables.scope.phpを参照してください。

于 2012-11-06T17:41:20.830 に答える