Laravel 查询生成器。如何使查询更短?

Laravel query builder. How to make the query shorter?

我需要为数据表准备数据,我需要计算查询的过滤数据总量,但由于限制我不能只用一个查询来完成所以我几乎必须做相同的查询,但没有分页限制选项,它使我的代码量 x2。有没有可能让这段代码更短更漂亮?

public function data($request)
{
    $staff = auth()->user();
    $role = Role::find($staff->role_id)->alias;
    $isAdmin = $role == 'admin';

    $columns = ['id', 'name', 'shop', 'hash', 'status'];

    $limit = $request->input('length');
    $start = $request->input('start');
    $order = $columns[$request->input('order.0.column')];
    $directions = $request->input('order.0.dir');
    $searchValue = $request->input('search.value');

    $filters = explode(',', $request->input('columns.7.search')['value']);
    foreach ($filters as $key => $value) {
        if ($value !== "") {
            array_push($shops, $value);
        }
    }
    if ($searchValue) $filters[] = $searchValue;

    $nfcs = NfcMark::offset($start)->select('nfc_marks.*')
        ->leftJoin('shops as s', 's.id', 'nfc_marks.shop_id')
        ->when(!$isAdmin, function ($q) {
            $shop_ids = $this->shopRepository->shopsIdsByOwner(auth()->user()->id);
            return $q->whereIn('shop_id', $shop_ids);
        })
        ->when($searchValue, function ($q) use ($filters) {
            foreach ($filters as $filter) {
                $q->orWhere('shops.name', 'LIKE', '%' . $filter . '%');
            }
        })
        ->limit($limit)
        ->orderBy($order, $directions)
        ->get();

    $nfcs_count = NfcMark::query()
        ->leftJoin('shops as s', 's.id', 'nfc_marks.shop_id')
        ->when(!$isAdmin, function ($q) {
            $shop_ids = $this->shopRepository->shopsIdsByOwner(auth()->user()->id);
            return $q->whereIn('shop_id', $shop_ids);
        })
        ->when($searchValue, function ($q) use ($filters) {
            foreach ($filters as $filter) {
                $q->orWhere('shops.name', 'LIKE', '%' . $filter . '%');
            }
        })->get();

    $totalFiltered = count($nfcs_count);
    $totalData = $totalFiltered;

    $data = array();

    if (!empty($nfcs)) {
        foreach ($nfcs as $item) {
            $nestedData['id'] = $item->id;
            $nestedData['name'] = $item->name;
            $nestedData['shop'] = $item->shop_id;
            $nestedData['hash'] = $item->hash;
            $nestedData['status'] = $item->status;

            $data[] = $nestedData;
        }
    }

    $json_data = array(
        "draw" => intval($request->input('draw')),
        "recordsTotal" => intval($totalData),
        "recordsFiltered" => intval($totalFiltered),
        "data" => $data
    );

    return json_encode($json_data);

}

如果您觉得需要这两个查询,您可以保留与构建器相同的查询部分,运行 这两个查询:

$query = NfcMark::leftJoin('shops as s', 's.id', 'nfc_marks.shop_id')
    ->when(!$isAdmin, function ($q) {
        $q->whereIn(
            'shop_id',
            $this->shopRepository->shopsIdsByOwner(auth()->user()->id)
        );
    })
    ->when($searchValue, function ($q) use ($filters) {
        foreach ($filters as $filter) {
            $q->orWhere('shops.name', 'LIKE', '%' . $filter . '%');
        }
    });


$nfcs_count = $query->get();

$nfcs = $query->select('nfc_marks.*')
    ->offset($start)
    ->limit($limit)
    ->orderBy($order, $directions)
    ->get();

您也可以在不返回行的情况下获取计数,只需使用 count() 而不是 get()

您可以使用克隆来复制查询,然后 运行 使用不同的 where 语句。

$query1 = NfcMark::query()
        ->leftJoin('shops as s', 's.id', 'nfc_marks.shop_id')
        ->when(!$isAdmin, function ($q) {
            $shop_ids = $this->shopRepository->shopsIdsByOwner(auth()->user()->id);
            return $q->whereIn('shop_id', $shop_ids);
        })
        ->when($searchValue, function ($q) use ($filters) {
            foreach ($filters as $filter) {
                $q->orWhere('shops.name', 'LIKE', '%' . $filter . '%');
            }
        })

$query2 = clone $query1;


$nfcs_count = $query1->get() //or $query1->count();
$$nfcs = $query2
        ->limit($limit)
        ->orderBy($order, $directions)
        ->get();