<?php
interface iface_dynamic_members{
public function __call($name, $args);
public function __set($name, $value);
public function quietly_fail():bool;
}
trait trait_has_dynamic_members{
public function __call($name, $args) {
if (is_callable($this->$name)) {
return call_user_func($this->$name, $args);
}
else {
if($this->quietly_fail()===true){
echo 'Method does not exist, but I do not mind.';
}else{
echo 'Method does not exist, I consider this a bug.';
}
}
}
public function __set($name, $value) {
$this->$name = is_callable($value) ? $value->bindTo($this, $this): $value; }
}
abstract class MBR_ATTR{
public static function is_a_walker(iface_dynamic_members $obj, ?string $walker_type='normal pace'){
$obj->walker_type = $walker_type;
$obj->walker_walk = function() {
return "I am walking {$this->walker_type}.";
};
}
public static function is_a_runner(iface_dynamic_members $obj, string $runner_type){
$obj->runner_type = $runner_type;
$obj->runner_run = function() {
return "I am running {$this->runner_type}.";
};
self::is_a_walker($obj); }
}
class cls_partly_dynamic implements iface_dynamic_members{
use trait_has_dynamic_members;
public function quietly_fail():bool{
return true;
}
}
error_reporting(E_ALL & ~E_NOTICE); $obj_runner = new cls_partly_dynamic();
MBR_ATTR::is_a_runner($obj_runner, 'fast');
$obj_runner->runner_type = 'a bit slow';
$obj_walker = new cls_partly_dynamic();
MBR_ATTR::is_a_walker($obj_walker, 'slow');
$obj_walker->walker_type = 'super fast';
echo 'walker in action...' . '<br>';
echo $obj_walker->walker_walk() . '<br>';
echo '<br>';
echo 'runner in action...' . '<br>';
echo $obj_runner->walker_walk() . '<br>';
echo $obj_runner->runner_run() . '<br>';
echo $obj_runner->xxx() . '<br>'; ?>