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.php
的 updatedQuery()
函数中 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.php
和 Recipe.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 时保留它。
我正在尝试从我的数据库的 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.php
的 updatedQuery()
函数中 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.php
和 Recipe.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 时保留它。