-
-
Save mybigman/aab7d086b9a36272b549d441c267bbde to your computer and use it in GitHub Desktop.
A null object pattern implemented in PHP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
# Implements a recursive null object pattern. | |
# | |
# Implemented as a trait so any object can make it's properties use | |
# the null pattern without resorting to inheritance. | |
# | |
# The goal is so you can pull data off a partially populated object | |
# without excessive existance checks. | |
trait NullPattern { | |
# The real data we are wrapping. Since we continually return wrapped | |
# objects if you ever want a unwrapped object the property can be | |
# simply accessed | |
public $__value__; | |
function __call($name, $arguments) { | |
if( is_object($this->__value__) && method_exists($this->__value__, $name) ) | |
return new NullObject(call_user_func_array(array($this->__value__, $name), $arguments)); | |
else | |
return new NullObject(); | |
} | |
function __get($name) { | |
if( is_object($this->__value__) && property_exists($this->__value__, $name) ) | |
return new NullObject($this->__value__->$name); | |
else | |
return new NullObject(); | |
} | |
function __set($name, $value) { | |
if( is_object($this->__value__) ) $this->__value__->$name = $value; | |
} | |
function __isset($name) { | |
return is_object($this->__value__) && property_exists($this->__value__, $name); | |
} | |
function __unset($name) { | |
if( is_object($this->__value__) ) unset($this->__value__->$name); | |
} | |
function __toString() { | |
if( is_array($this->__value__) ) | |
return implode(', ', $this->__value__); | |
else | |
return (string) $this->__value__; | |
} | |
# True if the raw value is not empty | |
function present() { | |
return !empty($this->__value__); | |
} | |
# If not present will return the given default value. If present | |
# then returns the raw actual underlying value. | |
function or_default($default) { | |
if( $this->present() ) { | |
return $this->__value__; | |
} else { | |
return $default; | |
} | |
} | |
# Used to simulate array access when the wrapped object is a | |
# non-asssociative array. So: | |
# | |
# $list(5) | |
# | |
# functions like: | |
# | |
# $list[5] | |
# | |
# Can also update an array in the same way: | |
# | |
# $list(5, 'foo') | |
# | |
# works the same as: | |
# | |
# $list[5] = 'foo' | |
function __invoke($key) { | |
if( !is_array($this->__value__) ) return new NullObject(); | |
if( func_num_args() > 1) $this->__value__[$key] = func_get_arg(1); | |
if( array_key_exists($key, $this->__value__) ) | |
return new NullObject($this->__value__[$key]); | |
else | |
return new NullObject(); | |
} | |
} | |
# A general object that uses the NullPattern trait. Make it easy to | |
# turn any piece of data into something that behaves with the | |
# NullPattern. | |
class NullObject { | |
use NullPattern; | |
# Constructor to wrap a value in a NullObject object | |
function __construct($value=null) { | |
if( $value ) { | |
if( is_assoc($value) ) $value = (object) $value; | |
$this->__value__ = $value; | |
} | |
} | |
} | |
if( !function_exists('is_assoc') ) { | |
# Copied from: http://www.php.net/manual/en/function.is-array.php#89332 | |
function is_assoc($v) { | |
return is_array($v) && array_diff_key($v,array_keys(array_keys($v))); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment