0

I am using this library and when I put on my OOP project, it gave me an error https://github.com/lincanbin/PHP-PDO-MySQL-Class

Notice: Undefined variable: DB in E:\Laragon\www\shop\include\category.php on line 13

Fatal error: Uncaught Error: Call to a member function query() on null in E:\Laragon\www\shop\include\category.php:13 Stack trace: #0 E:\Laragon\www\shop\admin\category.php(8): Category->getAllCategories() #1 {main} thrown in E:\Laragon\www\shop\include\category.php on line 13

on my category class

<?php

require_once('../vendor/autoload.php');

class Category {
    function __construct()
    {
        $DB = new Db('localhost', '3306', 'shop', 'root', '');
    }

    public function getAllCategories()
    {
        $query = $DB->query("SELECT * FROM categories");

        return $query;
    }
   ...
}

and in my php frontend

<?php

    require_once('../include/category.php');


    $test = new Category();

    var_dump($test->getAllCategories());
?>

EDIT FOR Jite

Does every query like insert, getall, select, delete need to add closeConnection? I found this here: https://stackoverflow.com/a/20492486/5406008 require_once('../vendor/autoload.php');

class Category {
    protected $DB;

    function __construct()
    {
        $this->DB = new Db('localhost', '3306', 'shop', 'root', '');
    }

    public function __destruct()
    {
       $this->DB->closeConnection();
    }

    public function getAllCategories()
    {
        $query = $this->DB->query("SELECT * FROM categories");

        return $query;
    }
Storm Spirit
  • 1,410
  • 4
  • 18
  • 37
  • 2
    `$this->DB` instead of `$DB`. You need to define it first. Basic OOP pattern. – Qirel Apr 30 '19 at 06:15
  • 1
    Possible duplicate of [How Do I define properties for a class in php?](https://stackoverflow.com/questions/11034330/how-do-i-define-properties-for-a-class-in-php) – Qirel Apr 30 '19 at 06:18
  • It is worth looking into [dependency injection](http://php-di.org/doc/understanding-di.html) (DI) which would mean passing in the connection to the class. (Link is just the first link I found) – Nigel Ren Apr 30 '19 at 06:37
  • You should not use closeConnection at all (maybe only when you really know you should). Closing connection require you to open it again for next query so it will run much slower. When PHP script finishes it closes connection automatically anyways. – Volvox Apr 30 '19 at 06:38

3 Answers3

2

When you create a new variable in a class method, it will only exist in that scope, so when creating the $DB variable in the constructor, it will go out of scope when you reach the end of the constructor.

To store the variable in the class as a member field, you will have to set it to the $this object, preferably defining it before hand:

class Category {
    private $DB;
    function __construct()
    {
        $this->DB = new Db('localhost', '3306', 'shop', 'root', '');
    }

    public function getAllCategories()
    {
        $query = $this->DB->query("SELECT * FROM categories");

        return $query;
    }
   ...
}

That way, the class will store the variable as a member and make it available in all it's methods.

Jite
  • 5,730
  • 2
  • 23
  • 35
  • is it okay to close the connection every function? `$DB->closeConnection();` like bottom of $query. or when do I need to close the db connection? – Storm Spirit Apr 30 '19 at 06:20
  • It's always good to close the connection when it's not needed anymore, but I'm not sure how the internal logic of the `Db` class works, so unsure if you should close it. Personally I'd recommend that you create ONE db object for the whole page and then pass it into the constructor of the class, then you can keep it open through the whole runtime and not use more handles than needed. – Jite Apr 30 '19 at 06:23
  • you mean on the view file? sorry I'm too noob, I've updated my description with added yours. – Storm Spirit Apr 30 '19 at 06:26
  • @StormSpirit - Don't close the connection in every method. It's better to have one single connection that you reuse. Connecting to the database is costly so you don't want to do that more often than you really have to. PHP will actually close the connection for you when the script ends. If you want to make sure it's closed, you can always close it in the class [destruct](https://www.php.net/manual/en/language.oop5.decon.php#language.oop5.decon.destructor)-method. – M. Eriksson Apr 30 '19 at 06:27
  • As @MagnusEriksson says, php will close it, so you don't need to care too much about the actual connection. The other part is more of a optimization, as I always say: make it work, then make it good, so start with making the script run as you wish, then you can look at making it better :) – Jite Apr 30 '19 at 06:29
  • so it's okay to don't close it and my category is all good right? it will end when it execute every method – Storm Spirit Apr 30 '19 at 06:29
  • Not when you end the method no, but rather when the class is deleted from memory (as the database object will be deleted from it too). :) If you instead create a local variable in the `getAllCategories` method, it would be deleted when the method reaches the end of the scope. – Jite Apr 30 '19 at 06:30
0

Please define $DB as a class variable and then use it.

<?php   
require_once('../vendor/autoload.php');
class Category {
 private $DB; // Define it here.
 function __construct() {
  $this->DB = new Db('localhost', '3306', 'shop', 'root', ''); // Set value here
 }
 public function getAllCategories() {
  $query = $this->DB->query("SELECT * FROM categories"); // Get value here
  return $query;
 }
 ...
}
Pupil
  • 23,528
  • 5
  • 42
  • 64
0

Change your class to this :

class Category {

protected $DB;

function __construct()
{
    $this->DB = new Db('localhost', '3306', 'shop', 'root', '');
}

public function getAllCategories()
{
    $query = $this->DB->query("SELECT * FROM categories");

    return $query;
}

... }

Amir Kaftari
  • 986
  • 9
  • 10
  • `$this->DB`, not `$this->$DB` – Qirel Apr 30 '19 at 06:18
  • 1
    You might also want to add an explanation so the OP knows _why_ they should change their code to this. – M. Eriksson Apr 30 '19 at 06:24
  • They should change their code to this ,Because he wants to solve his problem. – Amir Kaftari Apr 30 '19 at 07:45
  • When posting an answer, you need to explain what they've done wrong and what you've changed to fix it. If not, the OP (and future visitors) won't know what the _actual_ solution was, and can't apply the same solution on other similar problems they might have. They will then come back and post similar questions again and again. That's not constructive to anyone. – M. Eriksson Apr 30 '19 at 08:31