在 laravel 中动态填充下拉列表的有效方法

Efficient way to populate drop-down dynamically in laravel

我有多个数据库表,每个表都填充一个下拉列表,关键是每个下拉列表都会影响下一个下拉列表。

我的意思是,如果我 select 第一个下拉列表中的一个项目,下一个下拉列表值会在 selected 项目上发生变化,这意味着它们是相关的,并且它们会在每个下拉项目变化时动态填充.

我知道这效率不高,需要重构,所以我很乐意向我指出填充这些下拉菜单的正确方法。

这是控制器代码:

<?php

use App\Http\Controllers\Controller;
use App\Models\County;
use App\Models\OutDoorMedia;
use App\Models\Province;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;


class FiltersController extends Controller
{
    protected static $StatusCode = 0;
    protected static $Msg = '';
    protected static $Flag = false;

    public function index(Request $request)
    {

        try {
            $validator = Validator::make($request->all(), [
                'province_id' => 'exists:province,id',
                'county_id' => 'exists:county,id',
                'media_type' => Rule::in([MEDIA_TYPE_BILLBOARD, MEDIA_TYPE_OUTDOOR_MONITOR, MEDIA_TYPE_INDOOR_MONITOR, MEDIA_TYPE_STAND, MEDIA_TYPE_STRABOARD, MEDIA_TYPE_BRAND_BOARD]),
                'media_status' => Rule::in([MEDIA_STATUS_AVAILABLE, MEDIA_STATUS_NEGOTIATING, MEDIA_STATUS_ASSIGNED, MEDIA_STATUS_ARCHIVE]),
                'category_id' => 'exists:category_list,id',
            ]);

            if ($validator->fails()) {
                abort(400, $validator->errors()->first());
            } else {
                //############################# Input Filters ####################################
                $province_id = $request->has('province_id') ? $request->province_id : null;
                $county_id = $request->has('county_id') ? $request->county_id : null;

                $media_type = $request->has('media_type') ? $request->media_type : null;
                $location = $request->has('location') ? $request->location : null;
                $media_status = $request->has('media_status') ? $request->media_status : null;


                $category_id = $request->has('category_id') ? $request->category_id : null;

                //this flag is for detecting if user is requesting from "advertiser my order" to ignore some concitions
                $advertiser_my_orders = ($request->has('my_orders') && $request->my_orders == 'true') ? true : false;

                $province_ids = [];
                $county_ids = [];

                //############################# Media Owner Filters ####################################
                //offline section filters
                if (!is_null($province_id) && Province::whereId($request->province_id)->exists()) {

                    //check correction of county id
                    if (!is_null($county_id) && County::whereId($county_id)->whereProvinceId($province_id)->exists()) {

                        $media_owner_ODM_Provinces = Province::whereHas('media')->get()->toArray();

                        $media_owner_ODM_Provinces_Counties = County::whereProvinceId($province_id)
                            ->whereHas('county_media')->get()->toArray();

                        foreach ($media_owner_ODM_Provinces as $key => $province) {
                            if ($province['id'] == $province_id) {
                                $media_owner_ODM_Provinces[$key]['county'] = $media_owner_ODM_Provinces_Counties;
                            }
                        }

                        $media_owner_ODM_locations = OutDoorMedia::whereProvinceId($province_id)->whereCountyId($county_id)->groupBy('location')->pluck('location')->toArray();

                        $media_owner_ODM_media_types = OutDoorMedia::whereProvinceId($province_id)->whereCountyId($county_id)->whereIn('location', $media_owner_ODM_locations)->groupBy('media_type')->pluck('media_type')->toArray();

                        $media_owner_ODM_media_Status = OutDoorMedia::whereProvinceId($province_id)->whereCountyId($county_id)->whereIn('media_type', $media_owner_ODM_media_types)->groupBy('status')->pluck('status')->toArray();

                    } else {
                        $media_owner_ODM_Provinces = Province::whereHas('media')->with(['county' => function ($query) {
                            $query->whereHas('county_media');
                        }])->get()->toArray();

                        $media_owner_ODM_locations = OutDoorMedia::whereProvinceId($province_id)->groupBy('location')->pluck('location')->toArray();

                        $media_owner_ODM_media_types = OutDoorMedia::whereProvinceId($province_id)->whereIn('location', $media_owner_ODM_locations)->groupBy('media_type')->pluck('media_type')->toArray();

                        $media_owner_ODM_media_Status = OutDoorMedia::whereProvinceId($province_id)->whereIn('media_type', $media_owner_ODM_media_types)->groupBy('status')->pluck('status')->toArray();
                    }

                } else {
                    $media_owner_ODM_Provinces = Province::whereHas('media')->with(['county' => function ($query) {
                        $query->whereHas('county_media');
                    }])->get()->toArray();

                    foreach ($media_owner_ODM_Provinces as $province) {
                        $province_ids[] = $province['id'];
                        foreach ($province['county'] as $county) {
                            $county_ids[] = $county['id'];
                        }
                    }

                    $media_owner_ODM_locations = OutDoorMedia::whereIn('province_id', $province_ids)->whereIn('county_id', $county_ids)->groupBy('location')->pluck('location')->toArray();

                    $media_owner_ODM_media_types = OutDoorMedia::whereIn('province_id', $province_ids)->whereIn('county_id', $county_ids)->whereIn('location', $media_owner_ODM_locations)->groupBy('media_type')->pluck('media_type')->toArray();

                    $media_owner_ODM_media_Status = OutDoorMedia::whereIn('province_id', $province_ids)->whereIn('county_id', $county_ids)->whereIn('media_type', $media_owner_ODM_media_types)->groupBy('status')->pluck('status')->toArray();
                }

                $media_owner_offline = [
                    'provinces' => $media_owner_ODM_Provinces,
                    'media_status' => $media_owner_ODM_media_Status,
                    'location' => $media_owner_ODM_locations,
                    'media_type' => $media_owner_ODM_media_types,
                ];

                $filters['media_owner']['offline'] = $media_owner_offline;

                self::$StatusCode = 200;
                self::$Msg = $filters;
                self::$Flag = true;
            }
        } catch (\Exception $e) {
            //=========== Get Error Exception Message ============
            self::$StatusCode = 400;
            self::$Msg = $e->getMessage();
            self::$Flag = false;
            return $this->CustomeJsonResponse(self::$Flag, self::$StatusCode, self::$Msg);
            //=========== Get Error Exception Message ============
        } finally {
            return $this->CustomeJsonResponse(self::$Flag, self::$StatusCode, self::$Msg);
        }
    }
}

仅供参考:我正在使用 laravel 5.3 框架。

以下是您应该注意的事项。 首先,如果您验证了 province_id,那么就没有必要在您的代码中仔细检查它。所以你应该删除 Province::whereId($request->province_id)->exists()

第二个是,Laravel 有 ->when eloquent 方法可以帮助您减少空值的 if else 语句,如果给定参数有空值,它不会影响询问。 https://laravel.com/docs/5.8/queries#conditional-clauses

第三,我建议您使用Laravel 资源来转换您从API 中的数据库中获取的数据。 https://laravel.com/docs/5.8/eloquent-resources

这是你的一小部分代码的更好版本,我认为有了建议的提示和这段代码,你可以重构它:

class TestController extends Controller
{
    const DEFAULT_COUNTRY_ID = '10';

    public $request;

    public function something(Request $request)
    {
        //  Put Validations ...

        $this->request = $request;

        OutDoorMedia::when('province_id', function ($query) {
            return $query->where('province_id', $this->request->province_id);
        })
        ->when('country_id', function ($query) {
            // if country_id exists
            return $query->where('country_id', $this->request->country_id);
        }, function ($query) {
            // else of above if (country_id is null ...)
            return $query->where('country_id', self::DEFAULT_COUNTRY_ID);
        })
        ->get();
    }
}

这只是一个示例,您可以使用这种方式来重构您的代码库。