Skip to content

Instantly share code, notes, and snippets.

@swvitaliy
Created February 4, 2012 15:55
Show Gist options
  • Save swvitaliy/1738673 to your computer and use it in GitHub Desktop.
Save swvitaliy/1738673 to your computer and use it in GitHub Desktop.
Mixins in php5.3
<?php
/**
* mixin.php
* Mixin emulation in php 5.3
*
* Author: swvitaliy
*/
class MixinContainer extends stdClass {
private $_mixin_protectes = array();
protected $_mixin_objs = array();
protected function _mixin_call_($name, $args, &$found = null) {
$found = $this->$name instanceof ReflectionMethod;
if ($found) {
$mixinObj = $this->_mixin_objs[$this->$name->class];
$mixinObj->_mixin_before_call_($name, $this);
return $this->$name->invokeArgs($mixinObj, $args);
}
}
public function __call($name, $args) {
return $this->_mixin_call_($name, $args);
}
protected function _mixin_init_($mixinName) {
$mixinClass = new ReflectionClass($mixinName);
$thisClass = new ReflectionClass($this);
foreach ($mixinClass->getDefaultProperties() as $propName=>$propValue) {
if ($thisClass->hasProperty($propName)) continue;
$property = $mixinClass->getProperty($propName);
if (!$property->isStatic() && strpos($propName, '_mixin_')!==0) {
$this->$propName = $propValue;
if ($property->isProtected())
$this->_mixin_protectes [$propName] = $propValue;
}
}
foreach ($mixinClass->getMethods() as $mixinMethod) {
$methodName = $mixinMethod->getName();
if ($thisClass->hasMethod($methodName)) continue;
if (!$mixinMethod->isStatic() && $mixinMethod->isPublic() && strpos($methodName, '_mixin_')!==0)
$this->$methodName = $mixinMethod;
}
$this->_mixin_objs [$mixinName] = new $mixinName;
}
protected function _mixin_super_($mixinName, $mixinMethod) {
$args = array_slice(func_get_args(), 2);
$mixinObj = $this->_mixin_objs[$mixinName];
$mixinObj->_mixin_before_call_($mixinMethod, $this);
$reflectMethod = new ReflectionMethod($mixinName, $mixinMethod);
return $reflectMethod->invokeArgs($mixinObj, $args);
}
}
class Mixin extends stdClass {
protected static $_mixin_meta_ = array (
// relations
// 'method' => array ('property1', 'property2', /* etc */),
);
public function _mixin_before_call_($methodName, MixinContainer $container) {
if (!isset(static::$_mixin_meta_[$methodName]))
return;
$properties = static::$_mixin_meta_[$methodName];
foreach ($properties as $property)
$this->$property = $container->$property;
}
}
/*
class T0 extends Mixin {
const to_c = 't0_c';
public static $t0_pus = 't0_pus';
protected static $t0_pros = 't0_pros';
private static $t0_pris = 't0_pris';
public static function t0_pusf() { return 't0_pusf'; }
protected static function t0_prosf() { return 't0_prosf'; }
private static function t0_prisf() { return 't0_prisf'; }
public $t0_pu = 't0_pu';
protected $t0_pro = 't0_pro';
private $t0_pri = 't0_pri';
public function t0_puf() { return 't0_puf'; }
protected function t0_prof() { return 't0_prof'; }
private function t0_prif() { return 't0_prif'; }
public function t0_prif_test() { return $this->t0_prif(); }
public function t0_prof_test() { return $this->t0_prof(); }
}
class A extends MixinContainer {
public function __construct() {
$this->_mixin_init_('T0');
}
}
// access error
// $t0 = new T0;
// $t0->t0_pro = 'sd';
$a = new A();
echo $a->t0_pu . "\n";
// access error?
echo $a->to_pro = "blablabla\n"; // now it public property :(
//echo $a->t0_pro . "\n";
//echo $a->t0_pri . "\n";
// errors
//echo A::t0_pus . "\n";
//echo A::t0_pros . "\n";
//echo A::t0_pris . "\n";
echo $a->t0_puf() . "\n";
echo $a->t0_prof_test() . "\n";
echo $a->t0_prif_test() . "\n";
class T1 extends Mixin {
protected static $_mixin_meta_ = array (
'message' => array('t1_hello', 't1_who'),
);
public $t1_hello = 'Hello';
public $t1_who = 'World!';
public function message () { return $this->t1_hello . ' ' . $this->t1_who; }
}
class B extends MixinContainer {
public function __construct() {
$this->_mixin_init_('T1');
}
}
$b = new B;
echo $b->message() . "\n";
$b->t1_who = 'Jonny!';
echo $b->message() . "\n";
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment