Вы должны рассматривать свой контроллер как один из множества интерфейсов, в идеале ваш контроллер должен только заботиться обо всем, что специфично для 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
на нем.Если вы хотите, чтобы ваучер выплачивался только при создании, вы можете установить для метода pay
значение protected
вместо public
, а затем использовать прослушиватель событий Eloquent, чтобы вызвать событие created
и предотвратить его.от использования в любое другое время.
Что касается обновления ваучеров в дальнейшем: было бы ошибкой допускать, чтобы ваучеры были изменяемыми, но если вы должны это сделать, вы все равно должны рассматривать транзакции как неизменяемые, что означает любое изменение вваучер должен создавать новые транзакции с получателем и отправителем, которые бы равнялись суммам, вы никогда не должны изменять исторические данные транзакции в системе учета.
Примечание: если бы я разрабатывал это, я почти наверняка неЯ делаю это таким образом, но мне нужно лучше понять назначение и функциональность ваших приложений, чтобы правильно их спроектировать, поэтому то, что я привел здесь, - это лучшее усилие, основанное на том, чем вы поделились, но не идеальное решение.