PHP: Modeling a URL Class

In this first part of a series, you’ll get an overview of what the Object Value pattern is and how to implement it in PHP. Specifically, in this part you’ll learn how to define a basic URL class that can be used to easily create immutable value objects.

While it’s fair to admit that PHP isn’t exactly the most elegant and efficient language that you can use for developing object-oriented applications, its improved object model packs in enough functionality to implement the OOP paradigm in a pretty thorough fashion. This  becomes particularly evident in the new methodologies that numerous PHP programmers are starting to adopt or already utilize for building web-based programs — especially when looking back to the old days when nearly every dynamic web page was generated through tons of transcription scripts.

Today, many developers appeal to the functionality of design patterns and other trusted approaches to solve software-related problems with elegance and efficiency. What’s more, things like Factories, Entities, Services and Repositories, just to name a few, have become familiar, as more and more programmers enter the terrain of domain-driven design (DDD). Granted, DDD in PHP is still in its infancy, particularly when compared to older and more mature languages like Java.   

This doesn’t mean, however, that the implementation of certain patterns extremely relevant in DDD is pointless. Not at all, trust me. To demonstrate the veracity of my claim, in this series of articles I’m going to introduce you to using the Object Value pattern. This is a fundamental paradigm in DDD (and in OOP by the way) which permits you to create value objects with minor headaches.

But wait a minute! You may be wondering what a value object is, right? Well, simply put, a value object is a raw object whose equality with reference to other objects is based on the values (hence its name) assigned to its fields, and not on its identity.

If this explanation sounds confusing to you, let me elaborate on the concept with an example: if two user objects have the same name (which can occur in the real world) and there’s no identity field that allows you to differentiate one from the other, they’re value objects because their equality is based on the values assigned to their properties.

On the other hand, if each user has its own identity (usually in the form of an ID), they suddenly become entities. The same rule can be applied to other simple objects as well, like dates, email addresses, URLs and so forth. Got the point? I hope so.

Also, in many cases a value object exposes a characteristic known as immutability, which is nothing but a fancy way to say that once its fields have been populated with the mandatory values, they can’t be changed later. This makes lot of sense for preventing inconsistencies between domain objects that make reference to the same value object. For the moment, though, I’m not going to complicate the theory of value objects with additional explanations, as each concept will be properly clarified by means of a concrete example.

So far, so good. Having roughly outlined what the Value Object pattern does, it’s time to start showing you some functional code samples, which hopefully will help you understand the actual functionality of value objects in PHP. Let’s get started!

Implementing the Value Object pattern: building a basic URL class

Since my purpose here is to demonstrate how to create value objects that may exist in a real-world environment, the first step that I’m going to take will consist of defining a simple class. It will be responsible for modeling basic URLs. In line with the concepts deployed in the introduction, every instance spawned from the class will be immutable, meaning that once its fields have been populated, they simply can’t be altered any further.

In reality, several approaches can be used for building immutable value objects. For instance, Matthew Weier O’Phinney shows how to accomplish this by using a combination of a private property and the magic “__set()” method, while Ralph Schindler relies on exceptions to build immutable objects derived from the ArrayObject PHP built-in class. While all these examples are perfectly valid and functional, in this case I’m going to take an approach similar to Giorgio Sironi’s, which in my opinion is the easiest to follow. Needless to say, you’re free to pick the method that best fits your needs.

Having clarified that point, here’s the initial definition of my own immutable URL-modeling class:

(Url.php)

final class Url
{
    private $_scheme; 
    private $_host;
    private $_path;
    private $_queryString;
   
    // constructor
    public function __construct($url)
    {
        if (!filter_var($url, FILTER_VALIDATE_URL, array(FILTER_FLAG_SCHEME_REQUIRED, FILTER_FLAG_HOST_REQUIRED))) {
            throw new UrlException(‘The specified URL is invalid.’);
        }
       
        $url = parse_url($url);
        $this->_scheme = $url['scheme'];
        $this->_host = $url['host'];
       
        if (isset($url['path'])) {
            $this->_path = $url['path'];
        }
       
        if (isset($url['query'])) {
            $this->_queryString = $url['query'];
        }
    }
}

 

(UrlException.php)

<?php

class UrlException extends Exception{}

Even though in its current state, the above “Url” class does nothing especially interesting, it indeed follows the model of an immutable value object. First, via its constructor, it accepts a string containing the URL that will be modeled, which is validated at a basic level by using a few PHP filters. And then, the scheme, host, path and query string parts of the given URL are assigned to the class’ fields.

By far, the most interesting facet of this process is that the values assigned to the pertinent fields are no longer modifiable, since the class doesn’t declare any mutator method for them. This means that instances created from the class will be immutable by default. On the other hand, two or more instances will be equal only if the values assigned to their properties are the same. In a few simple steps, I managed to create an immutable value object that models basic URLs. That was much easier to accomplish than you thought, wasn’t it?

It’s valid to point out that while the fields of the previous “Url” class are immutable, they should be accessed from client code through the corresponding getters. Since this is a must for good object-oriented programming, in the next section I’m going to add those additional methods to the class. This will extend its core functionality a bit.

To see how these methods will be properly implemented, click on the link that appears below and keep reading.

{mospagebreak title=Adding getters to the Url class}

If you’ve dealt with classes frequently, you’ll know that coding getters that provide access from client code to their protected or private fields is a breeze. The previous “Url” class is no exception. Since the class is already immutable (or the objects derived from it, to be more precise), it’s desirable to make it a little more functional by adding some accessors to it. So, here they are:  

// get the scheme part of the URL
public function getScheme()
{
    return $this->_scheme;
}

// get the host part of the URL
public function getHost()
{
    return $this->_host;
}

// get the path part of the URL
public function getPath()
{
    return $this->_path;
}

// get the query string of the URL
public function getQueryString()
{
    return $this->_queryString;
}

That’s not rocket science. Now that the proper getters have been implemented, each private property that the class declares can be accessed by client code in a truly simple manner. This is actually OOP 101, but for the sake of completeness I included the definition of these methods, so you can see how they look and even introduce your own tweaks into them.

And now that the methods have been adequately defined, we’re going to add them to the definition of the “Url” class. This will be done in the course of the following section, so keep reading. 

The finished version of the “Url” class

As I noted above, here’s the finished version (at least for the moment) of the sample “Url” class, after adding to it the set of getters implemented previously. Check it out:

(Url.php)

<?php

final class Url
{
    private $_scheme; 
    private $_host;
    private $_path;
    private $_queryString;
   
    // constructor
    public function __construct($url)
    {
        if (!filter_var($url, FILTER_VALIDATE_URL, array(FILTER_FLAG_SCHEME_REQUIRED, FILTER_FLAG_HOST_REQUIRED))) {
            throw new UrlException(‘The specified URL is invalid.’);
        }
       
        $url = parse_url($url);
        $this->_scheme = $url['scheme'];
        $this->_host = $url['host'];
       
        if (isset($url['path'])) {
            $this->_path = $url['path'];
        }
       
        if (isset($url['query'])) {
            $this->_queryString = $url['query'];
        }
    }
   
    // get the scheme part of the URL
    public function getScheme()
    {
        return $this->_scheme;
    }
   
    // get the host part of the URL
    public function getHost()
    {
        return $this->_host;
    }
   
    // get the path part of the URL
    public function getPath()
    {
        return $this->_path;
    }
   
    // get the query string of the URL
    public function getQueryString()
    {
        return $this->_queryString;
    }
}     

Mission accomplished, at least for the moment. At this stage, I’ve built a basic class which is capable of modeling immutable value objects. While this is good, I’d like you to look more closely at this class. Admittedly, it’s nothing but an immutable structure that acts like a container for the different parts of a well-formed URL. What if I want to implement some kind of behavior, like appending additional parameters to its existing query string?

In a case like this, the “$_queryString” property should be altered in some way, thus breaking up its immutability! Well, fear not, because here’s exactly where another feature of the Object Value pattern comes into play. If you try to mutate an immutable object, the process should always return a new object of the same type.

Now, if I translate this concept to my “Url” class, any method that attempts to alter its query string field will result in the creation of a new “Url” object. Got the idea? Don’t worry if you don’t yet, as in the next installment I’m going to add such a method to the class. This way, you’ll be able to see its concrete implementation and catch its driving logic. 

Final thoughts

In this introductory part of the series, I provided you with an overview of what the Object Value pattern is and how to implement it in PHP. In the example above, you learned how to define a basic URL class that can be used for creating easily immutable value objects.

As I said before, though, the class has no behavior beyond acting like a simple data container. However, this is about to change, since in the next tutorial I’m going to add to it a method that will append extra arguments to its query string. In keeping with the schema imposed the Value Object pattern, the method will return a new “Url” object, therefore keeping the class’ immutability intact.

Don’t miss the next part!

Google+ Comments

Google+ Comments