Evolution of PHP Object Instantiation with detailed error diagnostics
Tags: php, oophp, pattern
Published: 2021-04-29 20:18:24

---
title: Evolution of PHP Object Instantiation with detailed error diagnostics
published: true
description: Describing a safe method of object instantiation.
tags: PHP, OOPHP, Pattern
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/24zraw8a1pqi0vgs2ou7.png
---

I've recently devised a new method (to me) of object instantiation that I think I'm going to use a lot in my future developments. I strongly suspect it's an established design pattern that probably has a name, but I didn't get a CS qualification and I made it up myself.

I say made it up, but mathematicians are fond of stating how they *discover* new maths, that it already exists in nature and the structure of the universe, and in a similar way I suspect this pattern is a natural evolution that has occurred before, multiple times.

### Private constructor with optional return object ###

Most basic object classes I create have private constructors and offer one or more public instantiation methods:

```PHP
class token {
    public static function create(string $prop) : ?token {
        $token = null;
        if(is_valid($prop)){
            /* I use static routinely in case I want to extend 
            the class later */
            $token = new static();
            $token->prop = $prop;
        }
        return $token;
    }

    protected function __construct(){

    }
}
```
Cool, now when we call `token::create('Foo')` we may get a token object or we may get null. It's a start.

But what if something goes wrong? And we want to know what? NULL doesn't tell us a great deal.

Something I've done in the past is to pass in a generic error handler to the constructor.

```PHP
class token {
    public static function create(string $prop, errorHandler $errorHandler) : ?token {
        $token = null;
        if(is_valid($prop)){
            /* I use static routinely in case I want to extend the 
            class later */
            $token = new static();
            $token->prop = $prop;
        } else {
            $errorHandler->addError(errorHandler::INVALID_PROPERTY, $prop.' is not a valid string for some reason.');
        }
        return $token;
    }
    ...
}
```

That's a bit better, we can give our errorHandler class any number of error constants and compile an array of error messages to feed back to the user.

The problem with this is two-fold. If the `::create` method has more than a few parameters, devs have to pass defaults for all the intermediate properties before they can append the errorHandler object, unless we put it up front I suppose; and secondly we have to create the errorHandler object prior to creating the object we actually want, every single time. It adds a boilerplate overhead to every object instantiation that I'd rather avoid.

### Introducing the requestResult object ###

The `::create` method comes with the implication that it's kind of going to work...that it'll return an object of the correct type. Adding the ? on the typehint because things might go awry is where the problems arise. 

What if we could be certain we're going to get back on object of a particular type? We could "request" an object and process the return result.

```PHP
class token {
    public static function request(string $prop) : tokenRequestResult {
        $result = new tokenRequestResult();
        if(!is_valid($prop)){
            $result->addError(tokenRequestResult::INVALID_PROPERTY_VALUE);
        }
        if(!$result->getErrorMask()){
            $token = new static();
            $token->prop = $prop;
            $result->setObject($token);
        }
        return $result;
    }
    ....
}
```

I've defined an interface and abstract class to handle most of the functionality of the `requestResult` object.

```PHP
interface requestResult {
	public function getErrorMask() : int;
	public function getErrorMessages() : array;
	// TODO: When PHP >= 7.4 add typehints as per commented lines below
	public function getObject();
	public function setObject($object);
//	public function getObject() : Object;
//	public function setObject(Object $object);
	public function addError(int $maskBit, ?string $message);
}

abstract class baseRequestResult implements requestResult {
	protected $errorMask = 0;
	protected $errorMessages = [];
	protected $object;

	public function getErrorMask(): int {
		return $this->errorMask;
	}

	public function getErrorMessages(): array {
		return $this->errorMessages;
	}

	public function buildErrorMessageList(dataWriter $writer) : string {
		$response = '';
		if(count($this->errorMessages)){
			$response .= $writer->beforeResults();

			foreach($this->errorMessages as $errorMessage){
				$response .= $writer->item((object)['message'=>$errorMessage]);
			}

			$response .= $writer->afterResults();
		} else {
			$response .= $writer->noResults();
		}
		return $response;
	}

	// TODO: When PHP >= 7.4 add typehints as per interface
	abstract public function getObject();
	abstract public function setObject($object);

	public function addError(int $maskBit, ?string $message) {
		$this->errorMask |= $maskBit;
		if($message && !in_array($message, $this->errorMessages)){
			$this->errorMessages[] = $message;
		}
	}
}
```

And the tokenRequest class is really very small and easily replicable for different object types:

```PHP
class tokenRequestResult extends baseRequestResult {
	const INVALID_TYPE = 1<<0;
	const MATCHING_TOKEN_IN_USE = 1<<1;

	// TODO: When PHP >= 7.4 use typehint for \token here instead of instanceof condition
	public function setObject($token) {
		if($token instanceof \token){
			$this->object = $token;
		}
	}

	public function getObject() : \token {
		return $this->object;
	}
}
```

Externally, the API is then used like this:
```PHP
$tokenResult = token::request('Foo');
if($tokenResult->getErrorMask()){
    /*
        There are errors that need handling. We can flesh out the 
        tokenRequestResult object to handle the various error mask values 
        and/or error messages, pass in a writer class to output the 
        errors to screen, whatever.
    */
    
} else {
    /*
        But if reported errors are 0 we can be confident that `->getObject()` 
        will get us our native `token` object and act accordingly
    */
    $token = $tokenResult->getObject();
    $token->callPublicMethodOfTokenObject();
}
```

I think this technique is going to prove pretty valuable in my work. Like I said, it's probably a documented pattern but given I don't know what it might be called I'm not sure how to begin looking it up.

If you happen to know its name, I'd be thankful, but if it's new to you I hope you find it useful.