Should Models Extend the Database? Performance considerations

I have a database class which extends PDO (and constructs it in its own constructor). For any model class I have that needs a database connection, I extend the database class for that model. So class DB extends PDO, and a model called UserInfoChange extends DB.

This allows me very easy access to writing sql queries without going through a pain the butt of connecting to the DB constantly or writing a bunch of boiler plate. I can just write $db_connection = $this->prepare($sql), bind my parameters, and execute. Very easy, very convenient. (I tried to model it after some other frame works.)

The problem: I have been profiling my code and it seems that database/PDO is being constructed for every class that extends the db that is instantiated, instead of just once. This is as expected due my architecture, but each DB/PDO class construction takes 10-20ms on my local machine, which is quite a bit (in context) and adds up for many models in play at once. I am trying to cut back on this, and just have one instantiation of PDO, instead of many. Would a static function be the answer here? Really have no idea how to go about cutting back here or what the best solution is.

Here is some example code (only a bare example, the real classes are much larger). (And forewarning: no validation takes place here, I handle validation in other classes that do usually do not access the database.)

DB class that extends PDO:

class DB extends PDO
{

	public function __construct()
	{
		try
		{
			parent::__construct(DSN, USER, PASSWORD_DB);
			$this->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
			$this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

		}
		catch (PDOException $e)
		{
			// error handling
		}

	}

}

Now a Model-type class:

class UpdateUser extends DB
{
	
	
	public $id_user;

	public $username;

	// Setters
	public function setIDUser($id_user)
	{
	    $this->id_user = $id_user;
	}
	
	public function setUserName($username)
	{
	    $this->username = $username;
	}

	
	// Single Updates
	public function updateUserName()
	{
		if (isset($this->username))
		{
			try
			{

				$sql = 'UPDATE users SET username = :username WHERE id_user = :id_user';

				$dbq = $this->prepare($sql);
				$dbq->bindValue(':username', $this->username);
				$dbq->bindValue(':id_user', $this->id_user);
				$dbq->execute();
			}
			catch (PDOException $e)
			{
				// error handling
			}

		}
	}
}

Any ideas on the best way to preserve the convenience but also improve performance?

Pass an instance of your DB object to a model in the constructor and use that.

Basically

class Model
{
     protected $db;
     public function __constuct(DB $db)
     {
        $this->db = $db;
     }

     public function doSomething()
     {
        $stmt = $this->db->prepare(/* SQL GOES HERE */);
        // etc
     }
}

Create a class with the $db field and the constructor and let all models extend that one.

2 Likes

isnt it easier to use the Repository design pattern? i often see things like $model = new Model()->where(ā€˜somethingā€™,ā€˜=ā€™,ā€˜somevalueā€™) for me its just not make sense at all. a model find by some methods their data? why not

$model = $this->repository->findBySomeField($fieldValue);
$model->doSomething();

i think the model should not know anything about their datasource, the provider schould return a ready to use model.

also about class UpdateUser extends DB, a good advise to figure out what you can extends is if you replace the word extends with ā€œis aā€ and then read it

UpdateUser is a DB ā€¦ does it really make sense? no , so no extends at all

Try to use extends as less as possible, go with Composition over Extension

just my 2 ct :smiley:

1 Like

I tried what you suggested Scallio and then profiled it, and it had the desired effect. Thanks.

Itā€™s a bit off topic, but the way I organized the PDO to Database to Model class hierarchy was to try to emulate something Laravel seemed to do with its default User model, which is extend its ORM, Eloquent. (http://laravel.com/docs/4.2/eloquent). I might be wrong on this, but this allows the user model to have a closer relationship with the database so that it can run queries. I am not sure how it works (never really got into it, just looked at examples), but is it typical for a Laravel model to extend the database, or maybe I am way off base here? Or is putting the database into the constructor the more common route?

@BlackScorp: I am not very familiar with the repository design pattern, so I will look into it. Any links you might endorse on the topic would be helpful. I looked up a few and found many, but not as many oriented towards php, and not many at all with real world web-app examples.

The Eloquent class they are extending there is not a database connection, but a model class, as evident by the fact that it has a connection variable to tell the model which connection to use

From the page you linked to:

[quote]
Likewise, you may define a connection property to override the name of the database connection that should be used when utilizing the model.[/quote]

As shown in my previous example you can also run queries if you donā€™t extend the DB have an internal connection to a DB instance :slight_smile:

Yes, that is how a lot of frameworks do it. Either that, or they use some sort of repository to look up the database connection. Either way, letter the model extend the DB class is highly uncommon.

1 Like

@ShinVe http://www.sitepoint.com/repository-design-pattern-demystified/

1 Like

My thanks to both of you. Iā€™m slowing progressing to cover some of the more intermediate level considerations in PHP, so there is a lot of ground to cover (and clear up).

Nope, that is a terrible design. Use composition and pass the database connection into the objects that require it as a dependency. For something more sophisticated consider looking into a dependency injection container to manage dependencies and possibly automate injection.

The Symfony DIC is a good place to start for learning about dependency injection and common container features.

A good way to put this to is a model IS NOT a database. Therefore, using inheritance is not the proper approach. A model is a domain level representation of a single entity which might consume a database or other persistent storage mechanism such as the file system to get data. Thus, the relationship is better represented through composition (dependency injection) rather than inheritance.

Speaking of DI, I really like this introduction to DI from Aura.

Speaking of DI,

DI is something different than a Container

DI means only that you make use of Typehints just wanted to mention it, cause many ppl pass then the entire container to a class and pick the right classes from containerā€¦