Jump to content

Archived

This topic is now archived and is closed to further replies.

yonta

Singleton to avoid multiple calls to pconnect ?

Recommended Posts

Right now i'm following the mvc pattern in an app i'm building, so i basically have templates, controllers and models.
There's one model per mysql table, so if i have a products table i'll have a products_model with all the basic CRUD functionality.
A controller can use one or several models. For example, each product can have several documents and so there's a product_docs table and its corresponding model. This means that the product_controller can use the products_model and the product_docs_model.

All models extend (inherit from) a common database manager class and it's this common class that's responsible for actually connecting to the database (it has a connect method).

Now for my problem: if in a single call to the server more than one model is used, there will be more than one instance of the database manager class created, and so more than one attempt to connect to the database (it's a persistent connection, btw) and there seems to be no need for it. In a single call to the server i only need to connect once to the database. I mean, performance wise it just seems stupid. And so i thought i could use the singleton pattern to ensure that only one attempt to connect to the database was done.

something like this:

[code]
class products_Model extends DbManager
{

var $select_titles;
var $tablename;
var $security;

function products_Model()
{
$this->tablename = 'products';
$this->select_titles = 'SELECT prod_id, prod_title, prod_text, prod_ispub FROM '.$this->tablename;
if(!singleton::getInstance('DbManager')) //if there's no dbmanager in singleton array, attempt to connect
parent::connect();
                //without the singleton pattern it was just like below
                //parent::connect();
$this->security = new Security();
}
[/code]

But searching around i found this:

"The singleton pattern applies to the situation where you need a single, global instance of a class. It fits situations where a factory object returns uniform objects, such as file handles or user sessions. These aren't good candidates for being implemented in a PHP script because the [b]language provides built-in solutions such as persistent database connections[/b]." ( http://www.zend.com/zend/trick/tricks-app-patt-php.php )

which of course got me thinking.

Am i thinking about this the totally wrong way? Maybe i should do it another way? Or is it actually ok? Or there's no need to worry about making several calls to pconnect since it's a persistent connection anyway? Or should i use delegation ($db = new DbManager(); ) instead of inheritance (.. extends DbManager ) ?

Any input would be a great great help.

Share this post


Link to post
Share on other sites
Ok, maybe my post was a bit confusing.

If you follow the mvc pattern in your apps, do you have a common database manager for all your models (in my case, it's a wrapper for adodb - http://adodb.sourceforge.net/ ) or not? If not, why not?

If you do have a common db manager, how do you avoid multiple attemps to connect to the database when you use more than one model in a controller? Do you simply detect if there's a connection already established or not?

I'm thinking i could use something like this:
[code]
$this->DB = &ADONewConnection('mysql');
  if(!$this->DB->IsConnected( ))
  {
  $this->DB->PConnect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_DATABASE) or
  trigger_error("Não é possível ligar à base de dados. Contacte o administrador.", E_USER_ERROR);
  }
[/code]

Do you do something like this as well?..

I'm still a bit new to the oop scene so if anyone could tell me how they do it, it would help.

Thanks

Share this post


Link to post
Share on other sites
Depends on your application's purpose. For example.. if it's a database management application, you may very well want multiple connections available.

Also take note when using pconnect - the function first checks if there is a connection already open that uses the same criteria (host, username, password)

If there is it will automagically use the existing connection instead of creating a new one. So the singleton part is taken care of for you..

[code]<?php

$link = mysql_pconnect(/* etc */);

$link2 = mysql_pconnect(/* same details as above */);

// $link2 is now a reference to $link

?>[/code]

Also rather than using a singleton, at worst I'll use a registry - however I much prefer (as do a lot of OOD/P folk) to just pass the Db object as a parameter.

[code]<?php

class SomeClass
{
    private $_db;

    public function __construct($db)
    {
        $this->_db = $db;
    }

    // or use a setter:
    public function setDb($db)
    {
        $this->_db = $db;
    }
}

// the above is prefered over the following:

class SomeClass2
{
    private $_db;

    public function __construct()
    {
        $this->_db = DbClass::getInstance();
    }
}

?>[/code]

OOD/P is all about encapsulation and controlled points on input/output. Using a Singleton (as above) is 'breaking' that rule of encapsulation.

Share this post


Link to post
Share on other sites
So are you saying that instead of extending the dbmanager in all my models, to avoid the repetition i could in a controller do

$db = new DbManager();
$products = new ProductsModel($db);

- basically just pass the dbmanager around, and since i only use one controller in a single call to the server there would be uneeded multiple instantiation. It does seem cleaner :) thank you, thank you

So pconnect checks if there's already a connection available. I use persistent connections because i read that it's faster but that you also increase the risk of having too many connections open. How is that if pconnect checks if there's already a connection available?

'if it's a database management application, you may very well want multiple connections available' - it is, but i really don't get why i would want multiple connections to the database. If multiple users are asking to see the same or different pages, shouldn't the server use the same connection to mysql? Could you explain this a bit more please?

thanks :)

Share this post


Link to post
Share on other sites
With non-persistent connections, the connection is terminated as soon as the script ends. A persistent connections stays open until explicitly told to close (or when the persistent connection timeout expires)

Persistent connections are 'assigned' to the webserver executable, so multiple users will use the same connection.

You only need worry about creating multiple connections if you are connecting to two or more database servers concurrently, otherwise you should continue to use the same connection.

Share this post


Link to post
Share on other sites

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.