Banking System
Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 89 of 91.
Challenge
EasyLet's build a Banking System that handles accounts, transactions, and transfers between accounts. You'll create a system with proper encapsulation to protect financial data, inheritance for different account types, and validation to ensure data integrity.
You'll organize your code across six files:
Transaction.php— Create aTransactionclass to record financial operations. Use constructor promotion fortype(string — "deposit", "withdrawal", or "transfer"),amount(float), andtimestamp(string). All properties should be public readonly. Add a methodgetDescription(): stringthat returns"[type]: $[amount]"(format amount to 2 decimal places).BankAccount.php— Include the Transaction file. Create an abstractBankAccountclass with:- Constructor promotion for
accountNumber(string, public readonly) andholderName(string, public readonly) - A protected
$balanceproperty initialized to 0.0 - A private array to store transaction history
getBalance(): float— returns the current balancedeposit(float $amount): string— adds to balance, records transaction, returns"Deposited: $[amount]"abstract withdraw(float $amount): string— child classes implement withdrawal rulesaddTransaction(Transaction $t): void— protected method to add transactions to historygetTransactionCount(): int— returns number of transactions
- Constructor promotion for
SavingsAccount.php— Include the BankAccount file. Create aSavingsAccountclass extendingBankAccountwith:- A class constant
INTEREST_RATEset to 0.02 (2%) withdraw(float $amount): string— if amount exceeds balance, return"Insufficient funds"; otherwise deduct, record transaction, return"Withdrew: $[amount]"applyInterest(): string— calculates interest on current balance, adds it as a deposit, returns"Interest applied: $[interest]"
- A class constant
CheckingAccount.php— Include the BankAccount file. Create aCheckingAccountclass extendingBankAccountwith:- A private
$overdraftLimitproperty set via constructor (add a third parameter with default 100.0) withdraw(float $amount): string— allows withdrawal if amount doesn't exceed balance + overdraft limit; return"Insufficient funds (overdraft limit: $[limit])"on failure, or"Withdrew: $[amount]"on successgetOverdraftLimit(): float— returns the overdraft limit
- A private
Bank.php— Include both account files. Create aBankclass that manages accounts:- A private array to store accounts indexed by account number
addAccount(BankAccount $account): void— adds an accountfindAccount(string $accountNumber): ?BankAccount— returns account or nulltransfer(string $fromAccount, string $toAccount, float $amount): string— transfers money between accounts. Return"Source account not found","Destination account not found", or the result of the withdrawal if it fails. On success, deposit to destination and return"Transferred $[amount] from [from] to [to]"
main.php— Include the Bank file. You'll receive two inputs: accounts data (JSON) and operations (JSON).Accounts JSON format:
[{"type": "savings", "number": "SAV001", "holder": "Alice", "initial": 1000}, {"type": "checking", "number": "CHK001", "holder": "Bob", "initial": 500, "overdraft": 200}]Operations JSON format:
[{"op": "deposit", "account": "SAV001", "amount": 200}, {"op": "withdraw", "account": "CHK001", "amount": 600}, {"op": "transfer", "from": "SAV001", "to": "CHK001", "amount": 300}, {"op": "interest", "account": "SAV001"}, {"op": "balance", "account": "SAV001"}]Create the bank and all accounts (depositing initial amounts). Process each operation:
"deposit"— Print the result ofdeposit()"withdraw"— Print the result ofwithdraw()"transfer"— Print the result oftransfer()"interest"— Print the result ofapplyInterest()(only for savings accounts)"balance"— Print"[holder] balance: $[balance]"(2 decimal places)
Print each result on a new line. Format all monetary amounts to 2 decimal places.
Remember that transfers should be atomic — if the withdrawal fails, the deposit shouldn't happen. The protected $balance property allows child classes to modify it while keeping it hidden from outside code, demonstrating proper encapsulation in a financial context.
Try it yourself
<?php
require_once 'Bank.php';
// Read input
$accountsJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));
// Parse JSON inputs
$accounts = (array)json_decode($accountsJson, true);
$operations = (array)json_decode($operationsJson, true);
// TODO: Create a Bank instance
// TODO: Create accounts from the accounts data
// For each account in $accounts:
// - If type is "savings", create SavingsAccount
// - If type is "checking", create CheckingAccount (with overdraft if provided)
// - Add account to bank
// - Deposit initial amount
// TODO: Process each operation
// For each operation in $operations:
// - "deposit": Print result of deposit()
// - "withdraw": Print result of withdraw()
// - "transfer": Print result of transfer()
// - "interest": Print result of applyInterest() (only for savings)
// - "balance": Print "[holder] balance: $[balance]" (2 decimal places)
?>All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe $this KeywordMethodsPropertiesConstructor (__construct)Destructor (__destruct)Recap - Simple Calculator4Inheritance
Basic InheritanceThe parent:: KeywordMethod OverridingThe final KeywordAbstract ClassesRecap - Employee Hierarchy7Encapsulation
Public, Protected, PrivateAccess Modifiers in DepthGetters and SettersInformation HidingConstructor Promotion (8.0)Recap - Student Records System2Namespaces & Autoloading
Introduction to NamespacesThe use KeywordPSR-4 Autoloading StandardComposer AutoloaderRecap - Organized Project5Interfaces & Contracts
Introduction to InterfacesImplementing InterfacesMultiple Interface ImplementInterface vs Abstract ClassType Hinting with InterfacesRecap - Shape Calculator8Magic Methods
Magic Methods Introduction__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Object Cloning__serialize & __unserializeRecap - Custom Collection11Type System & Error Handling
Type DeclarationsNullable TypesUnion & Intersection TypesException ClassesCustom Exception HierarchyTry, Catch, FinallyRecap - Form Validator14Project: Library Management
Project OverviewBook and User Classes3Class Properties
Instance vs Static PropertiesConstants in ClassesStatic Methods & PropertiesPrivate & Protected PropertiesReadonly Properties (PHP 8.1)Recap - Bank Account Manager6Polymorphism
Method Overriding RevisitedPolymorphism via InterfacesType Hinting & Union TypesLate Static BindingRecap - Payment Processor9Traits
Introduction to TraitsUsing Multiple TraitsTrait Conflict ResolutionAbstract Methods in TraitsTraits vs Inheritance12Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern