<?php class Collection { private $items; private static $macros = []; public static function macro($name, callable $macro) { static::$macros[$name] = Closure::fromCallable($macro); } public static function mixin($class) { foreach (get_class_methods($class) as $method) { static::macro($method, $class->$method()); } } public function __construct(array $items) { $this->items = $items; } public function map(callable $callback) { return new static(array_map($callback, $this->items)); } public function all() { return $this->items; } public function exampleClosure() { return function () { return $this->items; }; } public function __call($method, $args) { return static::$macros[$method]->bindTo($this, static::class)(...$args); } public static function __callStatic($method, $args) { return static::$macros[$method]->bindTo(null, static::class)(...$args); } } Collection::macro("flatMap", function (callable $callback) { $tmp = []; foreach ($this->items as $item) { $tmp = array_merge($tmp, $callback($item)); } return new static($tmp); }); $items = new Collection(["a", "b", "c"]); $items = $items->flatMap(function ($item) { return [$item, $item]; }); if ($items->all() === ["a", "a", "b", "b", "c", "c"]) { echo "it works"; } // This is the thing that is deprecated and causes a warning: // Here we're removing $this from a closure that isn't static // All non-static closures will have a $this in PHP 8.x when defined in a method try { var_dump( $items->exampleClosure()->bindTo(null)() ); } catch (\Throwable $e) { // We'll get an error about using $this is a non-object context // This will no longer be possible after PHP 7.4 var_dump($e); } // You can definitely still do this: class UnrelatedClass { private $items = ["foo", "bar"]; } var_dump( $items->exampleClosure()->bindTo(new UnrelatedClass, UnrelatedClass::class)() ); // The only thing that could cause problems is: // methods meant to be called statically in a mixin that were not defined with static: class SomeMixin { public function range() { return function ($start, $end) { return new static(range($start, $end)); }; } public function staticRange() { return static function ($start, $end) { return new static(range($start, $end)); }; } } Collection::mixin(new SomeMixin()); // This will error because: // 1. the above is not defined with static // 2. The closure is written inside a class var_dump(Collection::range(0, 10)); // The following will not because the closure was defined with static var_dump(Collection::staticRange(0, 10)); // Basically the change prevents the creation of methods and closures that can be used as instance and static methods at the same time by dynamically checking $this inside the function.
You have javascript disabled. You will not be able to edit any code.