我正在构建一个现有数据库(一个名为Epicor的ERP系统)的Laravel前端,以便在单独的(新)数据库中扩展该功能 . 目前,我正在尝试显示具有运送给客户状态的“设备”,并包含来自零件表的信息 . 数据库关系都存在,我可以使用SSMS获取所需的所有信息 - 所以我相信我在使用Eloquent时一定会出错 . 我有以下型号:
Equipment - 这是系统中的序列号,因此实际上是一个部件的实例:
<?php
class Equipment extends Model
{
protected $table = 'ERP.SerialNo';
public $timestamps = false;
protected $primaryKey = 'SerialNumber';
protected $keyType = 'string';
protected $fillable = [
'SerialNumber',
'SNStatus',
'PartNum',
'TerritoryID',
'JobNum',
'PackNum',
'PackLine',
'RMANum',
'CustNum',
'SNStatus'
];
public function Part()
{
return $this->belongsTo(Part::class,'PartNum','PartNum');
}
public function Customer()
{
return $this->belongsTo(Customer::class,'CustNum', 'CustNum');
}
}
Part
class Part extends Model
{
protected $table = 'ERP.Part';
public $timestamps = false;
protected $primaryKey = 'PartNum';
protected $keyType = 'string';
protected $fillable = [
'PartNum',
'SearchWord',
'Innactive',
'PartDescription',
'ClassID',
'CommodityCode',
'NetWeight'
];
public function ShipmentLine()
{
return $this->hasMany(Shipment::class, 'PartNum', 'PartNum');
}
public function Equipment()
{
return $this->hasMany(Equipment::class,'PartNum', 'PartNum');
}
}
Customer Controller
public function show($CustID)
{
$Customer = Customer::find($CustID);
$Shipments = $Customer->Shipment->where('Voided', '0');
$Equipments = $Customer->Equipment->where('SNStatus', 'SHIPPED');
return view('Customer.show', compact('Equipments', 'Customer','Shipments', 'Parts'));
}
show.blade.php (under Customer)
<?php
@foreach($Equipments as $Equipment)
<tr>
<td>ClassID</td>
<td><a href="{{ route('Part.show',$Equipment->PartNum)}}">{{$Equipment->PartNum}}</a></td>
<td><a href="{{ route('Equipment.show',$Equipment->SerialNumber)}}">{{$Equipment->SerialNumber}}</a></td>
<td>PartDescription is sometimes really really really long.....even longer than this!</td>
</tr>
@endforeach
这一切都运行正常,我得到了所有具有运送给该客户状态的设备的清单 . 我现在要做的是,在设备列表中,包括Part表中的相关字段(ClassID和PartDescription) .
我尝试了一些东西,但觉得我抓着稻草,我的所有尝试都失败了 . 我设法在设备上显示show.blade.php部件信息,所以我相信模型设置好了 .
提前致谢,
理查德
2 回答
首先,Part模型内部的关系方法(以及Customer模型内部)必须以复数形式编写,因为您匹配多个实体:
其次,您可以使用关系来加载控制器中的设备,而不是使用延迟加载:
最后,在刀片模板中,您可以非常轻松地使用设备的一部分:
另外,我建议使用
@forelse
而不是@foreach
来覆盖那些没有设备时的情况:我想你要找的是with() .
在我谈到这一点之前,你实际上遇到了比看起来更大的问题 . Matei Mihai实际上触及了这一点 .
当你有像
$Customer->Equipment
这样的东西时,你're actually making use of Eloquent' s "dynamic properties" . 这意味着,在那里有一个神奇的__get()
,它表示所需的属性是否已经通过with()
或load()
急切加载 .所以当你做
$Customer->Equipment
时,它基本上是$Customer->Equipment()->get()
的快捷方式 .接下来要考虑的是
get()
的结果是Eloquent\Collection,它是Support\Collections的子类 . 而Support \ Collections有自己的where()方法版本 .所有这些,
$Customer->Equipment->where('SNStatus', 'SHIPPED')
不会导致运行如下所示的查询:你正在做的是运行它:
然后要求Collection类在
SNStatus='SHIPPED'
之后过滤生成的集合 . 这可能是一个巨大的性能损失,甚至可以最大化您的服务器RAM,具体取决于这些表的大小 . 我认为你真正想要的是:$Customer->Equipment()->where('SNStatus', 'SHIPPED')->get()
通过调用实际的
Equipment()
方法而不是动态属性,你还没有为它执行查询做好准备,因为你还在为它添加条件 .(另外,作为旁注,你的命名惯例会伤害我的强迫症,方法应该总是“camelCased” . 只有类名的首字母大写 . )
那么......回到你实际问过的问题,包括对
Model::where()
和Collection::where()
之间区别的理解,我们得到的是这样的:由于您要在Parts表中指定实际关注的几个字段,因此可以使用constrained eager-load
这将为您提供一个嵌套的
Part
对象,其中只包含您关注Eloquent\Collection
结果中每个Equipment
模型元素的字段 .至于如何在你的刀片文件中处理这些结果,我与Matei Mihai的不同之处在于,我认为答案非常好 .