Home arrow PHP arrow Page 2 - Lazy Loading with External PHP Iterators

Building File Helpers in PHP - PHP

Let’s face it: building custom external iterators is one of those things that we, as PHP developers, have to tackle sooner or later. Whether it comes to iterating over database result sets or traversing plain array elements, external iterators are powerful, reusable structures that permit you to develop more efficient object-oriented applications. This is the third part in our series on external iterators in PHP.

TABLE OF CONTENTS:
  1. Lazy Loading with External PHP Iterators
  2. Building File Helpers in PHP
By: Alejandro Gervasio
Rating: starstarstarstarstar / 3
April 06, 2011

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Using the Previous Array Collection: Building a Basic File Helper

As we saw in the previous section, the file helper that I plan to create will make use of the earlier array collection to iterate over the contents of a specified text file. Since I want the collection to be invoked only when the helper is consumed within a “foreach” loop, the latter will be an implementer of the native “IteratorAggregate” SPL interface.

If this speech sounds somewhat confusing to you, don’t worry too much - take a look at the following code snippet, which includes the source code of the helper:

(Utility/FileProcessor.php)

<?php

namespace Utility;

class FileProcessor implements \IteratorAggregate
{
    protected $_file = 'Utility\data.txt';
    protected $_iterator;
   
    /**
     * Constructor
     */
    public function __construct($file = '')
    {
        if ($file !== '') {
            $this->setFile($file);
        }
    }
   
    /**
     * Set the target file
     */
    public function setFile($file)
    {
        if (!file_exists($file)) {
            throw new \InvalidArgumentException('The target file ' . $file . ' does not exist.');
        }
        $this->_file = $file;
    }
   
    /**
     * Get the target file
     */
    public function getFile()
    {
        return $this->_file;
    }
   
    /**
     * Write the specified data to the target file
     */
    public function write($data)
    {
        if (!$fp = fopen($this->_file, 'a+')) {
            throw new \UnexpectedValueException('Error opening the target file.');
        }
        if (!fwrite($fp, $data . "\n")) {
            throw new \UnexpectedValueException('Error writing data to the target file.');
        }
        fclose($fp);
        return $this;
    }
   
    /**
     * Get the external iterator
     */
    public function getIterator()
    {
        if ($this->_iterator === null) {
            if (($data = file_get_contents($this->_file)) !== false) {
                $data = explode("\n", $data);
                $this->_iterator = new ArrayCollection($data);
            }
            else {
               throw new \UnexpectedValueException('Error reading data from the target file.');
            }
        }
        return $this->_iterator;
    } 
}

Despite its fancy name, the area of concern for the “FileProcessor” class is quite limited, as it’s only responsible for reading and writing text data to a specified target file. Even when the implementation of the class’ “write()” method is dead simple, you should pay attention to its counterpart “getIterator()”, which is worth analyzing in more depth.

Effectively, the class uses this method to read data from the target file and inject it into the custom array collection, but only when the method is called explicitly or when invoked transparently within a “foreach” construct. This shows - in a nutshell - how an external iterator (in this case a custom array collection) can be used for lazy-loading data, no matter if it comes from a flat database, an RDBMS, or a web service. Pretty good, huh?

And now that you grasp the logic that stands behind the previous file helper, it’s time to give it a try and see if it’s as functional as it seems at first sight.

Putting the Pieces Together: Seeing the File Helper in Action

If you want to see the previous file helper in action, below is a short script that uses it firstly for saving some trivial text to the default “data.txt” file, and then for getting this data back. As just stated, this last operation is performed only when an instance of the helper is embedded into a “foreach” loop.

Here’s how this test script looks (remember that the autoloader is the same used here [http://www.devshed.com/c/a/PHP/Building-a-service-Locator-in-PHP/]):

<?php

use Utility\FileProcessor as FileProcessor;

// include the autoloader
require_once 'Autoloader.php';
Autoloader::getInstance();

// create an instance of the FileProcessor class
$fileProc = new FileProcessor;

// write some data to the target file
$fileProc->write('This is the first line of the file')
         ->write('This is the second line of the file')
         ->write('This is the third line of the file');

// lazy-load file data
foreach ($fileProc as $key => $value) {
    echo $value . '<br />';
}

/* displays the following

This is the first line of the file
This is the second line of the file
This is the third line of the file

*/

There you have it. In a few easy steps, I managed to create a file helper, which is not only capable of lazy-loading data through the implementation of the IteratorAggregate SPL interface, but performs this task via a custom external iterator.

In this case the helper isn’t really important (in fact, I’m sure that you can build a more functional one on your own). What’s really worth noting here is how it uses an array collection for fetching data on request, which is then traversed using an array collection. This approach can be easily translated to other storage mechanisms, such as a database or a CDN, and proves particularly useful when it comes to manipulating common relationships of data (one-to-one/one-to-many) in a more efficient way.

So, fire up your spark of creativity and start using the functionality of external iterators for lazy-loading data in your own applications. The results that you’ll get will put a big smile on your face, believe me.       

Final thoughts

In this third episode of the series, I demonstrated with a concrete example how the use of a custom external iterator can be of great help when it comes to lazy-loading data from a specific storage mechanism, being in this case the file system. In the above example, the implementation of a basic file helper was all that I needed to made my point, but this approach can be easily extended to other contexts as well (i.e. when working with a RDBMS).

What’s more, if you’re a sharp observer, you’ll probably have realized that the previous helper can be tweaked to work seamlessly with the native ArrayIterator SPL class instead of using a custom array collection. Well, that’s exactly what I plan to do in the final tutorial of the series, so don’t miss it!



 
 
>>> 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: