Go back index.php
<?php
set_include_path(
APPLICATION_PATH . '/../library' . PATH_SEPARATOR
);
require_once "library/Zend/Loader/Autoloader.php";
$autoloader = Zend_Loader_Autoloader::getInstance();
$started = microtime();
?><html>
<head>
<title>Idiomatic for the people -- a Zend_Array proposal</title>
<link rel="stylesheet" type="text/css" href="files/code.css" />
<script type="text/javascript" src="js/jquery-1.3.1.js"></script>
<script type="text/javascript" src="js/flot/jquery.flot.js"></script>
<script type="text/javascript" src="js/menu.js"></script>
</head>
<body>
<h1><i>Idiomatic for the people</i> — a Zend_Array proposal</h1>
<p class="header">©2010 <a href="http://chapman.id.au">Nigel Chapman</a>:
License: <a href="http://www.opensource.org/licenses/bsd-license.php">BSD
License</a>; this page last modified 31 January 2010.</p>
<h2>Abstract</h2>
<p>Zend_Array is a 'fluent' wrapper for PHP's array functions, giving them a
chainable interface that works well with closures, i.e. anonymous or lambda
functions; functions stored in variables or passed as arguments to other
functions. It has been influenced considerably by Ruby and JQuery, and makes
PHP more idiomatic. It is designed for ease of use, in line with the UNIX
philosophy of simple and reliable tools, which become poweful in combination.
It is very new software, and you should expand the test suite to your
satisfaction before using it for anything important.</p>
<h2>Introduction</h2>
<p>Zend_Array implements chainable array operations that work well with
closures.</p>
<div class="input"><?php highlight_file("examples/hello_world.php"); ?></div>
<div class="output"><?php require_once "examples/hello_world.php"; ?></div>
<p>Though it does a lot more, it's good at simple data pipelines:</p>
<div class="input"><?php highlight_file("examples/demo.php"); ?></div>
<div class="output"><?php require_once "examples/demo.php"; ?></div>
<?php
/*
*
*
<div class="input"><?php
require_once "examples/l33t.php";
highlight_file("examples/characters.php");
?></div>
<div class="output"><?php require_once "examples/characters.php"; ?></div>
*
*
*/
?>
<p>Here's how it does a <a
href="http://en.wikipedia.org/wiki/Schwartzian_transform">Schwartzian
Transform</a> in PHP, using the classic example of sorting lines by their last
words.</p>
<div class="input"><?php highlight_file("examples/schwartzian.php"); ?></div>
<div class="output"><?php require_once "examples/schwartzian.php"; ?></div>
<h2>Sample Data</h2>
<p>The following sample data will be used in the examples below.</p>
<div class="input"><?php highlight_file("examples/data.php"); ?></div>
<?php require_once "examples/data.php"; ?>
<h2>"Get Statements"</h2>
<p>Much of Zend_Array's functionality depends on a single function called
'get'. It figures out what you're looking for in the elements of an array:</p>
<ul>
<li>Get the specified key(s) from sub-arrays,</li>
<li>Get the specified attribute(s) of the object elements,</li>
<li>Get the results of calling a certain method(s) on the object elements,</li>
<li>Get the results of calling a user-defined function(s) with each element as it's argument,</li>
<li>Or some combination of these.</li>
</ul>
<p>When I call <i>sort($x)</i>, <i>$x</i> can be any argument recognized by <i>get()</i>.</p>
<div class="input"><?php highlight_file("examples/get_statements.php"); ?></div>
<div class="output"><?php require_once "examples/get_statements.php"; ?></div>
<p>PHP's own library of functions can be used as well (@todo: take arguments):</p>
<div class="input"><?php highlight_file("examples/php_functions.php"); ?></div>
<div class="output"><?php require_once "examples/php_functions.php"; ?></div>
<h2>EXAMPLE 1. Numbers and strings</h2>
<div class="input"><?php highlight_file("examples/basic_numbers.php"); ?></div>
<div class="output"><?php require_once "examples/basic_numbers.php"; ?></div>
<div class="input"><?php highlight_file("examples/basic_strings1.php"); ?></div>
<div class="output"><?php require_once "examples/basic_strings1.php"; ?></div>
<div class="input"><?php highlight_file("examples/basic_strings2.php"); ?></div>
<div class="output"><?php require_once "examples/basic_strings2.php"; ?></div>
<div class="input"><?php highlight_file("examples/basic_strings3.php"); ?></div>
<div class="output"><?php require_once "examples/basic_strings3.php"; ?></div>
<h2>EXAMPLE 2. Manipulating arrays</h2>
<p>Arrays can be chopped up into smaller arrays in several ways:</p>
<div class="input"><?php highlight_file("examples/slicing.php"); ?></div>
<div class="output"><?php require_once "examples/slicing.php"; ?></div>
<h2>EXAMPLE 3. Sorting and collating</h2>
<h4>Sorting by keys or attributes</h4>
<div class="input"><?php highlight_file("examples/sorting-keys.php"); ?></div>
<div class="output"><?php require_once "examples/sorting-keys.php"; ?></div>
<h4>Sorting by values</h4>
<div class="input"><?php highlight_file("examples/sorting.php"); ?></div>
<div class="output"><?php require_once "examples/sorting.php"; ?></div>
<h4>Collation</h4>
<p>Collation means grouping arrays for iteration; you can collate by
several values in one operation.</p>
<div class="input"><?php highlight_file("examples/sorting-tables.php"); ?></div>
<div class="output"><?php require_once "examples/sorting-tables.php"; ?></div>
<div class="input"><?php highlight_file("examples/sorting-tables-2.php"); ?></div>
<div class="output"><?php require_once "examples/sorting-tables-2.php"; ?></div>
<h2>EXAMPLE 4. Tree traversal</h2>
<p>Because all Zend_Array operations recurse by default, tree traversal has
already been observed in some of the operations above.</p>
<div class="input"><?php highlight_file("examples/tree-traversal.php"); ?></div>
<div class="output"><?php require_once "examples/tree-traversal.php"; ?></div>
<p>A more serious example would start with <i>Zend_Array::takeXML($str)</i>, or
<i>takeXMLFile($path)</i> — unwritten, but easy to wrap SimpleXML. But
would XML be part of the core functionality? Or do we need...</p>
<h2>Extensions</h2>
<p>Zend_Array should contain only a minimal set of functionality for array
topography, tree traversal, mapping and filtering constructions, basic string
and number operations, and HTML. Anything specialized can go into
extensions.</p>
<h4>Zend_Array_Flot / jquery.flot.js</h4>
<p><i>Just a simple proof-of-concept</i>.</p>
<p><a href="http://code.google.com/p/flot/">Flot</a> | <a href="http://people.iola.dk/olau/flot/examples/">Examples</a></p>
<div class="input"><?php highlight_file("examples/extensions.php"); ?></div>
<div class="output"><?php require_once "examples/extensions.php"; ?></div>
<h2>Download Files</h2>
<p>Everything on this page is generated live; the examples are the actual code.
The source code for Zend_Array can be viewed here:</p>
<?php
$link = create_function('$s', 'return "<a href=\"$s.html\">$s</a>";');
echo Zend_Array::take(array(
'index.php',
'library/Zend/Array.php',
'tests/Zend/Array.php',
))->map($link)->htmlList();
?>
<p>To get everything necessary to render this page (incl. a copy of Zend Loader,
it's only dependency) and a copy of JQuery with the Flot Graphing library,
click here:</p>
<ul>
<li><a href="Zend_Array.tgz">Download the
files</a> (.tgz, <?= number_format(filesize('Zend_Array.tgz') / 1024) ?>K).</li>
</ul>
<h2>Efficiency</h2>
<p>This is not presently an exercise in efficiency but rather idiom and
convenience. Having said that, there's no reason the core functions can't be
optimized if necessary.</p>
<?php
$t1 = split(' ' ,$started);
$t2 = split(' ' ,microtime());
$ms = (int)((($t2[0]-$t1[0])+($t2[1]-$t1[1]))*1000);
?>
<p class="footer">Time to render page: <?= $ms ?> ms.
<?php if ($ms > 50): ?>
— If more than 50ms, reload; the server was asleep.
<?php endif; ?>
</p>
</body>
</html>
Go back index.php