cult3

How to create an Active Record style PHP SDK Part 6

Aug 13, 2014

Table of contents:

  1. Why do you need a factory?
  2. Writing the tests
  3. The Party model
  4. The Factory
  5. Conclusion

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.

Why do you need a factory?

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.

Writing the tests

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 Party model

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
{
}

The Factory

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.

Conclusion

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.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.