PHP Closures as View Helpers: Lazy-Loading File Data

In this second part of a two-part tutorial, you’ll learn how to use closures in the development of an extendable template system. This system can be customized at will without struggling too much, thanks to the number of interfaces that it implements.

As an important part of PHP 5.3’s new features, closures have quickly made a mark on the language’s field. This is due to their versatile nature, which allows programmers to utilize them in a wide variety of use cases and situations. They not only yield great results when processing array elements in all sorts of clever ways; it’s fairly easy to get excellent results with them in the object-oriented programming arena as well.

The best way to show you how using anonymous functions can help you to develop more efficient OO applications is with some functional, hands-on examples. With this idea in mind, in the installment that preceded this one, I implemented an extendable template system. This system could spawn view objects and render the template files associated with these objects.

While this process per se wasn’t especially notable, as it was the behavior expected of any decent template mechanism, in this case there was a subtle detail worth observing. The class responsible for creating the aforementioned view objects could execute any closure embedded in the corresponding template files as if it were a regular field.

This approach brought a lot of functionality to the table. It made it possible to encapsulate relatively simple logic behind a closure without the need to explicitly define a view helper, be it static or dynamic. I demonstrated this ability with a concrete example in which the IP addresses of users accessing a web page were determined via an anonymous function, which was first assigned to the property of a view object for further rendering.

It’s valid to point out, however, that this approach really shines when lazy-loading data from a remote resource (for instance, a database, a flat file, or even a web service). Therefore, in this final article I’ll show you how to load, on request, the contents of a basic text file by using the template system developed in the previous tutorial. As I explained before, this will be accomplished via a simplistic, primitive closure.

Ready to learn how to take the abilities of anonymous functions to the next level? Then keep reading.          

Utilizing Closures in a Complex Scenario: Loading File Data on Request

Since my plan here consists of demonstrating how to lazy-load the contents of a file by using a closure, and then drop that data straight into a template file, the first logical step is to create a couple of additional classes that make this a smooth process. The first of these classes will be tasked with serializing/unserializing the contents in question, while the second one will read data from, and write data to, a specified file.

So, here’s the definition of the former, which I’ve named “Serializer:”

(MyApplication/Serializer.php)

<?php

namespace MyApplication;

class Serializer implements Serializable
{
   
    /**
     * Serialize the given value.
     */
    public function serialize($value)
    {
        if (is_resource($value)) {
            throw new InvalidArgumentException(‘A PHP resource cannot be serialized.’);
        }
        try {
            return serialize($value);
        }
        catch (Exception $e) {
            throw new RunTimeException($e->getMessage());
        }
    }
   
    /**
     * Unserialize the given value.
     */
    public function unserialize($value)
    {
        if (!is_string($value)) {
            throw new InvalidArgumentException(‘The value to be unserialized must be a string.’);
        }
        if (($unserialized = @unserialize($value)) === false) {
            throw new RunTimeException(‘Unable to unserialize the value ‘ . $value);
        }
        return $unserialized;
    }   
}

As you can see, aside from implementing the native “Serializable” PHP interface, the “Serializer” class does exactly what its name suggests. It defines a couple of methods for serializing/unserializing a supplied value. In addition, the methods throw some exceptions if something goes wrong. 

With this utility class already set, it’s time to create the next one. As I said before, this extra class must be capable of reading from and writing data to a specified file. The one below performs these tasks:

(MyApplication/FileHandler.php)

<?php

namespace MyApplication;

class FileHandler implements DataHandlerInterface
{
    const DEFAULT_FILE_PATH = ‘data.txt’;
    protected $_serializer;
    protected $_filePath;
   
    /**
     * Constructor
     */
    public function __construct(Serializable $serializer, $filePath = self::DEFAULT_FILE_PATH)
    {
        $this->_serializer = $serializer;
        $this->setFilePath($filePath);
    }  
   
    /**
     * Set the file path.
     */
    public function setFilePath($filePath)
    {
        if (!$fp = @fopen($filePath, ‘r+’)) {
            throw new InvalidArgumentException(‘The supplied file path ‘ . $filePath . ‘ is invalid.’);
        }
        fclose($fp);
        $this->_filePath = $filePath;
        return $this;
    }
   
    /**
     * Get the file path.
     */
    public function getFilePath()
    {
        return $this->filePath;
    }
   
    /**
     * Write the given value to the file path.
     */
    public function write($value)
    {
        if (!$ret = file_put_contents($this->_filePath, $this->_serializer->serialize($value))) {
            throw new RunTimeException(‘Unable to save the supplied value ‘ . $value . ‘ to the target file.’);
        }
        return $ret;
    }
   
    /**
     * Read the written data back from the file path.
     */
    public function read()
    {
        if (!$value = $this->_serializer->unserialize(file_get_contents($this->_filePath))) {
            throw new RunTimeException(‘Unable to read the requested data from the target file.’);
        }
        return $value;
    }      
}

What I just said about the previous “Serializer” class applies to the above “FileHandler” as well. In  short, all that it does is implement a set of simple methods, which are nothing but wrappers for the “file_get_contents()” and “file_put_contents()” PHP functions. Also, to follow the commandments of the Open/Closed principle and the ones dictated by Design by Contract, I made this class an implementer of the “DataHandlerInterface” interface defined in the previous tutorial (remember that one, right?).

Quite possibly, the most interesting aspect of this class is that it takes a serializable object in the constructor to read/write any type of data from the specified target file.

With these additional classes up and running already, it’s time to move on and demonstrate how they can be packaged inside the boundaries of a closure to lazy-load data from a given file.

This process will be discussed in detail the next section, so click on the link below and keep reading. 

{mospagebreak title=A Final Example}

To demonstrate how easy it is to pull in file data on request by using the pair of classes defined in the previous section, it’s necessary to create the pertinent file and populate it with some trivial content. To make things shorter and easier to follow, I’ll be working with a file called “data.txt,” which is the default one used by the earlier “FileHandler” class.

The sample file looks like this:

(data.txt)

s:83:"This content has been lazy-loaded from a remote resource via an anonymous function.";

As you can see, the target file now contains a simplistic serialized string (but it could be anything else, like an array, an object and so forth), which definitely doesn’t bear any further explanation. That was the boring part, so it’s time to show how to use the power of closures to lazy-load this string and drop it into the same template file used in the previous tutorial.

In case you don’t recall how this template looked, here it is:

(default_template.php)

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Using closures in PHP</title>
</head>
<body>
    <header>
        <h1>Header section</h1>
        <h2>Welcome! You’re accessing this page from : <?php echo $this->clientIp;?></h2>
        <p><?php echo $this->header;?></p>
    </header>
    <section>
        <h2>Main section</h2>
        <p><?php echo $this->content;?></p>
    </section>
    <footer>
        <h2>Footer section</h2>
        <p><?php echo $this->footer;?></p>
    </footer>
</body>
</html>

Here is where things become really interesting, trust me. See the view field “$this->content” interspersed in the template’s main section? Well, in a typical use case, it should FIRST be populated with a dynamically-generated value (i.e. some database records) and then echoed to the screen. Thanks to the functionality of closures, though, it’s possible to delay this process until the template is actually rendered. If this sounds rather messy to you, make sure to peek at the following code snippet. It uses the previous “Serializer” and “FileHandler” classes to accomplish this. 

<?php

use MyApplicationView,
    MyApplicationSerializer,
    MyApplicationFileHandler;

// include the autoloader and create an instance of it
require_once __DIR__ . ‘/Autoloader.php’;
$autoloader = new Autoloader;

// create a view object
$view = new View;
$view->header = ‘This is the content of the header section’;
$view->footer = ‘This is the content of the footer section’;
$view->clientIp = $_SERVER[‘REMOTE_ADDR’];

// lazy load contents from a remote file and assign them to the ‘content’ field
$view->content = function() {
    $fileHandler = new FileHandler(new Serializer);
    return $fileHandler->read();
};

// render the view template
echo $view->render();

There you have it. As shown above, once a view object is created, the aforementioned classes are wrapped inside a closure, which is then assigned to the corresponding  “content” property. Finally, the view is dumped to the browser. This process generates the following output:

There you have it. Not only was the whole template rendered as expected, but the string placed in the “data.txt” file was retrieved on request and printed on screen.

Even though somewhat contrived, this example shows how to take advantage of anonymous functions for lazy-loading data from a persistence layer (in this case, a simple text file). So, go ahead and start discovering new and creative ways to spice up your OO applications with the functionality of closures. It’ll be a fun experience.  

Closing Remarks

We’ve come to the end of this tutorial. But hopefully the journey has been instructive, as you learned how to use closures in the development of an extendable template system, which can be customized at will thanks to the number of interfaces that it implements.

As you just saw, a proper mixture of anonymous functions, along with a few basic classes, is all you need to set up a flexible structure — a structure which allows you to parse template variables and execute different processes on request with remarkable ease.

To make a long story short: if you haven’t used closures before in your OO applications, or simply are looking new ways to get the most out of them, the code samples in this article should point you in the right direction.

See you in the next PHP development tutorial!          

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye