3v4l.org

run code in 300+ PHP versions simultaneously
<?php namespace app; define('YII_ENV_PROD', false); class BaseObject { protected $enableFriendClassesInProd = false; protected $calledClassStackLimit = 0; protected $friendParents = false; protected $friendDescendants = false; protected $friendClasses = []; public function __call($name, $args) { if (method_exists($this, $name) && method_exists($this, '_call')) { if (!YII_ENV_PROD || $enableFriendClassesInProd ) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, $this->calledClassStackLimit); $stackClasses = array_column($backtrace, 'class'); $calledClass = array_pop($stackClasses); if (in_array($calledClass, $this->friendClasses)) { return call_user_func_array([$this, '_call'], [$name, $args]); } elseif ($this->friendDescendants && is_subclass_of($calledClass, static::class)) { return call_user_func_array([$this, '_call'], [$name, $args]); } elseif ($this->friendParents && is_subclass_of(static::class, $calledClass)) { return call_user_func_array([$this, '_call'], [$name, $args]); } else { throw new \Exception('Method disallowed: ' . get_class($this) . '::' . $name); } } return call_user_func_array([$this, '_call'], [$name, $args]); } else { throw new \Exception('Calling unknown method:' . get_class($this) . '::' . $name); } } public function __get($name) { $getter = 'get' . $name; if (method_exists($this, $getter)) { return $this->$getter(); } elseif (method_exists($this, 'set' . $name)) { throw new \Exception('Getting write-only property: ' . get_class($this) . '::' . $name); } throw new \Exception('Getting unknown property: ' . get_class($this) . '::' . $name); } public function __set($name, $value) { $setter = 'set' . $name; if (method_exists($this, $setter)) { $this->$setter($value); } elseif (method_exists($this, 'get' . $name)) { throw new \Exception('Setting read-only property: ' . get_class($this) . '::' . $name); } else { throw new \Exception('Setting unknown property: ' . get_class($this) . '::' . $name); } } } class Yii { public static $app; } class A extends BaseObject { protected $friendDescendants = true; private function showName() { echo __CLASS__; } protected function _call($name, $args) { return call_user_func_array([$this, $name], $args); } } class B extends A { public function myName() { Yii::$app->showName(); } } Yii::$app = new A(); $b = new B(); $b->myName();
Output for 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.33, 8.2.0 - 8.2.29, 8.3.0 - 8.3.25, 8.4.1 - 8.4.12
app\A

preferences:
150.52 ms | 407 KiB | 5 Q