作用域函数中的 Laravel ORM 调用关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22944335/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 09:20:03  来源:igfitidea点击:

Laravel ORM call relationship in scope function

phpormlaraveleloquent

提问by yveslebeau

I am trying to load a relationship from my customer table into my orders table but every time I try I keep getting this error:

我试图将客户表中的关系加载到我的订单表中,但每次尝试时我都会收到此错误:

Symfony \ Component \ Debug \ Exception \ FatalErrorException Call to a member function where() on a non-object

Symfony \ Component \ Debug \ Exception \ FatalErrorException 调用非对象上的成员函数 where()

Here is my model for the orders

这是我的订单模型

class Orders extends Eloquent
{
    protected $softDelete = true;

    public function order_items()
    {
        return $this->hasMany('Order_item');
    }

    public function customer()
    {
        return $this->hasOne('Customer', 'id', 'customer_id');
    }

    public function client()
    {
        return $this->hasOne('Client', 'id', 'client_id');
    }

    public function billingAddress()
    {
        if($this->client()->first() != null)
        {
            return $this->client()->getBillingAddress($this->billing_address_id);
        }
        else
        {
            return $this->customer()->getBillingAddress($this->billing_address_id);
        }
    }
}

Here is my customer model

这是我的客户模型

class Customer extends Eloquent
{
    protected $softDelete = true;

    public function order()
    {
        $this->belongsTo('Orders');
    }

    public function addresses()
    {
        $this->hasMany('Customeraddress', 'id', 'customer_id');
    }

    public function scopeGetBillingAddress($query, $addressId)
    {
        return $this->addresses()
                    ->where('id', '=', $addressId)
                    ->where('type', '=', 'billing');
    }

    public function scopeGetShippingAddress($query, $addressId)
    {
        return $this->addresses()
                    ->where('id', '=', $addressId)
                    ->where('type', '=', 'shipping');
    }
}

And finally here is my customeraddress model:

最后这是我的 customeraddress 模型:

class Customeraddress extends Eloquent
{
    protected $table = "customer_addresses";
    protected $softDelete = true;

    public function customer()
    {
        $this->belongsTo('Customer');
    }
}

Now I am trying to run this on my controller to get the order address but I keep getting errors. How would I be able to do that via Eloquent relationship and scope function?

现在我试图在我的控制器上运行它以获取订单地址,但我不断收到错误消息。我怎样才能通过 Eloquent 关系和作用域函数做到这一点?

$address = Orders::find(21)->billingAddress()->first();
echo $address->street;

回答by Jarek Tkaczyk

Change this one:

改变这一点:

public function addresses()
{
    // $this->hasMany('Customeraddress', 'id', 'customer_id'); // wrong order of keys
    return $this->hasMany('Customeraddress', 'customer_id', 'id');
}

and these two

而这两个

// edit: Order is a child of customer and client so:
public function customer()
{
    //return $this->hasOne('Customer', 'customer_id', 'id');
    return $this->belongsTo('Customer', 'customer_id', 'id'); // customer_id and id are redundant bu I leave it for clarity
}

public function client()
{
    //return $this->hasOne('Client', 'client_id', 'id');
    return $this->belongsTo('Client', 'client_id', 'id'); // same here
}

And by the way, this one is dangerous :)

顺便说一句,这个很危险:)

public function billingAddress()
{
    // This line results in db query everytime you call billingAddress 
    // Unless you cache the query, it's overkill
    if($this->client()->first() != null)

    // instead use:
    if($this->client != null)

    {
        return $this->client()->getBillingAddress($this->billing_address_id);
    }
    else
    {
        return $this->customer()->getBillingAddress($this->billing_address_id);
    }
}

change scopes to accessors:

将范围更改为访问器:

public function getBillingAddressAttribute($addressId)
{
    return $this->addresses()
                ->where('id', '=', $addressId)
                ->where('type', '=', 'billing')->first();
}

public function getShippingAddressAttribute($addressId)
{
    return $this->addresses()
                ->where('id', '=', $addressId)
                ->where('type', '=', 'shipping')->first();
}

// then you can call it like $customer->shippingAddress etc