<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6272487201184082806</id><updated>2011-09-29T18:08:33.080-07:00</updated><title type='text'>PHP Tips and Tricks</title><subtitle type='html'>PHP Coding Tips and Tricks from a corner in a dark room</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://phpcodetips.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://phpcodetips.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Grom</name><uri>http://www.blogger.com/profile/07559995724297228420</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://bp3.blogger.com/_CAaqgV4Ew84/SFjrZplfXDI/AAAAAAAAAAM/WrlJvOun0h0/S220/me.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6272487201184082806.post-2927321881318876121</id><published>2011-08-25T23:11:00.000-07:00</published><updated>2011-09-29T18:08:33.103-07:00</updated><title type='text'>Prototype-based programming</title><content type='html'>&lt;pre class="php" name="code"&gt;
class UndefinedException extends Exception {
    public function __construct($msg, $file, $line) {
        $this-&gt;message = $msg;
        $this-&gt;file = $file;
        $this-&gt;line = $line;
    }
}

class Backtrace {
    /**
     * Return caller information from the backtrace
     */
    static public function caller() {
        $bt = debug_backtrace(0);
        $i = count($bt) - 1;
        return $bt[$i];
    }
}

class Prototype {
    public $prototype;

    public function __construct($parent = null) {
        $this-&gt;prototype = $parent;
    }

    public function __call($name, $args) {
        // Check closure
        $func = isset($this-&gt;$name) ? $this-&gt;$name : null;
        if (is_callable($func)) {
            return call_user_func_array($func, $args);
        }
        // Check prototype
        if ($this-&gt;prototype) {
            return call_user_func_array(array($this-&gt;prototype, $name), $args);
        }        
        $caller = Backtrace::caller();
        throw new UndefinedException('Undefined method: ' . $name, $caller['file'], $caller['line']);
    }

    public function __get($name) {
        if ($this-&gt;prototype) {
            return $this-&gt;prototype-&gt;$name;
        }
        $caller = Backtrace::caller();
        throw new UndefinedException('Undefined property: ' . $name, $caller['file'], $caller['line']);
    }

    final public function begetObject() {
        return new Prototype($this);
    }
}
&lt;/pre&gt;

Here is an example of using it:
&lt;pre class="php" name="code"&gt;
$a = new Prototype();
$a-&gt;greet = function() {
    echo "Hello World!\n";
};
$b = $a-&gt;begetObject();
$b-&gt;greet(); // Prints: Hello World!
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6272487201184082806-2927321881318876121?l=phpcodetips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phpcodetips.blogspot.com/feeds/2927321881318876121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6272487201184082806&amp;postID=2927321881318876121' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/2927321881318876121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/2927321881318876121'/><link rel='alternate' type='text/html' href='http://phpcodetips.blogspot.com/2011/08/prototype-based-programming.html' title='Prototype-based programming'/><author><name>Grom</name><uri>http://www.blogger.com/profile/07559995724297228420</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://bp3.blogger.com/_CAaqgV4Ew84/SFjrZplfXDI/AAAAAAAAAAM/WrlJvOun0h0/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6272487201184082806.post-3605022537297647454</id><published>2010-07-06T18:00:00.000-07:00</published><updated>2010-07-06T18:02:30.166-07:00</updated><title type='text'>Proxy Class</title><content type='html'>&lt;pre class="php" name="code"&gt;
/**
 * Wrapper around Zend_Db connection that performs logging
 */
class Zend_Db_LogWrapper {
    private $conn;
    private $logger;

    public function __construct($conn, $logFilename) {
        $this-&gt;conn = $conn;
        $this-&gt;logger = new Logger($logFilename);
    }

    public function insert($table, array $bind) {
        $this-&gt;logger-&gt;logDb($table, 'insert', $bind);
        return $this-&gt;conn-&gt;insert($table, $bind);
    }

    public function update($table, array $bind, $where = '') {
        $this-&gt;logger-&gt;logDb($table, 'update', $bind, $where);
        return $this-&gt;conn-&gt;update($table, $bind, $where);
    }

    public function delete($table, $where = '') {
        $this-&gt;logger-&gt;logDb($table, 'delete', '', $where);
        return $this-&gt;conn-&gt;delete($table, $where);
    }

    /**
     * Redirect all other calls to the wrapped connection
     */
    public function __call($name, $arguments) {
        return call_user_func_array(array($this-&gt;conn, $name), $arguments);
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6272487201184082806-3605022537297647454?l=phpcodetips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phpcodetips.blogspot.com/feeds/3605022537297647454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6272487201184082806&amp;postID=3605022537297647454' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/3605022537297647454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/3605022537297647454'/><link rel='alternate' type='text/html' href='http://phpcodetips.blogspot.com/2010/07/proxy-class.html' title='Proxy Class'/><author><name>Grom</name><uri>http://www.blogger.com/profile/07559995724297228420</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://bp3.blogger.com/_CAaqgV4Ew84/SFjrZplfXDI/AAAAAAAAAAM/WrlJvOun0h0/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6272487201184082806.post-4307463459866532734</id><published>2008-09-10T17:13:00.000-07:00</published><updated>2011-08-25T23:20:40.817-07:00</updated><title type='text'>Beware of References</title><content type='html'>I got tripped up by the following code:
&lt;pre class="php" name="code"&gt;
// This data actually comes from csv file
$data = array(
    array('Area1', null, null),
    array(null, 'Section1', null),
    array(null, null, 'Location1'),
    array('Area2', null, null),
    array(null, 'Section2', null),
    array(null, null, 'Location2')
);
$root = array();
foreach ($data as $row) {
    if ($row[0]) { // Is Area
        $area = array();
        $root[$row[0]] =&amp; $area;
    } elseif ($row[1]) { // Is Section
        $section = array();
        $area[$row[1]] =&amp; $section;
    } elseif ($row[2]) { // Is Location
        $section[] = $row[2];
    }
}
print_r($root); &lt;/pre&gt;

Expected result:
&lt;pre&gt;Array(
[Area1] =&gt; Array(                     
        [Section1] =&gt; Array(
                [0] =&gt; Location1
            )               
    )
[Area2] =&gt; Array(       
        [Section2] =&gt; Array(          
                [0] =&gt; Location2
            )               
    )
)&lt;/pre&gt;

Actual result:
&lt;pre&gt;Array(
[Area1] =&gt; Array(                     
        [Section2] =&gt; Array(
                [0] =&gt; Location2
            )               
    )
[Area2] =&gt; Array(       
        [Section2] =&gt; Array(          
                [0] =&gt; Location2
            )               
    )
)&lt;/pre&gt;

So what did I do wrong? To answer this lets look at a simpler example:
&lt;pre class="php" name="code"&gt;
$a = array();
$b =&amp;amp; $a;
$a[] = 'hello';
echo implode(' ', $b); // Outputs 'hello'
$a = array('world');
echo implode(' ', $b); // Outputs 'world' &lt;/pre&gt;

See I was expecting the last line to output 'hello' because I was thinking references were like C pointers. That is:
&lt;pre class="c" name="code"&gt;void* a = array();
void* b = *a;
&lt;/pre&gt;

So looking up the PHP manual it says:
&lt;blockquote&gt;They are not like C pointers; instead, they are symbol table aliases...
References can be thought of as hardlinking in Unix filesystem.
&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6272487201184082806-4307463459866532734?l=phpcodetips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phpcodetips.blogspot.com/feeds/4307463459866532734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6272487201184082806&amp;postID=4307463459866532734' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/4307463459866532734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/4307463459866532734'/><link rel='alternate' type='text/html' href='http://phpcodetips.blogspot.com/2008/09/beware-of-references.html' title='Beware of References'/><author><name>Grom</name><uri>http://www.blogger.com/profile/07559995724297228420</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://bp3.blogger.com/_CAaqgV4Ew84/SFjrZplfXDI/AAAAAAAAAAM/WrlJvOun0h0/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6272487201184082806.post-8766041198387564956</id><published>2008-09-01T23:02:00.000-07:00</published><updated>2008-09-01T23:04:40.897-07:00</updated><title type='text'>Generate random password</title><content type='html'>&lt;pre class="php" name="code"&gt;
/**
 * Generate a random character array from the list of $possible characters
 *
 * @param array  $possible Array of possible characters
 * @param int    $length   Length of string to generate
 * @return array An array of $length random characters
 */
function randomStringArray($possible, $length) {
    $stringArray = array();
    $possibleCount = count($possible);

    $i = 0;
    while ($i &lt; $length) {
        // pick a random character from the possible ones
        $char = $possible[mt_rand(0, $possibleCount - 1)];

        // we don't want this character if it's already in the password
        if (!in_array($char, $stringArray)) {
            $stringArray[] = $char;
            $i++;
        }
    }

    return $stringArray;
}

/**
 * Generate password that contains 6 letters and 2 numbers
 */
function generatePassword() {
    $letters = array_merge(range('a', 'z'), range('A', 'Z'));
    $numbers = range('0', '9');
    $chars = array_merge(
        randomStringArray($letters, 6), randomStringArray($numbers, 2));
    shuffle($chars);
    return implode('', $chars);
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6272487201184082806-8766041198387564956?l=phpcodetips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phpcodetips.blogspot.com/feeds/8766041198387564956/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6272487201184082806&amp;postID=8766041198387564956' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/8766041198387564956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/8766041198387564956'/><link rel='alternate' type='text/html' href='http://phpcodetips.blogspot.com/2008/09/generate-random-password.html' title='Generate random password'/><author><name>Grom</name><uri>http://www.blogger.com/profile/07559995724297228420</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://bp3.blogger.com/_CAaqgV4Ew84/SFjrZplfXDI/AAAAAAAAAAM/WrlJvOun0h0/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6272487201184082806.post-7931375194415786188</id><published>2008-08-26T16:04:00.000-07:00</published><updated>2008-08-26T16:40:14.191-07:00</updated><title type='text'>Beware of Relative Includes</title><content type='html'>Say you have an application with an &lt;code&gt;index.php&lt;/code&gt; that contains:&lt;pre class="php" name="code"&gt;
require_once 'include/config.php';
require_once '/path_to_lib/util/all.php';&lt;/pre&gt;
The util library also has an &lt;code&gt;include/config.php&lt;/code&gt; file. In &lt;code&gt;util/all.php&lt;/code&gt; it has:&lt;pre class="php" name="code"&gt;
require_once 'include/config.php';&lt;/pre&gt;
Which config file will &lt;code&gt;util/all.php&lt;/code&gt; include?

Relative paths are converted to absolute pathnames with something like:
&lt;pre class="php" name="code"&gt;
function relativeToAbsolute($relativePath) {
    return realpath(dirname($_SERVER['SCRIPT_FILENAME']) . '/' . $relativePath);
}
&lt;/pre&gt;

Since &lt;code&gt;index.php&lt;/code&gt; is the script that is being executed then &lt;code&gt;util/all.php&lt;/code&gt; will include the config file in the application folder instead of the one from the util library folder. The solution is instead of relative includes use:
&lt;pre class="php" name="code"&gt;
require_once dirname(__FILE__) . '/include/config.php';
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6272487201184082806-7931375194415786188?l=phpcodetips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phpcodetips.blogspot.com/feeds/7931375194415786188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6272487201184082806&amp;postID=7931375194415786188' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/7931375194415786188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/7931375194415786188'/><link rel='alternate' type='text/html' href='http://phpcodetips.blogspot.com/2008/08/beware-of-relative-includes.html' title='Beware of Relative Includes'/><author><name>Grom</name><uri>http://www.blogger.com/profile/07559995724297228420</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://bp3.blogger.com/_CAaqgV4Ew84/SFjrZplfXDI/AAAAAAAAAAM/WrlJvOun0h0/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6272487201184082806.post-7546659670076903844</id><published>2008-07-15T22:58:00.000-07:00</published><updated>2008-07-15T23:11:24.509-07:00</updated><title type='text'>Domain Model Validation</title><content type='html'>Using some magic methods can integrate validation without having to implement get and set methods everywhere.

&lt;pre class="php" name="code"&gt;
class ValidationException extends Exception {
}

abstract class DomainModel {
    private $validationErrors = array();

    final public function __get($field) {
        $getMethodName = 'get' . ucfirst($field);
        if (method_exists($this, $getMethodName)) {
            return call_user_func(array($this, $getMethodName));
        } elseif (isset($this-&gt;$field)) {
            return $this-&gt;$field;
        }
    }

    final public function __set($field, $value) {
        $setMethodName = 'set' . ucfirst($field);
        if (array_key_exists($field, $this-&gt;validationErrors)) {
            unset($this-&gt;validationErrors[$field]);
        }
        if (method_exists($this, $setMethodName)) {
            try {
                call_user_func(array($this, $setMethodName), $value);
            } catch (ValidationException $e) {
                $this-&gt;validationErrors[$field] = $e-&gt;getMessage();
            }
        } elseif (array_key_exists($field, get_object_vars($this))) {
            $this-&gt;$field = $value;
        }
    }

    final public function isValid() {
        return count($this-&gt;validationErrors) == 0;
    }

    final public function getValidationErrors() {
        return array_values($this-&gt;validationErrors);
    }

    final public function setData($data) {
        foreach ($data as $field =&gt; $value) {
            $this-&gt;__set($field, $value);
        }
    }

    final public function getData() {
        return get_object_vars($this);
    }
}

class Test extends DomainModel {
    protected $message;

    public function setMessage($msg) {
        if ($msg == null || strlen(trim($msg)) == 0) {
            throw new ValidationException("Message must not be empty");
        }
        $this-&gt;message = $msg;
    }
}

$obj = new Test();
$obj-&gt;message = "Hello!";
echo $obj-&gt;message . "\n";
$obj-&gt;message = " ";
if (!$obj-&gt;isValid()) {
    foreach ($obj-&gt;getValidationErrors() as $error) {
        echo $error . "\n";
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6272487201184082806-7546659670076903844?l=phpcodetips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phpcodetips.blogspot.com/feeds/7546659670076903844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6272487201184082806&amp;postID=7546659670076903844' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/7546659670076903844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/7546659670076903844'/><link rel='alternate' type='text/html' href='http://phpcodetips.blogspot.com/2008/07/domain-model-validation.html' title='Domain Model Validation'/><author><name>Grom</name><uri>http://www.blogger.com/profile/07559995724297228420</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://bp3.blogger.com/_CAaqgV4Ew84/SFjrZplfXDI/AAAAAAAAAAM/WrlJvOun0h0/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6272487201184082806.post-4116351990504932898</id><published>2008-06-18T06:32:00.000-07:00</published><updated>2008-06-18T08:00:45.082-07:00</updated><title type='text'>Workaround to CSS and JS cache woes</title><content type='html'>Here is a method I found of making it so the browser receives new CSS and Javascript files when they are changed on the server. It works by appending a timestamp parameter of when the file was last modified.

&lt;pre class="php" name="code"&gt;
function urlmtime($url) {
   $parsed_url = parse_url($url);
   $path = $parsed_url['path'];
   if ($path[0] == "/") {
       $filename = $_SERVER['DOCUMENT_ROOT'] . "/" . $path;
   } else {
       $filename = $path;
   }
   if (!file_exists($filename)) {
       // If not a file then use the current time
       $lastModified = date('YmdHis');
   } else {
       $lastModified = date('YmdHis', filemtime($filename));
   }
   if (strpos($url, '?') === false) {
       $url .= '?ts=' . $lastModified;
   } else {
       $url .= '&amp;amp;ts=' . $lastModified;
   }
   return $url;
}

function include_css($css_url, $media='all') {
   // According to Yahoo, using link allows for progressive 
   // rendering in IE where as @import url($css_url) does not
   echo '&amp;lt;link rel="stylesheet" type="text/css" media="' .
      $media . '" href="' .
      urlmtime($css_url) . '"&amp;gt;'."\n";
}

function include_javascript($javascript_url) {
   echo '&amp;lt;script type="text/javascript" src="' .
     urlmtime($javascript_url) .
     '"&amp;gt;&amp;lt;/script&amp;gt;'."\n";
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6272487201184082806-4116351990504932898?l=phpcodetips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://phpcodetips.blogspot.com/feeds/4116351990504932898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6272487201184082806&amp;postID=4116351990504932898' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/4116351990504932898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6272487201184082806/posts/default/4116351990504932898'/><link rel='alternate' type='text/html' href='http://phpcodetips.blogspot.com/2008/06/workaround-to-css-and-js-cache-woes.html' title='Workaround to CSS and JS cache woes'/><author><name>Grom</name><uri>http://www.blogger.com/profile/07559995724297228420</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://bp3.blogger.com/_CAaqgV4Ew84/SFjrZplfXDI/AAAAAAAAAAM/WrlJvOun0h0/S220/me.jpg'/></author><thr:total>0</thr:total></entry></feed>
