How to get multiple joined data in one Laravel DB

2019-07-22 05:34发布

Update 3 (Solved but not optimal)

There is a way to hack the result:

public function loadRouteData($day, $week_nr, $year){
        $route_data = Facturatie_Invoice::with('customer', 'invoice_lines')
        ->whereHas('route_manager', function ($query) use ($week_nr, $year) {
            $query->where(['week_nr' => $week_nr,
                           'year' => $year]);
        })
        ->where('day', $day)
        ->get();

        foreach($route_data as $rd){
            for($i = 0; $i < count($rd->invoice_lines); $i++){
                $product = DB::table('facturatie_product')->where('id', $rd->invoice_lines[$i]->product_id)->first();
                $rd->invoice_lines[$i]->product = $product;
            }
        }
        return $route_data;
    }

I don't think this is the most optimal way so if any of you know a better method please let me know.

For details and things I tried see below.


I have the following ERD:

My ERD

Now what i want to do is get Facturatie_Route_Manager with:

Facturatie_Invoice
Facturatie_Customer
Facturatie_Invoice_Line
Facturatie_Product

Now when i try the following:

public function loadRouteData($day, $week_nr, $year){
    $route_data = DB::table('facturatie_route_manager')
    ->join('facturatie_invoice', 'facturatie_route_manager.invoice_id','=','facturatie_invoice.id')
    ->join('facturatie_customer', 'facturatie_invoice.customer_id','=','facturatie_customer.id')
    ->where(['facturatie_invoice.day' => $day,
             'facturatie_route_manager.week_nr' => $week_nr,
             'facturatie_route_manager.year' => $year])
    ->get();
    return $route_data;
}

I get duplicate records for route manager because each new invoice line don't get added to the same record but makes a new record instead. Also because i don't get the desired result i'm not including Facturatie_Product here yet.

Any ideas? I'm using Laravel 5+.

I've tried using models from Facturatie_Route_Manager but can't seem to refer Facturatie_Invoice id to Facturatie_Invoice_Line invoice_id starting at model Facturatie_Route_Manager. I would prefer not using joins if possible.


Update 1

public function loadRouteData($day, $week_nr, $year){
        $route_data = Facturatie_Route_Manager::whereHas('invoice', function ($query) use ($day) {
            $query->where('day', $day);
        })
        ->where(['week_nr' => $week_nr,
                 'year' => $year])
        ->get();
        return $route_data;
    }

Now still need link between facturatie_invoice and facturatie_invoice_line and facturatie_invoice_line and facturatie_product.

Model Facturatie_Route_Manager

class Facturatie_Route_Manager extends Model
{
    protected $table = 'facturatie_route_manager';

    public function invoice(){
        return $this->hasOne('App\Facturatie_Invoice', 'id', 'invoice_id');
    }
}

Update 2

Maybe it's easier to look from model Facturatie_Invoice because it has a one to one relationship with Facturatie_Route_Manager. This code is getting close to the end result:

public function loadRouteData($day, $week_nr, $year){
        $route_data = Facturatie_Invoice::with('customer', 'invoice_lines')
        ->whereHas('route_manager', function ($query) use ($week_nr, $year) {
            $query->where(['week_nr' => $week_nr,
                           'year' => $year]);
        })
        ->where('day', $day)
        ->get();
        return $route_data;
    }

Only still need a link between Facturatie_Invoice_Line - product_id and Facturatie_Product - id

Model Facturatie_Invoice

class Facturatie_Invoice extends Model
{
    protected $table = 'facturatie_invoice';

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

    public function invoice_lines()
    {
        return $this->hasMany('App\Facturatie_Invoice_Line', 'invoice_id', 'id');
    }

    public function route_manager()
    {
        return $this->hasOne('App\Facturatie_Route_Manager', 'invoice_id', 'id');
    }
}

0条回答
登录 后发表回答