如何使用 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() 方法,该方法确实会阻止触发任何事件。

https://github.com/Maatwebsite/Laravel-Excel/issues/2220