5 Inspiring (and Useful) PHP Snippets

“X PHP Snippets” type articles abound on the Internet, so why write another one? Well, let’s face it… the PHP snippets in them are generally lame. Snippets that generating a random string or return $_SERVER["REMOTE_ADDR"] for the IP Address of a client really aren’t that interesting and are of modest usefulness. Instead, here’s five snippets that you’ll no doubt find interesting and useful, presented along with the problems that inspired them. I hope the creativity in many of them inspire you to write better and more creative code in your own day-to-day endeavors.

1. Generating CSV

All too often we see code that attempts to convert a multi-dimensional array of data to CSV that looks like this:

<?php
$csv = "";
foreach ($data as $row) {
    $csv .= join(",", $row) . "n";
}
echo $csv;

The problem is that the individual elements are not properly escaped, and a single value with either a quotation mark or comma can throw off a parser that later tries to consume the CSV data. It’s much better to use the built-in fputcsv() function; it should execute faster because it’s implementation is in C code, and it handles the necessary quoting/escaping for you.

The following code wraps logic to construct CSV output from an array of data. It has optional parameters to allow for header columns and whether to flush the CSV directly to the browser or return the output as a string. The elegance here is the usage of streams with fputcsv() as the function requires an open file handle to operate.

<?php  
function toCSV(array $data, array $colHeaders = array(), $asString = false) {  
	$stream = ($asString)
	    ? fopen("php://temp/maxmemory", "w+")
	    : fopen("php://output", "w");  

	if (!empty($colHeaders)) {
		fputcsv($stream, $colHeaders);  
	}

	foreach ($data as $record) {
		fputcsv($stream, $record);
	}

	if ($asString) {
		rewind($stream);  
		$returnVal = stream_get_contents($stream);  
		fclose($stream);  
		return $returnVal;  
	}
	else {
		fclose($stream);  
	}  
}

With the toCSV() function in your arsenal, generating CSV becomes easy and fool proof.

2. Autoloading Classes

Autoloading class files is common place, but maybe you don’t like some of the bloated, heavier autoloader offerings provided by various PHP frameworks, or maybe you just like to roll your own solutions. Luckily, it’s possible to roll your own minimal loader and still be compliant with the PSR-0 standard adopted by the PHP Standards Working Group, which I first demonstrated on my own blog.

The standard doesn’t describe what support functionality must be provided by a PSR-0 compliant autoloader (registration methods, configuration options, etc.). If it can automatically find a class definition in the <Vendor Name>(<Namespace>) pattern, then it’s PSR-0 compliant. Furthermore, it doesn’t specify the parent directory for <Vendor Name>. The extra “fluff” of most autoloader implementations is convenient if you need to specify the location via code, but is unnecessary if you simply use a directory already within PHP’s include path.

<?php
spl_autoload_register(function ($classname) {
    $classname = ltrim($classname, "\");
    preg_match('/^(.+)?([^\\]+)$/U', $classname, $match);
    $classname = str_replace("\", "/", $match[1])
        . str_replace(["\", "_"], "/", $match[2])
        . ".php";
    include_once $classname;
});

The magic here is in the regex which splits the incoming name into its constituent parts; the class name will always be in $match[2], and $match[1] the namespace name which may or may not be an empty string. It’s necessary to identify the parts because the underscore has no special meaning in the namespace portion making a blind replace on underscores and backslashes incorrect.

3. Parsing Fixed-Width Data with unpack()

In today’s modern world filled with XML and JSON, you might think fixed-width formats are extinct… but you’d be wrong. There is still a large amount of fixed-width data, such as some log entries, MARC 21 (bibliographic information), NACHA (financial information), etc. And between you and me, I still have a soft spot for fixed-width data.

Fixed-width data is relatively easy to work with in languages like C because the data, one loaded into memory, aligns perfectly with the accessing data structure. But for some, working with fixed-data in a dynamic language like PHP can be a struggle; the loose typing of the language makes such memory access impossible. And as a result, we often see code that looks like this:

<?php
// Parse a NACHA header record
$row = fread($fp, 94);
$header = array();
$header["type"] = substr($row, 0, 1);
$header["priority"] = substr($row, 1, 2);
$header["immDest"] = substr($row, 3, 10);
$header["immOrigin"] = substr($row, 13, 10);
$header["date"] = substr($row, 23, 6);
$header["time"] = substr($row, 29, 4);
$header["sequence"] = substr($row, 33, 1);
$header["size"] = substr($row, 34, 3);
$header["blockFactor"] = substr($row, 37, 2);
$header["format"] = substr($row, 39, 1);
$header["destName"] = substr($row, 40, 23);
$header["originName"] = substr($row, 63, 23);
$header["reference"] = substr($row, 86, 8);
print_r($header);

You’re probably cringing. It’s okay, I wouldn’t want such code in my application either! It’s verbose and the indexing is error-prone. Luckily, there is a better alternative: unpack().

The documentation for unpack() in the PHP Manual says: “Unpacks a binary string into an array according to the given format” and show usage examples escaped using binary data. What may not be immediately apparent is that the function can be used to parse fixed-width strings thanks to the format specifier ‘A’ which represents a character (after all, is not a string just a series of bits and bytes?).

Using unpack(), the above example can be re-written more elegantly like so:

<?php
// Parse a NACHA header record
$row = fread($fp, 94);
$header = unpack("A1type/A2priority/A10immDest/A10immOrigin/"
    . "A6date/A4time/A1sequence/A3size/A2blockFactor/A1format/"
    . "A23destName/A23originName/A8reference", $row);
print_r($header);

The format string in this case is simply a series of A’s specifying character data, the character-count for the specific field, and the key name the retrieved data will be assigned in the final array, separated by slashes. A6date for example parses out the 6 characters and makes them available as $header["date"].

4. Templating HTML

There’s never been much of a consensus about templating in the PHP community. We all agree that keeping HTML and PHP separate is desirable, but clash on the suitability of using template libraries such as Smarty or Twig. Some point out that PHP itself is a template engine, and argue against a library’s speed, syntax, etc. Others claim to have benefited greatly from using the DSL that templating systems provide. One compromise is to template your HTML to keep things clean using a very minimal class written in PHP.

<?php
class Template
{
    protected $dir;
    protected $vars;

    public function __construct($dir = "") {
        $this->dir = (substr($dir, -1) == "/") ? $dir : $dir . "/";
        $this->vars = array();
    }

    public function __set($var, $value) {
        $this->vars[$var] = $value;
    }

    public function __get($var) {
        return $this->vars[$var];
    }

    public function __isset($var) {
        return isset($this->vars[$var]);
    }

    public function set() {
        $args = func_get_args();
        if (func_num_args() == 2) {
            $this->__set($args[0], $args[1]);
        }
        else {
            foreach ($args[0] as $var => $value) {
                $this->__set($var, $value);
            }
        }
    }

    public function out($template, $asString = false) {
        ob_start();
        require $this->dir . $template . ".php";
        $content = ob_get_clean();

        if ($asString) {
            return $content;
        }
        else {
            echo $content;
        }
    }
}

It’s not a full-fledged template engine; rather a succinct helper class that acts as a “bucket” to collects key/value data pairs which you can access in included files designated as templates. First you create an instance of the Template class in your view, optionally passing a directory name used to look up the subsequent template files (allowing you to group related files). Then, provide the values that should populate the templates to either the set() method or as a bare property. Once all the values are specified, you call the out() method to render the template.

<?php
$t = new Template();
// setting a value as if it were a property
$t->greeting = "Hello World!";
// setting a value with set()
$t->set("number", 42);
// setting multiple values with set()
$t->set(array(
    "foo" => "zip",
    "bar" => "zap"
));
// render template
$t->out("mytemplate");

The mytemplate.php file for the example might look something like this:

<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="utf-8">
...
 </head>
 <body>
  <div role="main">
   <h1><?=$this->greeting;?></h1>
...
  </div>
 </body>
</html>

Within the template files you have access to the full range of PHP functionality to format values, filter values, etc. as you see fit.

A second, optional parameter to out() can specify to return the template contents as a string instead of flushing it directly to the browser, which you can take advantage of to replace placeholders in one template with the result of a previously filled template.

5. Using file_get_contents as a cURL Alternative

cURL is robust library for communicating over various protocols. It certainly is very full-featured, and there are times when nothing else will do. If you explicitly need functionality as exposed by cURL to accomplish your task, then use cURL! But the majority of day-to-day cURL usage in PHP revolves around issuing HTTP GET and POST requests, something that can be done easily with built-in PHP functions.

The problem with relying on cURL for issuing HTTP requests is two-fold: 1) there of often many options that need to be set, even for the simplest of transactions, and 2) it is an extension that may or may not be available depending on your hosting and installation situation; it is a common extension, but one that is not enabled by default.

file_get_contents() and stream_context_create() are two native PHP functions that have been available since the 4.3 days. Together, they can be used to perform many of the same types of requests commonly done via cURL.

For basic GET requests, file_get_contents() can be used by itself:

<?php
$html = file_get_contents("http://example.com/product/42");

For requests where you need to specify HTTP headers, be it GET or any of the other HTTP methods, you can create a context by passing a specially-keyed array to stream_context_create() and then pass the context to file_get_contents().

<?php
$context = stream_context_create(array(
    "http" => array(
        "method" => "POST",
        "header" => "Content-Type: multipart/form-data; boundary=--foorn",
        "content" => "--foorn"
            . "Content-Disposition: form-data; name="myFile"; filename="image.jpg"rn"
            . "Content-Type: image/jpegrnrn"
            . file_get_contents("image.jpg") . "rn"
            . "--foo--"
    )
));

$html = file_get_contents("http://example.com/upload.php", false, $context);

The example above shows uploading a file via POST, with the context array specifying the necessary information for the transaction using the keys “method”, “header”, and “content”.

When using file_get_contents() for complex requests such as file uploads, it can be helpful to first make a mock web form and run it through Firefox with firebug enabled or something similar and then inspect what was included in the request. From there you can deduce the important header elements to include.

Summary

Hopefully you’ve found the snippets presented in this article interesting. They showcase creative problem solving and using PHP’s built-in functionality to new effect. I hope you find them useful and inspiring. And if you have inspiring snippets of your own, feel free to share in the comments below.

Image via Fotolia

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Shameer C

    Hi Tim,
    Thanks for the excellent article. All the snippets are really interesting, especially PSR-0 compatible autoloader and streams. I have written view classes for some of my projects where I used extract() to bring variables to local scope, so that we can use the same variable name inside template file. But I like your method as it is more elegant and easy to understand.

  • http://zaemis.blogspot.com Timothy Boronczyk

    When the template is included, its code inherits the scope of the parent, $this-> resolves to the Template class instance, and you would use something like $this->var in your template. You could use extract() and use $var in your templates if you’d like, but personally though I prefer to leave them with $this-> since it provides a some protection against clashing variable names. I can use $var within the template for “local” counter variables and other logic, and $this-> for imported content variables, without worrying about any conflicts.

  • Tony

    Please make your readers aware that file_get_contents() will only work on environments which have the allow_url_fopen runtime configuration setting to ON. (See http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)

  • http://faison.wpengine.com Faison

    Hi Tim,

    Crazy coincidence (or synchronicity), I just posted my first guide a couple days ago. It’s on creating a WordPress plugin for exporting MySQL data as a CSV file. It’s nice to see people writing about this, since lots of other guides and snippets opt to do it without using fputcsv(). Great article though, I’m definitely saving it for future reference.

  • http:/inpromtu.de KMB

    I tripped over “php://temp/maxmemory” and “php://output”. I googled and understood, but nevertheless, I tripped over it.

    • http://zaemis.blogspot.com Timothy Boronczyk

      Perhaps in hindsight I should have explained them, sorry. php://output opens a connection to PHP’s output buffer. php://temp/maxmemory is a connection to chunk of memory, and if too much is written to the memory it will fallback to a physical temp file. They’re documented in the PHP Manual. But on the bright side, you were able to learn something that you didn’t know before!

  • http://codeangry.com/ CodeAngry

    When I saw the first CSV snippet… (facepalm). When I saw the second one, I sighed with relief :)

    I don’t usually comment like this but good snippets and clean code. I like that!

    Cheers.

  • Alex Gervasio

    Nice compilation of snippets indeed. Not only they do show how to accomplish what they promise at face value, but they do it through solid code. Well done Tim :)

  • Dave Hulbert

    I’d wrap the include_once in the spl_autoload_register in an is_readable() check, so it can be used with other autoloaders.

  • Webtrendzs

    Nice info there Tim. However,with templating html i wouldn’t want to do the set() function the way you did. You already have the var property which is suppose to contain the template variables and the __set() magic function to set the variables. This would do: function set($arrData){ $this->vars=$arrData;}. You don’t need to call the setter function again inside the set(), that will be a work overload to the class. Remember the __set() function the way it works: if i have $arrData=array(‘right’=>’put me right here’) and i call $this->right in my template, the class attempts to read the property but does not find so it calls the __set() method to set it whic reads from the $this->vars and gets the right value that you just paased in the array $arrData

    • http://zaemis.blogspot.com Timothy Boronczyk

      Your approach would overwrrite the entire vars list that way, but it could be a perfectly acceptable approach depending on your needs. My set() example looks at the nature of the parameters passed to it to provide a jQuery-esque streamlined API and iterates through arrays pushing them onto the internal vars list.

  • http://zenshadow.com/ Trevor Geene

    I really like the class auto load script that you put in the article. It is clean and simple, something I love in code.

  • http://example.com Johan

    4. Templating HTML

    I use the output buffer to template It’s very simple indeed.
    The host file looks like this:

    ?php
    $Customer_First_Name=’test’;
    ob_start();include(‘mail.php’);$msg=ob_end_flush();
    echo $msg;
    ?

    in the mail.php i can use the $Customer_First_Name like a normal php variable… the rest can be simple html. I dont see the point of making it more difficult than it has to be. $msg contains your template, use it if you like to send it in an email or show it on the site.

  • Siegi

    I don’t understand how to call and go through the array in the template file, with the set() method. Example(s) for using set() would be a great help.