1

I´ve made a database connection with PDO and the singleton pattern. Everything works fine as long as I have the $_db variable set as public but it needs to be private... When I make it private I off course get the Error: Cannot access private property Database::$_db Can someone tell me how to make it private and still be able to get an instance?

When I call the database connection from another file I call the function getInstance() Here is an example how I call it from one file:

$db = Database::getInstance();
$query = $db->_db->prepare("SELECT `password`, `id` FROM `users` WHERE `username` = ?");     

This is what my database connection file looks like:

class Database 
{
    private $_db;
    static $_instance;

    private function __construct() 
    {
        $this->_db = new PDO('mysql:host=localhost;dbname=mvcuser', 'root', '');
        $this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    private function __clone(){}

    public static function getInstance() 
    {
        if (!(self::$_instance instanceof self)) 
        {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    public function query($sql) 
    {
    return $this->_db->query($sql);
    }
}
Lisa
  • 416
  • 6
  • 16
  • 29
  • 1
    [Please](http://stackoverflow.com/a/4596323/1607098), [don't](http://www.youtube.com/watch?v=-FRm3VPhseI) [use](http://www.youtube.com/watch?v=RlfLCWKxHJ0) [*singletons*](http://stackoverflow.com/q/137975/1607098) – Touki Nov 20 '13 at 16:22
  • It´s an assignment so not my choice... But out of curiosity, why not? @Touki – Lisa Nov 20 '13 at 16:23
  • You can check links hidden in each word to know why you shouldn't – Touki Nov 20 '13 at 16:25
  • Thanks just noticed:) @Touki Still need to solve my problem though:( – Lisa Nov 20 '13 at 16:28
  • Err... Do you quite realize, what does "protected" mean? – Your Common Sense Nov 20 '13 at 16:43
  • Is that an answer to my question? First of all I´m talking about private not protected, and yep I know what it means:P With a singleton pattern you need to have it set to private and my problem was how to then access it from outside when it´s private... Problem solved now:) @YourCommonSense – Lisa Nov 20 '13 at 16:54
  • You are asking for having private a variable you **intend** to call publicly. Which is a merely contradicting condition. – Your Common Sense Nov 20 '13 at 17:17
  • I made a mistake in my first comment. private it had to be, to reflect your demand. – Your Common Sense Nov 20 '13 at 17:19

2 Answers2

1

You don't need to write

$db->_db->
Because you're already using instance of your class.

Here you have a reference of your DB class

$db = Database::getInstance();

Every time when you decide to make a query or someting use only $db->query();, $db->prepare();

Look at your code: you're already using $_db reference in you DB class. So, you don't need to call $_db as public variable.

Dezigo
  • 3,220
  • 3
  • 31
  • 39
  • `$db->prepare()` will fail as there is no such method in the `Database` class. – ComFreek Nov 20 '13 at 16:35
  • Of course not,it works as adapter.,you need to create a method prepare() and call it inside the class $this->_db->prepare(); – Dezigo Nov 20 '13 at 16:39
  • and I've written ( or something use only),so there is no reason to downvote me. – Dezigo Nov 20 '13 at 16:40
  • I don't know why some people always think that one has downvoted them if they only commented on that post! I did **not** downvote you. – ComFreek Nov 20 '13 at 16:43
  • Got it! Thank you! I added a prepare() method aswell and it works like a charm! @ComFreek – Lisa Nov 20 '13 at 16:50
1

Oh, I can't stand all that static struggle no more.

Here is a minified version of @nikic's static PDO class

class DB
{
    protected static $instance = null;

    final private function __construct() {}
    final private function __clone() {}

    public static function instance()
    {
        if (self::$instance === null)
        {
            $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME;
            self::$instance = new PDO($dsn, DB_USER, DB_PASS);
            self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        return self::$instance;
    }
    public static function __callStatic($method, $args) {
        return call_user_func_array(array(self::instance(), $method), $args);
    }
}

Used the way static classes ought to be

echo DB::query("SELECT 'foo'")->fetchColumn();
echo DB::lastInsertId();

Without this __callStatic() magic you will have to mirror all the PDO methods manually, just like ComFreek said.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345