英文:
Mutating a field and performing a lookup in Laravel 9
问题
我有两个模型,Cart
和 Incode
。Cart
有一个名为 incode_txt
的字段,该字段被填充为一个包含字母和数字的字符串,例如 5td
。
当发生这种情况时,我有一个修改器来确保将字符串转换为大写,如下所示:
return Attribute::make(
set: fn (string $value) => strtoupper($value)
);
这是根据 Laravel 文档 中定义修改器的方式完成的。到目前为止一切顺利。
然而,Cart
模型还有另一个名为 address_incode_id
的字段。每当设置 incode_txt
时,我想使用相同的 $value
在 Incode
模型上执行搜索,如下所示:
$incode = Incode::where('name', '=', $value)
->orWhere('name', 'LIKE', $value[0] . '%')
->first();
然后,我希望将 $incode->id
保存到 Cart
模型的 address_incode_id
字段上。
我的问题是:我是否可以以某种方式将这两个操作合并到同一个修改器中,如果可以,这是否是一个好主意?我想知道如何正确实现这样的操作方式。Laravel 文档中有一节关于 修改多个属性,但似乎与我的用例不相关。
英文:
I have two models, Cart
and Incode
. Cart
has a field called incode_txt
which gets populated with an alphanumeric string such as 5td
When this happens, I have a mutator to make sure the string gets converted to uppercase as so:
return Attribute::make(
set: fn (string $value) => strtoupper($value)
);
This is done following the Laravel Docs for defining mutators. So far so good.
However, I also have another field on the Cart
model called address_incode_id
. Every time incode_txt
is set, I want to perform a search on the Incode
model using the same $value
like this:
$incode = Incode::where('name', '=', $value)
->orWhere('name', 'LIKE', $value[0] . '%')
->first();
I then want $incode->id to be saved to the address_incode_id field on the Cart
model.
My question: Can I somehow merge these two actions into the same mutator and, if so, is it even a good idea to do so? I'd like to know what the correct way to achieve something like this is. The Laravel docs has a piece about Mutating Multiple Attributes but it doesn't seem relevant to my use case.
答案1
得分: 1
以下是使用观察者的完整示例:
生成一个观察者
php artisan make:observer CartObserver --model=Cart
编辑生成的文件位于 app/Observers/CartObserver.php
以下是一个示例,仅观察更新事件,并检查特定属性是否已使用 isDirty
修改。
use App\Models\Cart;
use App\Models\Incode;
class CartObserver {
public $afterCommit = true; // 在提交后触发
public function updated(Cart $cart) {
if ( $cart->isDirty('incode_txt') ) {
$incode = Incode::where('name', $cart->incode_txt)
->orWhere('name', 'LIKE', $cart->incode_txt . '%')->first();
if ( $incode ) {
$cart->address_incode_id = $incode->id;
$cart->saveQuietly();
// 否则,创建一个静默更新 Card 模型的作业
}
}
}
}
完成后,不要忘记在 app/Providers/AppServiceProvider.php
的 boot
方法中添加你的观察者:
use App\Models\Cart;
use App\Observers\CartObserver;
在 `boot` 方法中:
Cart::observe(CartObserver::class);
英文:
Here's a full exmaple using Observers
Generate an Observer
php artisan make:observer CartObserver --model=Cart
edit the generated file in app/Observers/CartObserver.php
an example below that only observe updated event, the check if the specific attribute is modified using isDirty
use App\Models\Cart;
use App\Models\Incode;
class CartObserver {
public $afterCommit = true; //trigger after commit
public function updated(Cart $cart) {
if ( $cart->isDirty('incode_txt') ) {
$incode = Incode::where('name', $cart->incode_txt)
->orWhere('name', 'LIKE', $cart->incode_txt . '%')->first();
if ( $incode ) {
/* $cart->fill([
'address_incode_id' => $incode->id;
]); */
$cart->address_incode_id = $incode->id;
$cart->saveQuietly();
// Otherwise create a job that update the Card model quietly
}
}
}
}
After that, don't forget to add your observer in app/Providers/AppServiceProvider.php
boot
method
use App\Models\Cart;
use App\Observers\CartObserver;
and on boot
Cart::observe(CartObserver::class);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论