-2

I am following a YouTube video for making a listing website using PHP. However, when I try and create a new listing, this happens in my browser:

Fatal error: Uncaught Error: Call to a member function prepare() on null in D:\Dev\Dependencies\XAMPP\htdocs\addonlister\lib\Database.php:31 Stack trace: #0 D:\Dev\Dependencies\XAMPP\htdocs\addonlister\lib\Addon.php(61): Database->query('SELECT * FROM a...') #1 D:\Dev\Dependencies\XAMPP\htdocs\addonlister\addon.php(10): Addon->getAddon('2') #2 {main} thrown in D:\Dev\Dependencies\XAMPP\htdocs\addonlister\lib\Database.php on line 31

Here is my code on the referenced pages:

database.php

<?php
class Database{
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;

private $dbh;
private $error;
private $stmt;

public function __construct(){
    // Set DSN
    $dsn = 'mysql:host=localhost'. $this->host .';dbname=addonlister' . $this->dbname;

    // Set Options
    $options = array(
            PDO::ATTR_PERSISTENT => true,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    );

    // PDO Instance
    try{
        $this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
    } catch(PDOException $e) {
            $this->error = $e->getMessage();
    }
}

public function query($query){
        $this->stmt = $this->dbh->prepare($query);
}

public function bind($param, $value, $type = null){
        if(is_null($type)){
                switch(true){
                    case is_int ( $value ) :
                        $type = PDO::PARAM_INT;
                        break;
                    case is_bool ( $value ) :
                        $type = PDO::PARAM_BOOL;
                        break;
                    case is_null ( $value ) :
                        $type = PDO::PARAM_NULL;
                        break;
                    default :
                        $type = PDO::PARAM_STR;
                }
        }
        $this->stmt->bindValue($param, $value, $type);
}

public function execute(){
    return $this->stmt->execute();
}

public function resultSet(){
    $this->execute();
    return $this->stmt->fetchAll(PDO::FETCH_OBJ);
}

public function single(){
    $this->execute();
    return $this->stmt->fetch(PDO::FETCH_OBJ);
}}

Addon.php

<?php
class Addon{
    private $db;

    public function __construct(){
        $this->db = new Database;
    }

    // Get All Addons
    public function getAllAddons(){
        $this->db->query("SELECT addons.*, categories.name AS cname
                FROM addons
                INNER JOIN categories
                ON addons.category_id = categories.id
                ORDER BY post_date DESC
                ");
        // Assign Result Set
        $results = $this->db->resultSet();

        return $results;
    }

    //Get Categories
    public function getCategories(){
        $this->db->query("SELECT * FROM categories");
        // Assign Result Set
        $results = $this->db->resultSet();

        return $results;
    }

    // Get Addons By Category
    public function getByCategory($category){
        $this->db->query("SELECT addons.*, categories.name AS cname
                     FROM addons
                     INNER JOIN categories
                     ON addons.category_id = categories.id
                     WHERE addons.category_id = $category
                     ORDER BY post_date DESC
                     ");
       // Assign Result Set
       $results = $this->db->resultSet();

       return $results;
    }

    // Get category
    public function getCategory($category_id){
            $this->db->query("SELECT * FROM categories WHERE id = :category_id"
                );
            $this->db->bind(':category_id' , $category_id);

            // Assign Row
            $row = $this->db->single();

            return $row;
    }

    // Get Addon
    public function getAddon($id){
        $this->db->query("SELECT * FROM addons WHERE id = :id");

        $this->db->bind(':id' , $id);

        // Assign Row
        $row = $this->db->single();

        return $row;
    }

    // Addon Job
    public function create($data){
        //Insert Query
        $this->db->query("INSERT INTO addons (category_id, addon_title, description, developer, file_size)
        VALUES (:category_id, :addon_title, :description, :developer, :file_size)");
         //Bind Data
        $this->db->bind(':category_id', $data['category_id']);
        $this->db->bind(':addon_title', $data['addon_title']);
        $this->db->bind(':description', $data['description']);
        $this->db->bind(':developer', $data['developer']);
        $this->db->bind(':file_size', $data['file_size']);
        //Execute
        if($this->db->execute()){
            return true;
        } else {
            return false;
        }
    }
}

Addon.php

<?php include_once 'config/init.php'; ?>

<?php
$addon = new Addon;

$template = new Template('templates/addon-single.php');

$addon_id = isset($_GET['id']) ? $_GET['id'] : null;

$template->addon = $addon->getAddon($addon_id);

echo $template;
Dharman
  • 30,962
  • 25
  • 85
  • 135
  • 1
    Does this answer your question? [Reference - What does this error mean in PHP?](https://stackoverflow.com/questions/12769982/reference-what-does-this-error-mean-in-php) – Simone Rossaini May 27 '20 at 06:04
  • use \ before the class name which you included ex: new \PDO – Shibon May 27 '20 at 06:08
  • It's possible that your connection will fail and all it does is set `$this->error`, but after that you don't seem to bother checking either the error or if the connection succeeded. Also worth looking at Dependency Injection as this allows more flexibility with your classes. – Nigel Ren May 27 '20 at 06:46

1 Answers1

-1

You dont need to create functions or classes for the database connection. Just make a connection file containing the following

   <?php
     try
     {
      $db = new PDO('mysql:host=localhost; dbname=YourDBname;    charset=utf8', 'root', ''); 
        $db->setAttribute(PDO::ATTR_ERRMODE,    PDO::ERRMODE_EXCEPTION); 
        }
              catch (PDOException $ex)
    {
        echo error("Cannot connect to the database!");
    die();
        }
    ?>

Now wherever you need the database just require(“connection.php”); And to use it you can use it this way

             $ExampleQuery= $db->prepare(“SOME QUERY”);
  • A general OO mechanism for doing this sort of thing would be [dependency injection](https://stackoverflow.com/questions/10064970/php-dependency-injection) rather than declaring global variables. – Nigel Ren May 27 '20 at 06:42
  • 1
    So what are you saying? Is the method I mentioned above better or not? @Nigel Ren –  May 27 '20 at 09:43
  • Depends, if this is included in several places - will it create several connections to the database? – Nigel Ren May 27 '20 at 09:50
  • 1
    No it wouldn’t, it would only be required as if you write the code each time wherever u need it. Also i find this method of coding with php much smoother and more simple. Php is very simple i dont know why people hard code it sometimes –  May 27 '20 at 09:54
  • 1
    Please **do not catch exceptions!** – Dharman May 27 '20 at 10:31
  • `echo error("Cannot connect to the database!");` is *very* unprofessional, and wrong on so many levels;. Do not catch an exception to output such a message. – Your Common Sense May 27 '20 at 10:50
  • 1
    @nemesis no need to defend yourself. I am not criticizing you. I am just telling you this is a bad practice.It's just an advice. I apologize if you took that personally. In fact, this code is widely used, you cannot be blamed for it. So I don't blame you personally. – Your Common Sense May 27 '20 at 12:05
  • @YourCommonSense okay perhaps i miss understood thank you. –  May 27 '20 at 12:10