Decoupling the Interaction Between Objects with Factory Methods

Welcome to the fifth part of a six-part series on implementing factory methods in PHP 5. In this part, I show how the removal of a factory method inside the constructor of the class that originates persistent objects can produce a huge impact in the way that those objects handle its dependency, which happens to be a database handler object.

Unquestionably, defining factory methods during the development of an application is a task that both programmers and web developers must tackle frequently. In the case of PHP 5, this process is fortunately a no-brainer one, due to the versatility of its robust object model and its flat learning curve.

While the correct implementation of factory methods in PHP 5 is certainly a tame procedure for developers who have solid experience, it can be quite challenging and intimidating for those who are currently taking their first steps in object-oriented web development.

So, if you’re interested in learning the key concepts that surround the definition of factory methods in PHP 5, then start reading this article right away!

And now that you’ve been introduced to the subject of this series, it’s tine to review the topics that were discussed in the last article. In that installment of the series, I demonstrated how useful a factory method can be for reducing the number of instances of a database handler that need to be used by other classes.

Basically, this factory method returned a Singleton instance of this database handler, which was shared seamlessly by a couple of persistent objects, thus improving the way that these objects managed their interaction with this dependency.

However, in its current state, the class that originates those persistent objects is still responsible for creating the database handler, which is detrimental in terms of building truly decoupled classes. Thus, in this fifth part of the series I’m going to modify the signature of the class that models persistent objects, which will contribute to making them more independent from the aforementioned database handling object.

Now, it’s time to leave the preliminaries behind and learn more useful things about building factory methods in PHP 5. Let’s go!

{mospagebreak title=Review: implementing a simple factory method in PHP 5}

In the introduction, I said that a simple factory method can improve the relationship established between a persistent class and its corresponding dependency, which in this case happens to be a MySQL database handler. However, it’d be quite useful to recall how these sample classes were defined in the preceding tutorial, and how they can be put to work together as well.

Bearing this in mind, below I listed the signatures of those classes, accompanied by a short script that shows how to use them in a concrete situation.

First, take a look at the definition of the MySQL handling class:

class MySQL

{

private $result = NULL;

private $link = NULL;

private static $instance = NULL;

 

// returns a singleton instance of MySQL class (chainable)

public static function factory($host, $user, $password, $database)

{

if (self::$instance === NULL)

{

self::$instance = new MySQL($host, $user, $password, $database);

}

return self::$instance;

}

// connect to MySQL

public function __construct($host, $user, $password, $database)

{

if (FALSE === ($this->link = mysqli_connect($host, $user, $password, $database)))

{

throw new Exception(‘Error : ‘ . mysqli_connect_error());

}

}

 

// perform query

public function query($query)

{

if (is_string($query) AND empty($query) === FALSE)

{

if (FALSE === ($this->result = mysqli_query($this->link, $query)))

{

throw new Exception(‘Error performing query ‘ . $query . ‘ Error message :’ .mysqli_error($this->link));

}

}

}

 

// fetch row from result set

public function fetch()

{

if (FALSE === ($row = mysqli_fetch_assoc($this->result)))

{

mysqli_free_result($this->result);

return FALSE;

}

return $row;

}

 

// get insertion ID

public function getInsertID()

{

return mysqli_insert_id($this->link);

}

// count rows in result set

public function countRows()

{

if ($this->result !== NULL)

{

return mysqli_num_rows($this->result);

}

}

// implement destructor to close the database connection

function __destruct()

{

mysqli_close($this->link);

}

}

And now that you’ve surely recalled how the “MySQL” class looked, here’s the other one, which takes advantage of the functionality of “MySQL” to save and retrieve its properties from a specified database table:

class User

{

private $data = array();

private $id = NULL;

private $db = NULL;

 

// constructor

public function __construct($id = NULL)

{

$this->db = MySQL::factory(‘host’, ‘user’, ‘password’, ‘database’);

if ($id !== NULL)

 {

$this->id = $id;

$this->db->query(‘SELECT * FROM users WHERE id=’ . $this->id);

$this->data = $this->db->fetch();

}

}

 

// set undeclared property

public function __set($property, $value)

{

if ($property !== ‘name’ and $property !== ‘email’)

{

return;

}

$this->data[$property] = $value;

}

 

// get undeclared property

public function __get($property)

{

if (isset($this->data[$property]) === TRUE)

{

return $this->data[$property];

}

}

 

// save object to session variable

public function __destruct()

{

if ($this->id === NULL)

{

$this->db->query("INSERT INTO users (id, name, email) VALUES (NULL, ‘$this->name’, ‘$this->email’)");

}

else

{

$this->db->query("UPDATE users SET name = ‘$this->name’, email = ‘$this->email’ WHERE id = $this->id");

 }

}

}

As I explained before, this “User” class is a blueprint for building persistent objects that use a MySQL table to store the values assigned to its pertinent properties. However, the most relevant detail concerning the way this class works is the implementation of its constructor, since this method is entirely responsible for building an instance of the database handler. Even though the factory method of the database handler returns only Singletons to client code, this obviously isn’t a good thing. The persistent class should only be tasked with handling its properties, not with spawning other objects.

In addition, here’s a basic example that shows how to make use of the two classes shown previously for creating two persistent user objects:

// create first user object

$user1 = new User();

$user1->name = ‘Susan Norton';

$user1->email = ‘susan@domain.com';

 

// create second user object

$user2 = new User();

$user2->name = ‘Mary Smith';

$user2->email = ‘mary@domain.com';

Well, to be frank, the above script looks pretty clean, and works well enough, since the persistent objects are constructed in a straightforward fashion. Nonetheless, things are a bit more complicated behind the scenes due to the incorrect instantiation of the database handler.

So, can this issue be addressed easily? Fortunately, the answer is a resounding yes! A small change in the definition of the constructor of the persistent “User” class will solve this problem.

But the full details of this modification will be discussed in the next section. So, go ahead and read the following segment.

{mospagebreak title=Using a factory method more efficiently}

In the earlier segment, I reintroduced the example created in the previous tutorial of this series, which showed how to construct a pair of persistent objects by using a basic MySQL abstraction class. As I explained in that section, though, the class that originates these persistent objects is charged with creating an instance of the database handler, which introduces a serious issue that goes to the  detriment of building loosely decoupled classes.

Luckily, this issue can be fixed with only minor headaches, simply by moving the factory method of the database handler out of the constructor of the “User” class. If this explanation sounds confusing to you, then pay close attention to the modified definition of this class, which now looks like this:

class User

{

private $data = array();

private $id = NULL;

private $db = NULL;

 

// constructor

public function __construct(MySQL $db, $id = NULL)

{

$this->db = $db;

if ($id !== NULL)

{

$this->id = $id;

$this->db->query(‘SELECT * FROM users WHERE id=’ . $this->id);

$this->data = $this->db->fetch();

}

}

 

// set undeclared property

public function __set($property, $value)

{

if ($property !== ‘name’ and $property !== ‘email’)

{

return;

}

$this->data[$property] = $value;

}

 

// get undeclared property

public function __get($property)

{

if (isset($this->data[$property]) === TRUE)

{

return $this->data[$property];

}

}

 

// save object to session variable

public function __destruct()

{

if ($this->id === NULL)

{

$this->db->query("INSERT INTO users (id, name, email) VALUES (NULL, ‘$this->name’, ‘$this->email’)");

}

else

{

$this->db->query("UPDATE users SET name = ‘$this->name’, email = ‘$this->email’ WHERE id = $this->id");

}

}

}

Didn’t I tell you that the coupling issue could be solved easily? Well, if you look at the improved definition of the “User” class, then you’ll realize that I was right! As shown above, the factory method that originally created an instance of the database handler has been completely removed from the class’s constructor, thus delegating this task to its outer environment.

Now the constructor simply accepts an instance of the database handler as a passive player, which is expected to be supplied from the outside, rather than from its inner context. This approach is commonly known as “dependency injection by constructor,” and its implementation is as simple as that.

So far, so good. Having introduced that small change into the definition of the previous persistent user class, the next step is to set up an example that shows how this class and its corresponding database dependency can be put to work in tandem.

Therefore, in the last section of this article I’m going to create that example for you. Now, simply click on the link below and keep reading.

{mospagebreak title=Putting the sample classes to work}

If you’re like me, then it’s probable that you want to see how the modified version of the “User” class can be used to build a couple of persistent objects. Below I coded a script that does precisely that. Here it is:

// create first user object

$user1 = new User(MySQL::factory(‘host’, ‘user’, ‘password’, ‘database’));

$user1->name = ‘Susan Norton';

$user1->email = ‘susan@domain.com';

 

// create second user object

$user2 = new User(MySQL::factory(‘host’, ‘user’, ‘password’, ‘database’));

$user2->name = ‘Mary Smith';

$user2->email = ‘mary@domain.com';

Without a doubt, the relationship between the “User” class and the MySQL database handler is now much more independent. As you can see, the factory method of “MySQL” is used to inject a Singleton into the constructor, which demonstrates how simple it is to implement the injection dependency pattern via a constructor method.

In addition, the previous example can be streamlined even more, by coding it as follows:

// create instance of MySQL class via the factory method

$db = MySQL::factory(‘host’, ‘user’, ‘password’, ‘database’);

// create first user object

$user1 = new User($db);

$user1->name = ‘Susan Norton';

$user1->email = ‘susan@domain.com';

 

// create second user object

$user2 = new User($db);

$user2->name = ‘Mary Smith';

$user2->email = ‘mary@domain.com';

There you have it. In this last case, the factory method of the “MySQL” class is called only once, and then the corresponding instance is simply inputted into the respective constructors of the persistent objects.

Finally, with this example I’m finishing this fifth tutorial of the series. As always, feel free to edit all of the code samples included in this article to arm yourself with a much better background in building factory methods with PHP 5.

Final thoughts

That’s about it for now. Over this fifth installment of the series, I showed how the removal of a factory method inside the constructor of the class that originates persistent objects can produce a huge impact in the way that those objects handle its dependency, which in this specific case happens to be a database handler object.

In the last chapter, I’m going to explain how to further improve the relationship established between the sample classes shown earlier, which surprisingly won’t require the use of a factory method.

Here’s my final suggestion: don’t miss the conclusion!

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye