duan88014 2018-10-31 14:09
浏览 42
已采纳

循环中的雄辩关系

I'm building a Laravel frontend to an existing database (an ERP system named Epicor) with a view to extending that functionality in a separate (new) database. At the moment I am trying to display pieces of "equipment" that have a status of being shipped to a customer, and include information from the Part table. The DB relationships are all there and I can get all the information I need using SSMS - so I believe I must be going wrong in my use of Eloquent. I have the following models:

Equipment - this is a serial number in the system, so in effect an instance of a part:

<?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

Which all works fine and I get a list of all of the Equipment that has a status of being shipped to that customer. What I'd like to do now is, in the list of equipment, including fields from the Part table that relate (ClassID and PartDescription).

I've tried a few things, but feel I'm clutching at straws and all of my attempts fail. I have managed to display on Equipment show.blade.php Part information, so I believe the models are set up OK.

Thanks in advance,

Richard

  • 写回答

2条回答 默认 最新

  • dsjojts9734 2018-10-31 15:00
    关注

    I think what you're looking for is with().

    Before I get to that though, you actually have a bigger problem there than it seems. Matei Mihai actually touched on this.

    When you have something like $Customer->Equipment, you're actually making use of Eloquent's "dynamic properties". What this means is, there's a magic __get() in there somewhere that says if the desired property doesn't exist on the target model, check to see if it has a relation method by that name. And if so, lazy-load it if it hasn't already been eager-loaded via with() or load().

    So when you do $Customer->Equipment, it's basically a shortcut for $Customer->Equipment()->get().

    Next thing to consider is that the result of get() is an Eloquent\Collection, which is a child-class to Support\Collections. And Support\Collections have their own version of the where() method.

    All that to say, $Customer->Equipment->where('SNStatus', 'SHIPPED') does not result in running a query that looks like:

    SELECT * FROM Equipment WHERE customerID = ? AND SNStatus = 'SHIPPED'
    

    What you're doing is running this instead:

    SELECT * FROM Equipment WHERE customerID = ?
    

    And then asking the Collection class to filter the resulting set by SNStatus='SHIPPED' afterwards. This can be a huge performance hit and even max out your servers RAM depending on how big those tables are. I think what you're really looking for there is this:

    $Customer->Equipment()->where('SNStatus', 'SHIPPED')->get()

    By calling on the actual Equipment() method rather than the dynamic property, you're telling Eloquent that you're not quite ready for it to execute the query yet, because you're still appending conditions to it.

    (Also just as a side-note, your naming-convention hurts my OCD a little bit, methods should always be "camelCased". Only class names have their first letter capitalized.)


    So... back to the question you actually asked, and including an understanding of the difference between Model::where() and Collection::where(), what we have is something like this:

    $resutls = $Customer->Equipment()->with(['Part'])->where('SNStatus', 'SHIPPED')->get();
    

    Since you wanted to specify a couple fields within the Parts table that you actually care about, you can use a constrained eager-load

    $resutls = $Customer->Equipment()->with(['Part' => function (Illuminate\Database\Eloquent\Builder $query) {
        $query->select([
            'PartNum',  //Per Equipment::Part(), This needs to be there for the relation to be mated with its parent
            'ClassID',
            'PartDescription'
        ]);
        // Since PHP always handles objects by-reference, you don't actually need to return $query after having altered it here.
    }])->where('SNStatus', 'SHIPPED')->get();
    

    This will give you a nested Part object with just the fields you care about on each Equipment model element within the Eloquent\Collection results.

    As for how to handle these results within your blade file, I'll differ to Matei Mihai on that, I think that answer is pretty good.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?