【问题标题】:Laravel Scout/Algolia: Model relationships not pulling through to indexLaravel Scout/Algolia:模型关系没有通过索引
【发布时间】:2020-07-29 09:31:35
【问题描述】:

我有 3 个模型——产品、用户和用户产品。 UserProduct 是具有用户特定价格、产品代码等的特定产品的实例。因此,一个产品可以有许多用户产品,并且通过这些用户产品,可以有许多用户。这些关系在 Product 模型中定义:

public function userProducts() {
       return $this->hasMany(UserProduct::class);
}
 
public function users() {
return $this->belongsToMany(User::class, 'user_products');
}

我知道这些关系正在发挥作用,就像在 Artisan Tinker 中一样,我将其中任何一个作为属性调用时都会得到结果。

在我的 Algolia products 索引中,我希望结果包含有关用于过滤的相关用户和 UserProducts 的信息。因此,我按照 Scout Extended 和 Algolia 文档中的建议加载这些关系:

public function toSearchableArray() {
    $this->users;
    $this->userProducts;
    $array = $this->toArray();
     // Apply Scout Extended default transformations:
    $array = $this->transform($array);
    return $array;
}

一切都在进行中,但由于某种原因,“用户”和“用户产品”都空了。

这更加令人困惑,因为具有“用户”和“产品”关系的 UserProducts 在它们被拉入我的 user_products 索引之前成功加载了这些关系:

由此,我只能得出结论,问题一定在于我如何设置填充数据库的工厂文件。对于 UserProducts,我使用了一个简单的工厂:

<?php
 
/** @var \Illuminate\Database\Eloquent\Factory $factory */
 
use App\UserProduct;
use Faker\Generator as Faker;
 
$factory->define(UserProduct::class, function (Faker $faker) {
   return [
       'code' => 'EAN' . $faker->ean8,
       'price' => $faker->randomFloat(2, 5, 1000),
       'product_id' => App\Product::all()->random()->id,
       'user_id' => App\User::where('type', 'supplier')->inRandomOrder()->first()->id
   ];
});

……而在用户工厂中发生的事情要复杂一些:

$factory->define(User::class, function (Faker $faker) {
   return [
       'display_name' => $faker->name,
       'email' => $faker->unique()->safeEmail,
       'phone' => $faker->phoneNumber,
       'type'  => array_rand(['supplier', 'buyer']),
       'profile_completed' => true,
       'email_verified_at' => now(),
       'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
       'remember_token' => Str::random(10),
   ];
});
 
$factory->afterCreating(User::class, function ($user, $faker) {
 
   $user->assignRole($user->type);
 
   if($user->type==='supplier') {
       // create five products for them
       $products = factory(App\Product::class, 5)->create();
 
       $products->each(function($product) use ($user) {
 
           $user_product = factory(App\UserProduct::class)->create([
               'product_id' => $product->id,
               'user_id' => $user->id
           ]);
 
       })->each(function($product){
           $product->setUserProductCount();
           $product->update();
       });
 
   }
});

在 afterCreating 回调中所做的所有更改都已成功执行。但是,再多摆弄这段代码,添加 $product->searchable() 等似乎都可以将必要的数据带入我的产品索引。任何有用的建议将不胜感激。

【问题讨论】:

  • 我已经确定这绝对是工厂定义的问题,因为更新产品实例会使用所有必要信息更新索引中该产品的记录。不过还没弄清楚工厂出了什么问题。

标签: php laravel eloquent algolia laravel-scout


【解决方案1】:

可能是您忘记在您的 Product 模型上使用 Laravel 的 touch 功能。见https://www.algolia.com/doc/framework-integration/laravel/indexing/configure-searchable-data/?language=php#updating-relations-when-parentchild-change

如果这能解决您的问题,请告诉我

【讨论】:

  • 不幸的是,使用触摸功能似乎对我的问题没有帮助。在“users”属性(belongsToMany 关系)上使用它不会执行任何操作,而在“userProducts”属性(hasMany 关系)上使用它会导致种子命令无限期挂起。
  • 实际上,经过一番摆弄之后,这似乎确实是必要的修复,我之前的结果被与 laravel/artisan/composer 的缓存行为有关的东西混淆了。添加 $touches 数组后,索引工作正常。感谢您的帮助。
猜你喜欢
  • 2018-06-19
  • 2017-10-19
  • 1970-01-01
  • 2017-04-30
  • 1970-01-01
  • 2020-06-11
  • 2019-02-18
  • 1970-01-01
  • 2019-11-23
相关资源
最近更新 更多