Skip to main content
Became Hot Network Question
Changed question title to state the code's purpose
Link
Greg Burghardt
  • 5.9k
  • 13
  • 26

How to avoid duplication of code when processing query parameters on an optimally logical option? Laravel controller method that searches jobs using variable criteria

changed title
Link

How to avoid code duplication and optimizeof code when processing query parameters on an optimally logical option?

Source Link

How to avoid code duplication and optimize code?

I have custom code where I check request params for existing and make query to database with model

public function search(Request $request)
{
    $position = $request->get("position") ?? null;
    $location = $request->get("location") ?? null;
    $employment = $request->get("employment") ?? null;

    $jobsBy = null;
    $jobs = null;
    if($position) {
        $jobs = Job::where('title', 'LIKE', '%'.$position.'%');

        if($location) {
            $locations = [];
            if(is_array($location)) {
                foreach ($location as $name) {
                    $locations[] = $name;
                }
            } else $locations[] = $location;
            $jobs = $jobs->whereMetaIn("location", $locations);
        }

        if($employment) {
            $employments = [];
            if(is_array($employment)) {
                foreach ($employment as $name) {
                    $employments[] = $name;
                }
            } else $employments[] = $employment;
            $jobs = $jobs->withAnyTag($employments);
        }

        if($jobs->get()->count()) $jobsBy = "position";
    }
    if($location && $jobsBy === null) {
        $locations = [];
        if(is_array($location)) {
            foreach ($location as $name) {
                $locations[] = $name;
            }
        } else $locations[] = $location;
        $jobs = Job::whereMetaIn('location', $locations);

        if($employment) {
            $employments = [];
            if(is_array($employment)) {
                foreach ($employment as $name) {
                    $employments[] = $name;
                }
            } else $employments[] = $employment;
            $jobs = $jobs->withAnyTag($employments);
        }

        if($jobs->get()->count()) $jobsBy = "location";
    }
    if($employment && $jobsBy === null) {
        $employments = [];
        if(is_array($employment)) {
            foreach ($employment as $name) {
                $employments[] = $name;
            }
        } else $employments[] = $employment;
        $jobs = Job::withAnyTag($employments);

        if($jobs->get()->count()) $jobsBy = "employment";
    }

    if($jobs == null || !$jobs->get()->count()) {
        $jobs = Job::where("status", '<', 2);
        $jobsBy = "latest";
    }

    if(isset($jobs) && $jobs instanceof \Illuminate\Database\Eloquent\Builder && $jobsBy != null) {
        $IDS = $jobs->where('status', '<', 2)->pluck('id');

        $partnerCompanyJobs = Job::with(['user' => function($user) {
            $user->without('roles', 'companies')
                 ->select('id', 'name');
        }])->withCount('views')->where('type', 0)
                               ->whereIn('id', $IDS)
                               ->where('status', 1)
                               ->orderBy('updated_at', 'DESC')
                               ->get();

        $companyJobs = Job::with(['user' => function($user) {
            $user->without('roles', 'companies')
                 ->select('id', 'name');
        }])->withCount('views')->where('type', 1)
                               ->where('status', 1)
                               ->whereIn('id', $IDS)
                               ->orderBy('updated_at', 'DESC')
                               ->get();

        $sampleJobs = Job::with(['user' => function($user) {
            $user->without('roles', 'companies')
                 ->select('id', 'name');
        }])->withCount('views')->where('type', 2)
                               ->where('status', 1)
                               ->whereIn('id', $IDS)
                               ->orderBy('updated_at', 'DESC')
                               ->get();

        $somonJobs = Job::withCount('views')->whereIn('type', [3,4])
                               ->whereIn('id', $IDS)
                               ->where('status', 1)
                               ->orderBy('updated_at', 'DESC')
                               ->get();

        $jobs = $partnerCompanyJobs->merge($companyJobs)
                               ->merge($sampleJobs)
                               ->merge($somonJobs);

        if(count($jobs)) {
            $page = $request->page ?? 1;
            $items = $jobs->forPage($page, 5);
            return response()->json([          
                'data' => JobResource::collection($items),
                'total' => count($jobs),
                'jobsBy' => $jobsBy
            ]);
        }
    }

    return response()->json([          
        'data' => [],
        'total' => 0,
        'jobsBy' => ""
    ]);
}

How can I avoid duplication of code here and create an optimal database query in my case? I have a problem processing request parameters. Because of this, much is duplicated in my code. How can I fix such a case?