3

It's a basic website. Based off answers on here, I'm doing this:

private $db;

public function __construct($id = null) {
    $this->db = Db::getInstance(); //singleton from the Db class

But if there is a static method, I can't use the object specific variable.

Is there anything better than having to manually specify the db variable inside the static method?

public static function someFunction($theID){
    $db = Db::getInstance();

EDIT: Making the variable static doesn't solve the problem. Access to undeclared static property. I'd still have to assign the variable within the static function. The question is asking if there's a way around this.

My DB Class (although not important to this discussion):

class Db {
private static $m_pInstance;
private function __construct() { ... }

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

}

18
  • 1
    Is there some reason you can't just use $this->db inside of someFunction? Why else are you setting it in the constructor? Commented Dec 28, 2011 at 0:17
  • Just don't use static methods Commented Dec 28, 2011 at 0:18
  • @DaOgre: someFunction is static Commented Dec 28, 2011 at 0:19
  • Fyi: Db::getInstance() isn't a singleton, it's a factory, which returns a singleton. Commented Dec 28, 2011 at 0:25
  • @Digital Precision: why do you think so? Also, there are 2 different factory patterns. Which one you mentioned about? Commented Dec 28, 2011 at 0:30

2 Answers 2

5

Yes, you can make the $db static:

static private $db;

I'm assuming that's what you need, since you're accessing it from a static method. If there's any reason why you wouldn't want this, that must mean that the method probably shouldn't be static.

EDIT:

As per @zerkms (thanks) comments, you access static variables with self:::

self::$db = Db::getInstance(); 
Sign up to request clarification or add additional context in comments.

18 Comments

... but this will throw strict standards violation notification. Not cool
@zerkms I'm not sure I understand what you mean. Are you saying statics are bad? statics are part of OO design.
ideone.com/aupWx. Java, c#, etc will not allow you to access to the static variables using this instance reference. PHP does, but it doesn't mean it has something to do with good OO design
@zerkms "static instance retrieved from singleton" makes it sound so dirty :)). I now feel I'm in the dark side of OOP.
Problem: the $db variable is assigned in the constructor which isn't called when the static method is called. So how do I deal with this? "Access to undeclared static property"
|
3

You've outlined one of the issues you come across when co-mingling static methods within a class that can also be insantiated, setting member variables via instantiation, and expecting access to their values through static method call. The only real way around this is to set a class specific singleton for the database singleton, or pass in the DB object to the static method.

// Option 1
class MyClass
{
    private static $db;

    public function __construct($id = null)
    {
        self::$db = Db::getInstance(); //singleton from the Db class
    }

    public static function someFunction($theID)
    {
        self::$db->query('SELECT * FROM my_table');    
    }
}

// Singleton DB for MyClass will be initalized via constructor
$myClass = new MyClass();    

// This call will have access to DB object set via class specific singleton
MyClass::someFunction(4);

// Option 2
class MyClass
{
    private $db;

    public function __construct($id = null)
    {
        $this->$db = Db::getInstance(); //singleton from the Db class

        if (!is_null($id)) {
            $this->id = $id;
        }
    }

    public function getDb()
    {
        return $this->db;
    }

    public function getId()
    {
        return $this->id;
    }

    // Sub-Option 1: If Id ISNT set via object
    public static function someFunction($object, $theID)
    {
        $object->getDb()->query('SELECT * FROM my_table WHERE id = ' . (int) $theID);    
    }

    // Sub-Option 2: If Id IS set via object
    public static function someFunction($object)
    {
        $object->getDb()->query('SELECT * FROM my_table WHERE id = ' . (int) $object->getId());    
    }
}

// Sub-Option 1 call
$myClass = new MyClass();

MyClass::someFunction($myClass, 4);

// Sub-Option 2 call
$myClass = new MyClass(4);

MyClass::someFunction($myclass);

1 Comment

Since most of the time you are calling a static method from an instantiated class, passing the DB object to the static method is a great way to not have to deal with the waterfall of issues trying to declare the DB singleton class as static. In my case this answer worked perfectly and didn't make a mess.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.