Proxy (DesignPatterns) PHP

Hey Everyone,

I started with the Proxy design patterns but I cannot figure one thing out. Well, let start at the beginning. (I have used this article by the way).

On the page, we have some different PHP files and classes.

BankAccount.php

<?php declare(strict_types=1);

namespace DesignPatterns\Structural\Proxy;

interface BankAccount
{
    public function deposit(int $amount);

    public function getBalance(): int;
}

HeavyBankAccount.php

<?php declare(strict_types=1);

namespace DesignPatterns\Structural\Proxy;

class HeavyBankAccount implements BankAccount
{
    /**
     * @var int[]
     */
    private $transactions = [];

    public function deposit(int $amount)
    {
        $this->transactions[] = $amount;
    }

    public function getBalance(): int
    {
        // this is the heavy part, imagine all the transactions even from
        // years and decades ago must be fetched from a database or web service
        // and the balance must be calculated from it

        return (int) array_sum($this->transactions);
    }
}

BankAccountProxy.php

<?php declare(strict_types=1);

namespace DesignPatterns\Structural\Proxy;

class BankAccountProxy extends HeavyBankAccount implements BankAccount
{
    /**
     * @var int
     */
    private $balance;

    public function getBalance(): int
    {
        // because calculating balance is so expensive,
        // the usage of BankAccount::getBalance() is delayed until it really is needed
        // and will not be calculated again for this instance

        if ($this->balance === null) {
            $this->balance = parent::getBalance();
        }

        return $this->balance;
    }
}

ProxyTest.php

<?php declare(strict_types=1);

namespace DesignPatterns\Structural\Proxy\Tests;

use DesignPatterns\Structural\Proxy\BankAccountProxy;
use PHPUnit\Framework\TestCase;

class ProxyTest extends TestCase
{
    public function testProxyWillOnlyExecuteExpensiveGetBalanceOnce()
    {
        $bankAccount = new BankAccountProxy();
        $bankAccount->deposit(30);

        // this time balance is being calculated
        $this->assertSame(30, $bankAccount->getBalance());

        // inheritance allows for BankAccountProxy to behave to an outsider exactly like ServerBankAccount
        $bankAccount->deposit(50);

        // this time the previously calculated balance is returned again without re-calculating it
        $this->assertSame(30, $bankAccount->getBalance());
    }
}

The next thing I don’t really understand. When We look at the last file (ProxyTest.php).
A class is made on $bankAccount and money is added $bankAccount->deposit(30).

The account balance is calculated based on an array in the BankAccountProxy class (/PHP file)

$this->assertSame(30, $bankAccount->getBalance());

After that, there is again a deposit
$bankAccount->deposit(50);

In the end, the balance is loaded again

$this->assertSame(30, $bankAccount->getBalance());

But it won’t load the getBalance function completely? Since it is the heavy part.
And so how can it be calculated it this function is not recalled again?

    public function getBalance(): int
    {
        // this is the heavy part, imagine all the transactions even from
        // years and decades ago must be fetched from a database or web service
        // and the balance must be calculated from it

        return (int) array_sum($this->transactions);
    }

It will be called again the next request, because then you have a new proxy that starts without a balance.

Or you could create a new proxy object directly in this case if you wanted too.

Okay Get it :slight_smile:

1 Like