3v4l.org

run code in 300+ PHP versions simultaneously
<?php interface Equalable { function equal(User $otherUser): bool; } class Transaction { function __construct( public int $amount, public string $type, ) {} } class User implements Equalable { private array $transactions = []; function __construct(public string $name) {} // Assume this is operator ==(...) function equal(User $otherUser): bool { // Junior developer only has use-case where he needs to the username. return $otherUser->name === $this->name; } function mergeTransactions(User $user) { $this->transactions = array_merge($this->transactions, $user->transactions); } function addTransaction(Transaction $transaction) { $this->transactions[] = $transaction; } function getTransactions(): array { return $this->transactions; } } function mergeUsers() { $users = []; foreach( ObjectCache::getCache() as $user) { if (!array_key_exists($user->name, $users)) { $users[$user->name] = $user; } if ($users[$user->name] !== $user) { $users[$user->name]->mergeTransactions($user); } } ObjectCache::set($users); } class ObjectCache { private static string $method; private static array $objects; static function getCache(): array { return self::$objects; } static function add(Equalable $eq): void { if (count(self::$objects) === 0) { self::$objects[] = $eq; return; } foreach (self::$objects as $object) { switch (self::$method) { case 'built-in': if ($eq != $object) { self::$objects[] = $eq; break; } break; case 'op-overload': // Assume this is $eq != $object if (!$eq->equal($object)) { self::$objects[] = $object; break; } break; } } } static function set(array $objects): void { self::$objects = $objects; } static function init(string $method): void { self::$method = $method; self::$objects = []; } static function search(string $prop, mixed $value): ?object { $values = array_column(self::$objects,$prop); $index = array_search($value,$values); return $index !== false ? self::$objects[$index] : null; } } function loadFromDB() { $u = new User( "John" ); $u->addTransaction(new Transaction(100,'credit')); $u->addTransaction(new Transaction(500,'credit')); $u->addTransaction(new Transaction(250,'credit')); return $u; } foreach( ['built-in','op-overload'] as $method) { ObjectCache::init($method); echo "Method: {$method}\n"; $john = new User( "John" ); ObjectCache::add( $john ); ObjectCache::add( loadFromDB()); mergeUsers(); print_r(ObjectCache::getCache()); }
Output for 8.1.30 - 8.1.33, 8.2.22 - 8.2.29, 8.3.5 - 8.3.25, 8.4.1 - 8.4.12
Method: built-in Array ( [John] => User Object ( [transactions:User:private] => Array ( [0] => Transaction Object ( [amount] => 100 [type] => credit ) [1] => Transaction Object ( [amount] => 500 [type] => credit ) [2] => Transaction Object ( [amount] => 250 [type] => credit ) ) [name] => John ) ) Method: op-overload Array ( [John] => User Object ( [transactions:User:private] => Array ( ) [name] => John ) )

preferences:
54.96 ms | 409 KiB | 5 Q