<?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