Home arrow PHP arrow PHP Closures as View Helpers: Lazy-Loading File Data

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.

TABLE OF CONTENTS:
  1. PHP Closures as View Helpers: Lazy-Loading File Data
  2. A Final Example
By: Alejandro Gervasio
Rating: starstarstarstarstar / 0
January 30, 2012

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

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. 



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: