PHP Template Method Pattern and Class Hierarchies

You can tell when you are not using class hierarchies when you start duplicating fields and methods. By cutting and pasting methods, if there was a defect in the Person class, there would most likely be a defect in the Employee class as well because the implementation was copied between the two.

class Person
{
    private $name;

    public function setName($name)
    {
        $this->name = $name;
    }
}

class Employee
{
    private $name;

    public function setName($name)
    {
        $this->name = $name;
    }
}

Template Method Pattern

The Template Method Pattern is a behavioral design pattern that allows you to defines a skeleton of an algorithm in a base class and let subclasses override the steps without changing the overall algorithm’s structure. This also leverages inheritance. Inheritance allows functionality to be built up from related classes. Each class provides specialized support that’s specific to a class’s purpose. It’s common that functionality in an object-oriented application is provided by class hierarchies rather than single, unrelated classes.

name = $name;
    }

    /**
    * The optional method should by default do nothing.
    */    
    abstract public function introduceSelf();

}

class Person extends PersonTemplate
{
    public function introduceSelf()
    {
        echo 'I am a...';
    }
}

class Employee extends PersonTemplate
{
    public function introduceSelf()
    {
        echo 'My job is a...';
    }
}

function getWho(PersonTemplate $e){
	$e->introduceSelf();
}
$employee = new Employee();
$person = new Person();

getWho($employee);
getWho($person);

Value Objects in PHP

Explanation:
The equality of two Value Objects is not based on identity (them being the same object, checked with the operator ===), but on their content. Value Objects are almost always immutable so that they can be shared between other domain objects. Mutating a Value Object means creating a new one, often with a Factory Method, that being said “Once set, the value object cannot be modified without changing its identity”.

Benefits:

  • Readability – the types of things that we pass to different parts of our application match to what they represent in our domain and it’s clearer what kind of value is expected without having to check in the code
  • Validation – ensure every existing value object is in a correct state. This means that we don’t have to check them when we use them.
  • Type hinting – we can type hint primitive types for parameters.
  • Immutability – One of the main causes of bugs in software is when the state of an object inadvertently changes, or its reference becomes null. Immutable objects can be passed around to any function and their states will always remain the same.

Value Objects are easier to create, test, use and maintain, they also compose related attributes as an integral unit. Value Objects are completely replaceable when the measurement or description changes and can be compared with others through value equality with Side-Effect-Free behavior.

When creating a new value object we need to make sure that it has a valid state, and that the class can not be extended.

final class Person
{
    /** @var string */
    private $name;
 
    public function __construct(string $name)
    {
        if (strlen($name) < 3 || !ctype_alpha($name)) {
            throw new InvalidArgumentException("Person class name property has to consist of at least three letters");
        }
        $this->name = $name;
    }
 
    public function equals(Person $person): bool
    {
        return $this === $person;
    }
 
    public function getName()
    {
        return $this->name;
    }
}


// Using setters for validation

final class Person
{
    /** @var string */
    private $name;
 
    public function __construct(string $name)
    {
	$this->setName($name);
    }

    private function setName(string $name)
    {
        if (strlen($name) < 3 || !ctype_alpha($name)) {
            throw new InvalidArgumentException("Person class name property has to consist of at least three letters");
        }
        $this->name = $name;
    }
 
    public function equals(Person $person): bool
    {
        return $this === $person;
    }
 
    public function getName()
    {
        return $this->name;
    }

}

PHP Null Object Design Pattern

From wikipedia: In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (“null”) behavior. This pattern is used to deal with the absence of an object by providing an alternative that indicates this absence. In short the null object replaces the checking for null values. These classes also adhere to the Open-Close Principle.

This pattern changes:

if (!is_null($obj)) { $obj->callMethod(); }
to just 
$obj->callMethod();

– Client code is simplified
– Reduces the chance of null pointer exceptions
– Fewer conditionals require less test cases


execute();
    }
}

$outputCommand = new OutputCommand();
$fileCommand = new FileCommand();
$app = new Application();

// Echo predefined string
$application->run($outputCommand); // Output from the command

// Create a file and append string to it
$application->run($fileCommand);

// Do nothing
$application->run();

The Front Controller Pattern PHP

It is a controller that handles all requests, you need to have a single part of your website that is fully responsible for handling all incoming requests to your site, “a single entry point”. This is usuall done by pointing all requests to a single PHP file, usually index.php. The request is forwarded to the appropriate controller action by matching the URL path, it sees every page as the same script..

A disadvantage to this pattern is the complexity of the Front Controller, which may have to manage the Dependency Injection and autoloading of the various views and/or controllers, “if your files are loaded by controller actions” on every request. The front controller pattern is a specialized kind of mediator pattern

Implementing the front controller pattern.

.htaccess


# Redirect to the front controller
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^page/([a-z]*)$ ./index.php?page=$1

turns
site.com/index.php?page=one
site.com/page/one

index.php