如何使用 Maatwebsite/Excel 包在 Laravel 中触发模型观察器?
How to trigger a Model Observer in Laravel with the Maatwebsite/Excel package?
也许是一个简单的解决方案的问题,但我有几个小时试图找出答案。
抱歉我的英语不好...
我有一个管理产品、客户、订单、货币和其他东西的项目,这里最重要的是产品与数据库的操作,我使用 Laravel 8 和 Maatwebsite/excel 包来管理包含所有产品信息的 xlsx 文件的导入。
导入文件的过程运行良好,我有一个 ProductObserver 文件,它仅在我使用 CRUD 时触发事件,问题是导入发生时这些事件不会触发。
我会 post 我认为与流程相关的所有文件。
ProductObserver.php
* Handle the Product "created" event.
*
* @param \App\Models\Product $product
* @return void
*/
public function created(Product $product)
{
if ($product->check_custom_price != 'on') {
$currencies = Currency::all();
foreach ($currencies as $currency) {
ProductPrice::create([
'product_id' => $product->id,
'currency_id' => $currency->id,
'price' => $product->base_price * $currency->value,
'status' => 'A'
]);
}
}
}
/**
* Handle the Product "updated" event.
*
* @param \App\Models\Product $product
* @return void
*/
public function updated(Product $product)
{
if($product->isDirty('base_price') && $product->check_custom_price != 'on'){
ProductPrice::where('product_id', $product->id)->update([
'status' => 'I',
]);
$currencies = Currency::all();
foreach ($currencies as $currency) {
ProductPrice::create([
'product_id' => $product->id,
'currency_id' => $currency->id,
'price' => $product->base_price * $currency->value,
'status' => 'A'
]);
}
}
}
这里的2个事件正如我所说的那样完美触发。
ProductImport.php
<?php
namespace App\Imports;
use App\Models\Product;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithUpserts;
class ProductsImport implements ToModel, WithHeadingRow, WithUpserts
{
/**
* @return string|array
*/
public function uniqueBy()
{
return 'name';
}
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new Product([
'name' => $row['name'],
'base_price' => $row['base_price'],
'check_custom_price' => $row['check_custom_price'],
]);
}
}
如您所见,我有 ProductPrice, Currency, Product
个模型及其表格来保存产品对每种货币的每个价格。
我错过了什么?
更新:
EventServiceProviders.php
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use App\Models\Product;
use App\Models\Currency;
use App\Observers\ProductObserver;
use App\Observers\CurrencyObserver;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
Product::observe(new ProductObserver);
Currency::observe(new CurrencyObserver);
}
}
Observer 已注册,我对此没有任何问题,当我使用控制器操作创建或更新产品时,它就像魅力一样工作,感谢您的回答。
我很确定问题出在包保存模型的方式上。
在这个文档中:https://docs.laravel-excel.com/3.1/imports/model.html,他们说:
“将为您保存返回的模型。每一行将导致(至少)一次保存,并且还会触发模型事件。”
并且 save
事件触发与创建或更新相同。
但是当导入时...没有任何反应。
我看不出代码有什么问题,所以我想你可能忘记注册观察者了。
use App\Models\Product;
use App\Observers\ProductObserver;
class EventServiceProvider extends ServiceProvider
{
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
Product::observe(ProductObserver::class);
}
}
这里的问题是,当导入数据时,它使用的是 ->insert() 方法,该方法确实会阻止触发任何事件。
也许是一个简单的解决方案的问题,但我有几个小时试图找出答案。 抱歉我的英语不好...
我有一个管理产品、客户、订单、货币和其他东西的项目,这里最重要的是产品与数据库的操作,我使用 Laravel 8 和 Maatwebsite/excel 包来管理包含所有产品信息的 xlsx 文件的导入。
导入文件的过程运行良好,我有一个 ProductObserver 文件,它仅在我使用 CRUD 时触发事件,问题是导入发生时这些事件不会触发。
我会 post 我认为与流程相关的所有文件。
ProductObserver.php
* Handle the Product "created" event.
*
* @param \App\Models\Product $product
* @return void
*/
public function created(Product $product)
{
if ($product->check_custom_price != 'on') {
$currencies = Currency::all();
foreach ($currencies as $currency) {
ProductPrice::create([
'product_id' => $product->id,
'currency_id' => $currency->id,
'price' => $product->base_price * $currency->value,
'status' => 'A'
]);
}
}
}
/**
* Handle the Product "updated" event.
*
* @param \App\Models\Product $product
* @return void
*/
public function updated(Product $product)
{
if($product->isDirty('base_price') && $product->check_custom_price != 'on'){
ProductPrice::where('product_id', $product->id)->update([
'status' => 'I',
]);
$currencies = Currency::all();
foreach ($currencies as $currency) {
ProductPrice::create([
'product_id' => $product->id,
'currency_id' => $currency->id,
'price' => $product->base_price * $currency->value,
'status' => 'A'
]);
}
}
}
这里的2个事件正如我所说的那样完美触发。
ProductImport.php
<?php
namespace App\Imports;
use App\Models\Product;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithUpserts;
class ProductsImport implements ToModel, WithHeadingRow, WithUpserts
{
/**
* @return string|array
*/
public function uniqueBy()
{
return 'name';
}
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new Product([
'name' => $row['name'],
'base_price' => $row['base_price'],
'check_custom_price' => $row['check_custom_price'],
]);
}
}
如您所见,我有 ProductPrice, Currency, Product
个模型及其表格来保存产品对每种货币的每个价格。
我错过了什么?
更新: EventServiceProviders.php
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use App\Models\Product;
use App\Models\Currency;
use App\Observers\ProductObserver;
use App\Observers\CurrencyObserver;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
Product::observe(new ProductObserver);
Currency::observe(new CurrencyObserver);
}
}
Observer 已注册,我对此没有任何问题,当我使用控制器操作创建或更新产品时,它就像魅力一样工作,感谢您的回答。
我很确定问题出在包保存模型的方式上。
在这个文档中:https://docs.laravel-excel.com/3.1/imports/model.html,他们说:
“将为您保存返回的模型。每一行将导致(至少)一次保存,并且还会触发模型事件。”
并且 save
事件触发与创建或更新相同。
但是当导入时...没有任何反应。
我看不出代码有什么问题,所以我想你可能忘记注册观察者了。
use App\Models\Product;
use App\Observers\ProductObserver;
class EventServiceProvider extends ServiceProvider
{
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
Product::observe(ProductObserver::class);
}
}
这里的问题是,当导入数据时,它使用的是 ->insert() 方法,该方法确实会阻止触发任何事件。