<?php
function transfer($fromAccountId, $toAccountId, $amount)
{
DB::beginTransaction();
try {
$fromQuery = Account::whereId($fromAccountId);
if (! $fromQuery->exists()) {
throw new InvalidAccountException();
}
$toQuery = Account::whereId($toAccountId);
if (! $toQuery->exists()) {
throw new InvalidAccountException();
}
$fromAccount = $fromQuery->lockForUpdate()->first();
if ($amount > $fromAccount->balance) {
throw new InsufficientBalanceException();
}
$toAccount = $toQuery->lockForUpdate()->first();
$toAccount->balance += $amount;
$toAccount->save();
$fromAccount->balance -= $amount;
$fromAccount->save();
$transaction = new Transaction();
$transaction->from_account_id = $fromAccountId;
$transaction->to_account_id = $toAccountId;
$transaction->amount = $amount;
$transaction->save();
DB::commit();
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}