Aug 13, 2014
Table of contents:
Over the last couple of weeks we’ve looked at setting up the foundation of creating an Active Record style PHP SDK. One of the beautiful things about the Active Record pattern is the very intuitive and easy to use interface that is presented to the developer. The Active Record pattern presents entities and their storage as one interface, whilst hiding the implementation beneath the surface.
A couple of weeks ago we saw how in order to ensure we are able to test our code in isolation, we must inject the HTTP connection object as a dependency of the entity.
In today’s tutorial we’re going to look at writing a Factory to tuck away those implementation details and provide a better interface for the developer to work with.
Before we jump into the code, first let’s review why we need a Factory.
A Factory is simply an object that manages the creation of other objects. This is beneficial because it allows us to hide the complexity of instantiating certain objects whilst also ensuring that every instance of that object will be created in the same way.
For example, imagine we had a User
object that had a Connection
dependency:
$user = User(new Connection("key", "secret"));
Whenever you wanted an instance of User
you would also have to inject an instance of Connection
with the correct key
and secret
.
However what would happen if the Connection
object suddenly needed a third parameter? Well, you would have to find each instance within your project and update it, urgh!
Instead we can use a factory object to create the User
object for us:
$user = $factory->user();
The Factory
class is very simple because all it needs to do is to create other objects:
class Factory
{
public function user()
{
return new User(new Connection("key", "secret"));
}
}
I’ve actually covered the Factory Method Design Pattern in a previous tutorial so I won’t go into any more detail. If you are new to the concept of Factory objects, take a look at that article before continuing with this one.
The first thing I’m going to do is to write a couple of tests for the functionality I want to create.
Create a new file called CapsuleCRMTest.php
under the tests
directory:
use Mockery as m;
class CapsuleCRMTest extends PHPUnit_Framework_TestCase
{
}
I’m going to call my factory class CapsuleCRM
as I prefer to name the main entry point of a package after the name of the package itself.
The factory will have methods for each model instance of the API. In order to reduce code duplication I’ll write a setUp()
method that will be invoked before each test is executed:
public function setUp()
{
$connection = m::mock('PhilipBrown\CapsuleCRM\Connection');
$this->capsule = new PhilipBrown\CapsuleCRM\CapsuleCRM($connection);
}
You will notice that I’m mocking the Connection
instance. We are not interested in the HTTP connection in these tests so we can just mock it out.
The first test will ensure that an instance of the Connection
class is injected through the constructor of the factory on instantiation:
/**
* @expectedException Exception
*/
public function testCapsuleCRMRequiresConnection()
{
$c = new PhilipBrown\CapsuleCRM\CapsuleCRM("");
}
The second test will ensure that an instance of Party
is returned from the party()
method:
public function testCreateNewPartyModel()
{
$this->assertInstanceOf('PhilipBrown\CapsuleCRM\Party', $this->capsule->party());
}
Party is one of the resources of the API documentation.
Now if you run those tests you should see that they all fail.
Next we’ll write the code to make them pass.
The first thing I’ll do is to create the Party
model. For now this can just be an empty class as we’ll be actually implementing each model in the coming weeks.
Create a new file called Party.php
under src
:
<?php namespace PhilipBrown\CapsuleCRM;
class Party
{
}
Next we can create the factory. As I mentioned above, the factory should be a really simple class that has the single responsibility of creating new objects.
First, create a file called CapsuleCRM.php
under the src
directory:
<?php namespace PhilipBrown\CapsuleCRM;
class CapsuleCRM
{
}
Next, we need a __construct()
method that is injected with an instance of Connection
:
/**
* The HTTP Connection
*
* @var PhilipBrown\CapsuleCRM\Connection
*/
protected $connection;
/**
* Create a new instance of CapsuleCRM
*
* @param PhilipBrown\CapsuleCRM\Connection $connection
* @return void
*/
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
Remember to set the $connection
property on the class.
Finally we can implement the method to instantiate and return a new Party
instance:
/**
* Return a new Party model
*
* @return PhilipBrown\CapsuleCRM\Party
*/
public function party()
{
return new Party($this->connection);
}
Now if you run the tests again you should have all of your tests passing.
I really like the usage of factories in open source packages. A factory will hide a lot of the complexity of setting up objects and ensures that the developer won’t trip over by not instantiating something correctly. I think anytime we can provide a simple interface we should seize the opportunity. A lot of open source packages can be really complicated, but by simply implementing the factory pattern, we can make our code a lot more approachable and easier to pick up.
Now of course there is absolutely nothing from stoping a developer from bypassing the factory and instantiating the objects directly. If the developer chooses to go down this route they are more than welcome. In future tutorials I’ll show how we can put further restrictions in place to ensure that the dependencies that are required can’t be forgotten about.
As always, if you would like to grab a copy of the code that we are writing for this creating an Active Record style PHP SDK mini-series, you can find it on GitHub.