phplaravelmany-to-manylaravel-8relationship

make better code in laravel many to many relation


hi i wrote this code and it works just fine but i think its not the best way to do it!

i want to get all the jobs for 1 company.

each company can have many addresses and each address can have many jobs

here is my code:

 $company = Company::find($id)->with('addresses.jobDetails.job')->first();
    $jobs = [];
    foreach ($company->addresses as $address) {
        foreach ($address->jobDetails as $detail) {
            array_push($jobs, [
                'id' => $detail->job->id,
                'title' => $detail->job->title,
                'country' => $detail->job->country,
                'city' => $detail->job->city,
                'type' => $detail->job->type,
                'work_types' => JobType::where('job_id',$detail->job->id)->pluck('title'),
                'income' => $detail->income,
            ]);
        }
    }
    return $jobs;

can anyone help me to change this to better code please

thank you in advance


Solution

  • You do the opposite and start with JobDetails

    $jobDetails = JobDetail::whereHas('address.company', function($companyQuery) use($id) {
        $companyQuery->where('id', $id);
    })->whereHas('jobs', function($jobQuery) {
        $jobQuery->where('is_active', 1);
    })->with('jobs')->get();
    
    foreach ($jobDetails as $detail) {
        array_push($jobs, [
            'id' => $detail->job->id,
            'title' => $detail->job->title,
            'country' => $detail->job->country,
            'city' => $detail->job->city,
            'type' => $detail->job->type,
            'work_types' => JobType::where('job_id',$detail->job->id)->pluck('title'),
            'income' => $detail->income,
        ]);
    }
    
    return $jobs;
    

    EDIT:

    In your query

    Company::find($id)->with('addresses.jobDetails.job')->first();
    

    You run 4 queries with eager loading. one for each model. You can check in the result that you got that all the data is present in the variable $company.

    The example I gave you it runs only two queries, the first one (job_details) will use joins to filter the Job results by the id of the companies table (you can make it faster by using the field company_id in the addresses table) The second one is for the jobs relation using eager loading.