Last Updated:

Using Patterns in PHP

Using Patterns in PHP

Popular among C++ and Java fans, design patterns are very rarely discussed by PHP programmers. However, they are an important part of computer science. What's more, they apply to any language, even PHP.

The first popular book on design patterns was the book "Techniques of Object-Oriented Design. Patterns of Design", written by authors E. Gamma, R. Helm, R. Johnson, J. S. Smith, J. Vlissides. The authors were dubbed the "Gang of Four", which is why the templates described in the book became known as GoF.

Pattern definition

Intuitively, we learn programming patterns in every line of code. Using an array, you already imagine the optimal idiom for passing through it. Ever since the expression foreach appeared in PHP, it has become my favorite.

Another example. From a broader perspective, we encounter another familiar problem: where to put the functionality in the PHP script. Most projects require the separation of functionality into several modules. For a simple information site, a simple scheme using footers and headers included in the page is well suited.

In both examples, there is a problem posed and a memorized solution. The condition for determining the pattern is the presence of a known solution. Moreover, after repeatedly using the solution, you can evaluate the side effect, bad or good, of this solution.

The formal definition of a design pattern consists of four parts:

  • Name
  • Description of the problem
  • Decision
  • Set of consequences

The name gives us a convenient way to refer to the pattern. The description of the problem gives a set of conditions in which the pattern can be applied. The solution describes an overall strategy to achieve the best solution to the problem. In conclusion, the pattern describes the consequences that arise when the pattern is applied.

Pattern-based solutions are not very inventive. They do not require the use of mysterious chips. Patterns provide reliable, time-tested solutions. They are usually optimized for reuse rather than efficiency. Performance-optimized solutions have advantages in some situations and are usually not suitable for the overall case. For example, if you want to get the sum of three numbers, you'll do it with one line of code. However, the general case would be, say, adding 10,000 numbers, and for this you need to use an array and a loop.

Patterns are closely related to object-oriented design. With object-oriented programming, you can create fairly common modules called objects. Design patterns provide a common solution to common problems. This allows you not to reinvent the wheel.

Strictly speaking, PHP cannot be called an object-oriented language. We have data structures that combine methods and properties, but we don't have protected variables. However, this does not affect the applicability of OOP. A few patterns will be discussed below and will show you how to bypass the lack of OOP chips in PHP.

Definition

Polymorphism means assigning a single name or designation to an activity that is shared by objects of different types, with each object implementing the action in a manner appropriate to its type.

In the book GoF, the authors point out that the programming environment influences what can be considered a pattern. For example, polymorphism is a suitable pattern for procedural programming languages, while object-oriented languages such as Java include it as an embedded property.

There are many patterns that could be given here, but a few of the most famous will be given. The rest you can explore on your own, the benefit of books on this topic is enough. I must say that the application of patterns in PHP requires some tricks.

Singleton

The singleton pattern is used in situations where a single instance of a class is needed. In the case of PHP, you can consider a selector that you use on a page several times. You can create a large global variable and cram HTML into it, but you won't be able to set, say, a default value. That is, you will have to write new code every time, which is not a very good solution in terms of support and development of the resource.

Instead of using a global variable, the Singleton pattern is implemented using a class with a static method that returns an object. You call the static method directly, without first declaring an instance of the object. Until recently, PHP did not support static methods. The following implementation of the Singleton pattern uses a function with a static variable. If you are using the latest versions of PHP 4, you can use the class::method() notation.

The following is an implementation of a color selector that contains color names. The implementation consists of two parts: a class definition and a helper function, in which the Singleton pattern is applied. A helper function can be configured for many classes to convert them to Singleton. In other languages, we can create a generic super-class from which to inherit more specific ones.

<?php

    //setting the colorSelector class
    class colorSelector
    {
        /*
        **Private class members
        */

        //value array
        var$value;

        //default value
        var $default;

        //constructor
        function colorSelector($value)
        {
            //copy of array of values
            $this->value = $value;
        }


        /*
        ** Public class members
        */

        //set default value
        function setDefault($default)
        {
            $this->default = (integer)$default;
        }

        //return the HTML code of the selector
        function getHTML()
        {
            $html .= "Color: ";
            $html .= "<select>\n";

            foreach($this->value as $k=>$v)
            {
                $html .= "<option value=\"$k\"";
                if($k == $this->default)
                {
                    $html .= "selected";
                }
                $html .= ">$v</option>\n";
            }

            $html .= "</select>\n";

            return($html);
        }
    }

    // helper function that implements the "Singleton" pattern
    function getColorSelector($default)
    {
        //single copy
        static $instance;

        // if there is no instance yet, create it
        if(!isset($instance))
        {
            // array of values ​​for example demonstration
            $instance = new colorSelector(
                array('red','blue','green'));
        }

        $instance->setDefault($default);

        return($instance);
    }
?>

Comments in the code regarding the public and private members of the class are inserted to inform programmers. Note that the constructor itself is a private method. This is part of the implementation of the Singleton pattern. Only the getColorSelector method can create an instance of colorSelector. If we were using Java, this function would be a static method of the class.

The following is an example of using the Singleton pattern. In a real project, there can be several hundred lines of code between two getColorSelector calls. Calls can also be made in different modules. This explains the reason why I just didn't use the same variable $c again.

<?php

     //import class colorSelector
     include_once('colorSelector.php');

     //form start

     // call the color selector
     $c = getColorSelector(1);
     print($c->getHTML());

     //form continuation

     //call another color selector
     $c = getColorSelector(2);
     print($c->getHTML());

     //form ended
?>

The Singleton pattern has some advantages over the global variable. As long as we use a helper function, we only have one instance of the class. This avoids startup costs and optimizes memory usage.

Enclosing colorSelector functionality in a class illustrates the pattern well, but may not match your programming style. You can achieve the same results by plucking methods from a class and creating separate functions. In this case, you will need to move the properties of the value and default class to getColorSelector.