2

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?

user3628807
  • 325
  • 3
  • 12
  • post code for `Class.Database.php` – coderodour May 10 '17 at 19:00
  • Make use of construct function – Rotimi May 10 '17 at 19:02
  • Here https://pastebin.com/wms9P002 – user3628807 May 10 '17 at 19:04
  • Database::connect() would indicate a class static method. Your IDE should warn you about mixing instance and static contexts. `$db->connect()` would work with your code, since $db is an instance of Database. – YvesLeBorg May 10 '17 at 19:09
  • Yes, $db->connect() works but I want to make use of the spl_autoload_register function and avoid claling the Database class in every function. Or is it ok if I do? – user3628807 May 10 '17 at 19:16
  • Yes, that's how it works, you need to call the connect everytime you run a new query or statement. Unless you use http://php.net/manual/en/mysqli.multi-query.php. Maybe what you are looking for is persistent connection that is available with PDO and (since php 5.3) mysqli see http://php.net/manual/en/mysqli.persistconns.php – Louis Loudog Trottier May 10 '17 at 19:17
  • Can I call new Database; on a new line without having a string before that? Like $db = new Database; ? Sorry I can't use formatting in these comments – user3628807 May 11 '17 at 01:34

2 Answers2

2

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.

Community
  • 1
  • 1
tereško
  • 58,060
  • 25
  • 98
  • 150
-1

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

Adam W.
  • 202
  • 1
  • 5
  • I get an error: Fatal error: Call to a member function prepare() on null in D:\xampp\htdocs\PHP OOP\customSystem\Classes\Class.Users.php on line 178 Which is the $query = Database::connect()->prepare($sql); line – user3628807 May 10 '17 at 22:15
  • Ok after a couple hours of headbanging I got it to work by adding new Database; before having the Database::connect()->prepare($sql); No, string, no nothing. Is that how it is supposed to work? – user3628807 May 11 '17 at 01:31
  • @user3628807 Sorry, i made a mistake in my code. Now it should work fine. Check this out – Adam W. May 11 '17 at 08:20