Search code examples
phppdo

$this when not in object context when using database class in another class


I have looked at the other questions to this and most say it's to do with calling static methods, etc. and none of which were able to explain why I'm getting this error?

I'm getting used to classes and don't want to have to construct the connection to the database in every class but have a class for it that each other class that uses a connection to the database uses (it just makes more sense and less work in the long run).

Below are the 2 classes, init.php that loads the classes and the call to the class on index.php all at its most basic.

It's the line I have pointed out in the "Reports class" that is throwing the error.

DB class

<?php
class DB{
    
    public static $instance = null;
    
    private $_pdo;
    
    public function __construct(){
        try{
            $this->_pdo = new PDO('mysql:host=12345;dbname=12345', '12345', '12345');
            $this->_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }catch(PDOException $e){
            $e->getMessage();
        }
    }
    
    public static function getInstance() {
        if(!isset(self::$instance)) {
            self::$instance = new DB();
        }
        return self::$instance;
    }
      
}
?>

Reports class

<?php
class Reports{
    
     private $_db;
     
     public function __construct(){
         $this->_db = DB::getInstance();
     }
     
     public static function getReports($table, $version, $orderBy){
         
         $sql = "SELECT * FROM {$table} WHERE name = :name ORDER BY :orderBy";
         $query = $this->_db->prepare($sql); // line thats throwing the error on $this->_db
         $query->execute(array(
            ':name'=>$version,
            ':orderBy'=>$orderBy
         ));
         $result = $query->fetchALL(PDO::FETCH_OBJ);
         
         return $result;
     }
}
?>

init.php

<?php
error_reporting(E_ALL);
session_start();
session_regenerate_id(true);

function autoload($class) {
    require_once 'classes/' . $class . '.php';
}

spl_autoload_register('autoload');
?>

index.php

<?php
require_once "core/init.php";

$reports = Reports::getReports("demo", "name1", "id");

echo "<pre>" . print_r($reports) . "</pre>";
?>

What is causing this?


Solution

  • It's a static method so you need to access it statically or get the instance on which the method exists. The way you have it designed currently means there is no way to do this. It doesn't seem like that method should be static anyhow, so I would just make it non-static:

    class Reports{
    
         private $_db;
    
         public function __construct(){
             $this->_db = DB::getInstance();
         }
    
         public function getReports($table, $version, $orderBy){
    
             $sql = "SELECT * FROM {$table} WHERE name = :name ORDER BY :orderBy";
             $query = $this->_db->prepare($sql); // line thats throwing the error on $this->_db
             $query->execute(array(
                ':name'=>$version,
                ':orderBy'=>$orderBy
             ));
             $result = $query->fetchALL(PDO::FETCH_OBJ);
    
             return $result;
         }
    }
    

    Usage:

    require_once "core/init.php";
    $report = new Reports();
    $reports = $report->getReports("demo", "name1", "id");
    
    echo "<pre>" . print_r($reports) . "</pre>";
    

    If you are set on keeping it static then you getReports method would need to do something like this:

         public static function getReports($table, $version, $orderBy){
    
             $reports = new self();
             $sql = "SELECT * FROM {$table} WHERE name = :name ORDER BY :orderBy";
             $query = $reports->_db->prepare($sql); // line thats throwing the error on $this->_db
             $query->execute(array(
                ':name'=>$version,
                ':orderBy'=>$orderBy
             ));
             $result = $query->fetchALL(PDO::FETCH_OBJ);
    
             return $result;
         }