Instantiating Objects From Factory Classes in PHP

Auto instantiating objects created by factory classes.

1681 views
d

By. Jacob

Edited: 2020-07-27 11:05

factory classes in php, a php tutorial.

While using factories in PHP to build objects from lots of dependencies, you might be wondering how to best instantiate the object from your composition root (often your index.php file).

Creating the object from your constructor class does not work, so you will need to approach the problem differently.

I propose the following syntax:

$http_client = (new my_project\lib\factories\http_client_factory())->build();

The problem

While instantiating factory classes with the new keyword, you find that you can not return the final object directly from your constructor class, forcing you to first call a create() or build() method from your compositioning root.

You could load the object into a public property of the factory, but this would be dirty, as you would need to access your object through this property whenever using it. You could also use a singleton pattern for your factory, but people tend to dislike singletons.

Having to re-assign the object to a external variable in your composition root is also not very desirable, so what do you do? The following clearly does not work:

$http_client = new myProject\lib\factories\http_client_factory()->build();

And you probably also want to avoid this:

$factory_product = new myProject\lib\factories\http_client_factory();
$http_client = $factory_product->build();

However, the problem can be solved just by wrapping the new statement in some parentheses, reducing our work to this nice one-liner:

$http_client = (new myProject\lib\factories\http_client_factory())->build();

All you need to do in your factory class, is then to include your dependencies in the public build() method. Of course you should use Dependency Injection inside the factory itself.

A simple factory class

Factories are useful when you got an object that is made up of several other objects (dependencies), and you want to simplify the instantiation of the object. It also avoids having to memorize all the dependencies a object needs in order to be instantiated.

It is generally considered a bad practice to instantiate objects inside other objects using the new keyword (tightly coupled), but there is a exception for this, and that is within factory classes (loosely coupled).

A basic example of a factory class looks like this:

class file_handler_factory
{

    public static function build()
    {
        $superglobals = new \doorkeeper\lib\superglobals\superglobals();
        $helpers = new \doorkeeper\lib\php_helpers\php_helpers();
        $file_types = new \doorkeeper\lib\file_handler\file_types();
        return new \doorkeeper\lib\file_handler\file_handler($helpers, $superglobals, $file_types);
    }

}

The above is actually taken from a real project I am working on, and while still undergoing changes, it is a useful example of how to write a factory.

You could also seperate each dependency into its own method, but I personally found that this will just result in spaghetti code. For example:

class file_handler_factory
{
    public function build() {
      $this->create_superglobals();
      $this->create_helpers();
      return $this->create_file_handler();
    }

    private function create_superglobals()
    {
        $this->superglobals = new \doorkeeper\lib\superglobals\superglobals();
    }
    private function create_helpers()
    {
        $this->helpers = new \doorkeeper\lib\php_helpers\php_helpers();
    }
    private function create_file_handler()
    {
        $file_types = new \doorkeeper\lib\file_handler\file_types();
        return new \doorkeeper\lib\file_handler\file_handler($this->helpers, $this->superglobals, $file_types);
    }

}

Tell us what you think:

  1. In this Tutorial, it is shown how to redirect all HTTP requests to a index.php file using htaccess or Apache configuration files.
  2. How to create a router in PHP to handle different request types, paths, and request parameters.
  3. Tutorial on how to use proxy servers with cURL and PHP
  4. When using file_get_contents to perform HTTP requests, the server response headers is stored in a reserved variable after each successful request; we can iterate over this when we need to access individual response headers.
  5. How to effectively use variables within strings to insert bits of data where needed.

More in: PHP Tutorials