user3628807
user3628807

Reputation: 325

Avoid calling Database class in every function

I am trying to learn OOP php and as I was developing a login/register system, I noticed that I am calling the Database clase in every function in my Users class.

For example, like this:

<?php

class Users {
    public function signUp($username, $email, $password){
        $db = new Database;
        $dbh = $db->connect();

        $sql = "INSERT INTO users (username, email, password) VALUES (?, ?, ?)";

        try {
            $query = $dbh->prepare($sql);
            $query->execute(array($username, $email, $password));

            echo 'succ';
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    }

Basically, without copying the whole file, I have a few functions that work with the database and in every single one of them I have to call these two lines:

$db = new Database;
$dbh = $db->connect();

So I looked up on the internet and found about the spl_autoload_register. It worked perfectly for the most part, however I can't seem to replace the two lines from above like this:

$db = new Database;
$dbh = Database::connect();

as I get another error from my Database class:

Using $this when not in object context in D:\xampp\htdocs\PHP OOP\customSystem\Classes\Class.Database.php on line 24

Line 24 is the return of this function

public function connect(){
        return $this->conn; 
    }

and I am out of ideas of what to do now, but it won't solve my initial problem with calling the Database class in every function, too. So, what do I need to do?

Upvotes: 2

Views: 270

Answers (2)

tereško
tereško

Reputation: 58444

You should pass in the DB class as a dependency.

It should look something like this

class Users {
    private $dbh;

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

    public function signUp($username, $email, $password)
    {
        $sql = "INSERT INTO users (username, email, password) VALUES (?, ?, ?)";

        try {
            $query = $this->dbh->prepare($sql);
            $query->execute(array($username, $email, $password));

            echo 'succ';
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    }
}

This approach lets you pass same PDO instance to all of the classes that needs it. You can also further improve the code, by using a factory, that is responsible for creating all classes, that need PDO as a dependency, as described in this answer.

Upvotes: 2

Adam W.
Adam W.

Reputation: 202

When you statically call a method Database::connect(); you can't refer to $this.
$this is a reference to existing instance of your object therein. So, when you create new instance by new Database() then you can use $this pointer inside Database class methods.

Just learn more about static things and try with this:

class Database
{
    private static $instance = null;
    private static $conn = null;

    private function __construct()
    {
        try {
            $dbh = new PDO(DB_SOCKET_TYPE . ':host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8', DB_USER, DB_PASSWORD);
            $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            self::$conn = $dbh;
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }

    private function getDbConnection()
    {
        return self::$conn;
    }

    public static function connect()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance->getDbConnection();
    }
}

// how to use it? for eg.
$sql = 'INSERT INTO users (username, email, password) VALUES (?, ?, ?)';
$query = Database::connect()->prepare($sql);
$query->execute(array($username, $email, $password));

Sorry for any mistakes, but i wrote this quickly and did not test it
I hope it's useful

Upvotes: -1

Related Questions