你应该把你的控制器看作是许多接口中的一个,理想情况下,你的控制器应该
只有
关心任何特定于HTTP的内容。当你在控制器中编写代码时,你会想“我会需要这个控制器之外的功能吗?”如果答案是肯定的,那么该功能属于其他地方。
在这种情况下,你说的是你的模特的行为,你说的是“你的模特应该得到报酬(行为)”。这是一个很好的迹象,表明行为属于您的模型,作为一种方法,您可以在创建时(使用事件)或在外部按需调用它。例如在
App\Voucher.php
:
/**
* Account that is debited by the voucher.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function from(): HasOne
{
return $this->hasOne(Account::class, 'id', 'from_account_id');
}
/**
* Account that is credited by the voucher.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function to(): HasOne
{
return $this->hasOne(Account::class, 'id', 'to_account_id');
}
/**
* Credit the voucher amount.
*
* @return void
*/
public function pay(): void
{
$this->from()->transactions()->create([
'debit' => $this->amount,
'credit' => 0,
]);
$this->to()->transactions()->create([
'debit' => 0,
'credit' => $this->amount,
]);
}
然后你的控制器方法看起来像这样:
/**
* Create the Voucher and pay it out.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request): RedirectResponse
{
$voucher = Voucher::create([
'from_account_id' => $request->from,
'to_account_id' => $request->to,
'amount' => $request->amount,
]);
$voucher->pay();
return redirect()->route('vouchers.index')->with([
'success' => "{$request->amount} has been credited to your recipient."
]);
}
然后,任何时候你需要支付代金券,你可以打电话给
pay
方法。如果您只想在创建凭证时支付凭证,则可以设置
支付
方法
protected
而不是
public
然后使用雄辩的事件监听器在
created
事件,并防止其在任何其他时间被使用。
关于以后更新凭单:允许凭单可变是错误的,但如果必须这样做,则仍应将交易视为不可变的,这意味着凭单中的任何更改都应与接收方和发送方创建新的交易,使金额相等,决不应修改会计系统中的历史交易数据。
注意:如果我设计这个,我几乎肯定不会这样做,但我需要更好地了解您的应用程序的目的和功能,以便正确地设计它,所以我在这里给出的是基于您共享的内容的最佳努力,但不是完美的解决方案。