Laravel Livewire 的问题:尝试读取数组上的 属性 "recipes"

Problem with Laravel Livewire : Attempt to read property "recipes" on array

我正在尝试从我的数据库的 2 个数据table中搜索输入,一个包含蔬菜table,另一个包含由蔬菜table制成的食谱s,我首先使用 vegetable table 中的元素进行搜索输入。但现在我试图包含 repice table 但它不会工作:我收到错误“尝试读取数组上的 属性 “recipes””,但我不明白问题出在哪里.

这是我的代码:

Search.php:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Vegetable;

class Search extends Component
{
    public $query = '';

    public $vegetables;
    public $recipes;

    public function updatedQuery() 
    {
        $this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')->get()->toArray();
    }

    public function render()
    {
        return view('livewire.search');
    }
}

search.blade.php :

<div class="searchcomponent">
    <h1>Recherche</h1>
    <input wire:model="query" type="text" placeholder="Rechercher...">
    
    @if(!empty($query))
        <ul>
            @if(!empty($vegetables))
                <div class="vegetables">

                    @foreach($vegetables as $vegetable)
                        <li><span class="material-icons">lunch_dining</span>{{ $vegetable['name'] }}</li>
                    @endforeach
                
                </div>
            @else
                <li>Pas de résultat</li>
            @endif
            
            <div class="recipes">

                @foreach($vegetables as $vegetable)
                    @foreach($vegetable->recipes as $recipe)
                        <li><span class="material-icons">menu_book</span>{{ $recipe['name'] }}<span class="ingredient">Ingrédient: {{ $vegetable['name'] }}</span></li>
                    @endforeach
                @endforeach
            </div>
        </ul>
    @endif
</div>

我的模特蔬菜table :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Vegetable extends Model
{
    use HasFactory;

    public $timestamps = false;

    protected $fillable = ['name'];

    public function recipes(){
        return $this->belongsToMany(Recipe::class, 'vegetables_recipes', 'vegetable_id', 'recipe_id');
    }

    public function getName($id) {
        return $this->name;
    }
}

我的模特食谱:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Recipe extends Model
{
    use HasFactory;
    public $timestamps = false;

    protected $fillable = ['name'];

    public function vegetables(){
        return $this->hasOne(Vegetable::class, 'vegetables_recipes', 'recipe_id', 'vegetable_id');
    }

    public function getName($id) {
        return $this->name;
    }
}

我的模型 table VegetablesRecipe :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class VegetablesRecipe extends Model
{
    use HasFactory;

    public $timestamps = false;

    protected $fillable = ['vegetable_id', 'recipe_id'];
}

提前致谢

所以我发现了你的代码的问题;我昨天没注意到它,因为它隐藏在 Search.phpupdatedQuery() 函数中 off-screen:

$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->get()
->toArray();

当您调用 ->toArray() 时,您将 Vegetable 模型实例的集合转换为数组的数组。这意味着您不能使用对象访问来获取属性:

$vegetable->recipes; // Fails with error "Attempt to read property "recipes" on array"

此外,您不能访问任何模型函数,因为数组不是模型的实例:

$vegetables['recipes']; // Undefined array key "recipes"

因为 public function recipes()Vegetable.php 模型 class 的一种方法,那将不起作用。它 可以 工作,如果你先加载它 然后 投射到数组:

$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->with('recipes')
->get()
->toArray();

现在,$vegetable['recipes'] 可以工作,但最好完全放弃 ->toArray()

$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->with('recipes')
->get();

此外,出于性能原因,您希望包含 ->with('recipes') 以防止在循环时调用 N+1 查询。

完成这些更改后,您可以按如下方式编写 livewire/search.blade.php 代码:

<div class="searchcomponent">
  <h1>Recherche</h1>
  <input wire:model="query" type="text" placeholder="Rechercher...">
  @if(!empty($query))
    <ul>
      @if(!empty($vegetables))
        <div class="vegetables">
          @foreach($vegetables as $vegetable)
            <li><span class="material-icons">lunch_dining</span>{{ $vegetable->name }}</li>
          @endforeach
        </div>
      @else
        <li>Pas de résultat</li>
      @endif
      <div class="recipes">
        @foreach($vegetables as $vegetable)
          @foreach($vegetable->recipes as $recipe)
            <li><span class="material-icons">menu_book</span>{{ $recipe->name }}<span class="ingredient">Ingrédient: {{ $vegetable->name }}</span></li>
          @endforeach
        @endforeach
      </div>
    </ul>
  @endif
</div>

最后,一些清理工作:

Vegetable.phpRecipe.php

方法getName($id)没有任何意义;你没有对 $id 做任何事情,并且 name 不是私有的 属性;你可以简单地做 $vegetable->name$recipe->name,它会和这些方法做的一样。

Recipe.php

如评论中所述,belongsToMany()belongsToMany() 的倒数,而不是 hasOne():

public function vegetables(){
  return $this->belongsToMany(Vegetable::class, 'vegetables_recipes');
}

此外,如果主键和外键名称与模型名称匹配,则不需要它们。枢轴 table 的正确名称是 recipes_vegetables(复数,按字母顺序排列),因此需要指定。您可以对 Vegetable.php:

执行相同的操作
public function recipes(){
  return $this->belongsToMany(Recipe::class, 'vegetables_recipes');
}

最后,您的模型 VegetablesRecipe.php 不需要,当前未使用。您通常不会为 Pivot 定义模型 table,因此您可以删除它,或者在您需要直接修改 Pivot 时保留它。