Laravel query builder. Как сделать запрос короче?


Laravel query builder. Как сделать запрос короче?

06.09.2020 10:27:11 Просмотров 32 Источник

Мне нужно подготовить данные для таблиц данных, и мне нужно подсчитать общее количество отфильтрованных данных запроса, но я не могу сделать это только с одним запросом из-за лимита, поэтому я должен сделать почти тот же запрос, но без опции лимита для разбиения на страницы, и это делает объем моего кода 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);

}
У вопроса есть решение - Посмотреть?

Ответы - Laravel query builder. Как сделать запрос короче? / Laravel query builder. How to make the query shorter?

Является ответом!
lagbox

06.09.2020 10:42:22

Вы можете держать ту часть запроса, которая одинакова между ними, как конструктор, и запускать из нее оба запроса, если чувствуете, что вам нужны оба этих запроса:

$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()

usrNotFound

06.09.2020 11:46:56

Вы можете использовать clone для дублирования запроса, а затем запустить его с различными операторами 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();
Помочь в развитии проекта:
Закрыть X