如何使用 AOP 或 Laravel 中的任何其他解决方案在内部自动调用其他控制器
How to use AOP or any other solution in the Laravel to auto call other controller internally
我正在开发一款会计软件,我必须在其中创建凭单,然后凭单应在创建后立即支付,这意味着针对该凭单的交易应从一个账户借记并记入另一个账户.
所以我把这两个表做成了。
- vouchers --> id, amount, from_account_id, to_account_id
- 交易 --> id,account_id,借方,贷方。
我分别制作了model,controller,并添加了CRUD操作方法
我已经为两者创建了 API,并为 CRUD 操作使用了 API。
所以真正的问题现在开始了。
针对一张凭证将发生两笔交易。
例如。
凭证记录:
id = auto_generated, 数量 = 500, from_account_id = 8, to_account_id = 9
所以我必须根据这张凭证记录以下两笔交易。
交易记录:
id = auto_generated, 借方 = 500, 贷方 = 0, account_id = 8
id = auto_generated, 借方 = 0, 贷方 = 500, account_id = 9.
现在我完全手动处理上述内容,这意味着我首先添加凭证,然后创建两个交易对象并根据数据分配值。
所以我在 store
凭证方法中为 3 个模型编写代码。所以我必须重写在凭证 store
方法中添加交易的所有代码。那么,有没有什么方便且更不易 code/error 自动调用针对该凭证的两笔交易的呢?
我也想要同样的更新过程,假设我稍后更新了我的凭证,那么后面的交易应该会自动更新。
您应该将您的控制器视为许多接口的一个接口,理想情况下您的控制器应该只关心任何特定于 HTTP 的东西。当您在控制器中编写代码时,请思考 "will I ever need this functionality outside of this controller?",如果答案是肯定的,那么该功能属于其他地方。
在这种情况下,您是在谈论模型的行为,您是在说 "Vouchers (your model) should be paid (behaviour)"。这是一个好兆头,表明该行为作为一种方法属于您的模型,您可以在创建时(使用事件)或在外部按需调用。例如 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
事件上并防止它在任何其他时间被使用。
关于稍后更新凭证:允许凭证可变是错误的,但如果您必须这样做,那么您仍应将交易视为不可变的,这意味着凭证中的任何更改都应与收件人建立新的交易和发件人的金额相等,您永远不应该修改会计系统中的历史交易数据。
注意:如果我正在设计这个,我几乎肯定不会这样做,但我需要更好地了解您的应用程序目的和功能才能正确设计它,所以我在这里给出的是最好的根据您分享的内容进行努力,但不是完美的解决方案。
我正在开发一款会计软件,我必须在其中创建凭单,然后凭单应在创建后立即支付,这意味着针对该凭单的交易应从一个账户借记并记入另一个账户.
所以我把这两个表做成了。
- vouchers --> id, amount, from_account_id, to_account_id
- 交易 --> id,account_id,借方,贷方。
我分别制作了model,controller,并添加了CRUD操作方法
我已经为两者创建了 API,并为 CRUD 操作使用了 API。
所以真正的问题现在开始了。
针对一张凭证将发生两笔交易。 例如。
凭证记录:
id = auto_generated, 数量 = 500, from_account_id = 8, to_account_id = 9
所以我必须根据这张凭证记录以下两笔交易。
交易记录:
id = auto_generated, 借方 = 500, 贷方 = 0, account_id = 8
id = auto_generated, 借方 = 0, 贷方 = 500, account_id = 9.
现在我完全手动处理上述内容,这意味着我首先添加凭证,然后创建两个交易对象并根据数据分配值。
所以我在 store
凭证方法中为 3 个模型编写代码。所以我必须重写在凭证 store
方法中添加交易的所有代码。那么,有没有什么方便且更不易 code/error 自动调用针对该凭证的两笔交易的呢?
我也想要同样的更新过程,假设我稍后更新了我的凭证,那么后面的交易应该会自动更新。
您应该将您的控制器视为许多接口的一个接口,理想情况下您的控制器应该只关心任何特定于 HTTP 的东西。当您在控制器中编写代码时,请思考 "will I ever need this functionality outside of this controller?",如果答案是肯定的,那么该功能属于其他地方。
在这种情况下,您是在谈论模型的行为,您是在说 "Vouchers (your model) should be paid (behaviour)"。这是一个好兆头,表明该行为作为一种方法属于您的模型,您可以在创建时(使用事件)或在外部按需调用。例如 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
事件上并防止它在任何其他时间被使用。
关于稍后更新凭证:允许凭证可变是错误的,但如果您必须这样做,那么您仍应将交易视为不可变的,这意味着凭证中的任何更改都应与收件人建立新的交易和发件人的金额相等,您永远不应该修改会计系统中的历史交易数据。
注意:如果我正在设计这个,我几乎肯定不会这样做,但我需要更好地了解您的应用程序目的和功能才能正确设计它,所以我在这里给出的是最好的根据您分享的内容进行努力,但不是完美的解决方案。