Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Static v Singleton class - ConnectionFactory explained

I'm new to this level of PHP programming and I've been reading a post about singleton and static classes. I'm in the process of writing a class that would facilitate my DB connections.

I came across the following code by Jon Raphaelson (here) :

class ConnectionFactory
{
    private static $factory;
    public static function getFactory()
    {
        if (!self::$factory)
            self::$factory = new ConnectionFactory(...);
        return self::$factory;
    }

    private $db;

    public function getConnection() {
        if (!$this->db)                 // this line was modified due to comment
            $this->db = new PDO(...);       // this line was modified due to comment
        return $db;
    }
}

function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

It seemed like I had found what I was looking for, however I have a few questions about it.

  1. self::$factory = new ConnectionFactory(...); - I don't see a constructor in this class. Do I just create this constructor and pass in the db details ('dbname', 'user', 'pass', etc)?
  2. the getSomething() function, I'm assuming that the intent was to put all of the actual functions that would retrieve data within the ConnectionFactory class - and this is the reason for this function being in this class. Otherwise, I would have expected this function to be within another class. [edit] SKIP THIS QUESTION, I didn't see the one bracket.
  3. What happens when two users are logged into the site and are requesting the DB connection (both are doing updates, etc)? Will it be an issue that this is a singleton?

Thanks!

like image 532
NEW2WEB Avatar asked Mar 15 '26 05:03

NEW2WEB


1 Answers

This is mostly to expand on my comments under the question...

The better "singleton" pattern would be this:

class ConnectionFactory {

    protected static $connection;

    public function getConnection() {
        if (!self::$connection) {
            self::$connection = new PDO(...);
        }
        return self::$connection;
    }

}

The users of this factory should expect an instance of it, not call it themselves:

class Foo {

    protected $connectionFactory;

    public function __construct(ConnectionFactory $factory) {
        $this->connectionFactory = $factory;
    }

    public function somethingThatNeedsAConnection() {
        $connection = $this->connectionFactory->getConnection();
        ...
    }

}

$foo = new Foo(new ConnectionFactory);

This allows Foo to get a connection itself when needed, but also allows you to inject some alternative connection into Foo, for example for testing purposes.

As a convenience measure and to cut down on instantiation complexity, this pattern is also good:

class Foo {

    protected $connectionFactory;

    public function __construct(ConnectionFactory $factory = null) {
        if (!$factory) {
            $factory = new ConnectionFactory;
        }
        $this->connectionFactory = $factory;
    }

    ...

}

This still allows the dependency to be injected and overridden, but it doesn't require you to inject a factory every time you instantiate Foo.

like image 156
deceze Avatar answered Mar 17 '26 01:03

deceze



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!