1
votes

Overview

I connect to a database in index.php, then import my classes.php file using require_once(). However, when connecting to the database, the database connection is undefined.

Code

index.php

$dbh = new PDO("mysql:host=$hostname;dbname=$dbname",$username,$password);
require_once("inc/classes.php");

/* ..... */

if($_POST["form"]=="login"){

    //Retrieve values
    $e = $_POST["email"];
    $p = $_POST["password"];

    //Data validation
    if(!filter_var($e, FILTER_VALIDATE_EMAIL)||strlen($e)<3) $errors->addError("email", "Please enter a valid email address.");
    if(strlen($p)<1) $errors->addError("password", "Please enter a valid password");
    $errors->killErrors();

    //Log user in
    $user = new User($e);
    if(!$user->login($p)) $errors->addError("form", "Incorrect username or password.");
    $errors->killErrors();

    exit("success");
}

inc/classes.php

class User
{
    public $id, $email, $data;

    public function __construct($e = null){

        if(isLoggedIn()){
            $stmt = $dbh->prepare("SELECT * FROM `users` WHERE `id`=? LIMIT 1");
            $stmt->execute(array($_SESSION["userid"]));
            $this->data = $stmt->fetch(PDO::FETCH_ASSOC);
        } else $this->email = $e;

    }

    public function login($p){
        //Perform database query for user
        $stmt = $dbh->prepare("SELECT `id`, `password` FROM `users` WHERE `email`=? LIMIT 1");
        $stmt->execute(array($this->email));
        if($stmt->rowCount()<1) return false;

        //Check password is correct
        $data = $stmt->fetch(PDO::FETCH_ASSOC);
        if(!password_verify($p, $data["password"])) return false;

        if(!$this->email) exit("User can only be logged in with an email address, not by User ID");

        $this->id = $data["id"];
        return $this->validate($this->id) ? true : false;
    }

}

Output

Notice: Undefined variable: dbh in /var/www/html/foo/public_html/bar/inc/classes.php on line 80

Fatal error: Call to a member function prepare() on null in /var/www/html/foo/public_html/bar/inc/classes.php on line 80

Line 80 is:

$stmt = $dbh->prepare("SELECT `id`, `password` FROM `users` WHERE `email`=? LIMIT 1");

Question

How can I include the database connection in index.php and have the classes.php file accept that PDO object?

2
You have to make it global $dbh; inside the function. It is a scope issue - Jay Blanchard
@JayBlanchard - directly inside the class or the individual function(s)? I've heard using global is not advised - is this still the case inside classes? - Ben
Done carefully it is OK, many use it too haphazardly and have a tendency to want to globalize all of their variables. I personally do it within the function to eliminate ambiguity. - Jay Blanchard
@JayBlanchard thanks - tested and working. If you post that as an answer I'll accept, cheers - Ben
You can also pass $dbh in function parameter as login($p,$dbh) get it usingfunction login($p,$dbh) - Saty

2 Answers

3
votes

You have to make your connection global:

global $dbh; 

Because of scope. Done carefully it is OK to use global variables. Many use it too haphazardly and have a tendency to want to globalize all of their variables. I personally do it within the function inside the class to eliminate ambiguity.

2
votes

http://php.net/manual/en/language.variables.scope.php - as @JayBlanchard writes, you need to reference the connection handle as a global variable.

However, it's much cleaner to pass dependencies into your object. For instance, when instantiating your User, you can pass in the connection.

$user = new User($dbh, $e);

You can then set a private variable for the connection handle. This way, you can change the name of the variable in index.php, or change the way it's instantiated without your User class blowing up due to a change in a different file.