*/ trait DataTable { public function getDataTable(Request $request, string $table, string $primaryKey, array $columns = []) { $query = DB::table($table); $data = $this->limit($query, $request); $data = $this->order($data, $request, $columns); $data = $this->filter($data, $request, $columns); $recordsFiltered = $this->filter($query, $request, $columns)->count($primaryKey); $recordsTotalQuery = clone $query; $recordsTotal = $recordsTotalQuery->count($primaryKey); $rows = $data->get(); $rows = $rows->map(fn ($item) => (array) $item)->toArray(); $rows = $this->createOutput($columns, $rows); return [ 'draw' => (int) $request->get('draw', 0), 'recordsTotal' => $recordsTotal, 'recordsFiltered' => $recordsFiltered, 'data' => $rows, ]; } protected function createOutput(array $columns, array $data) { $out = []; for ($i = 0, $ien = count($data); $i < $ien; $i++) { $row = []; for ($j = 0, $jen = count($columns); $j < $jen; $j++) { $column = $columns[$j]; // Is there a formatter? if (isset($column['formatter'])) { if (empty($column['db'])) { $row[$column['dt']] = $column['formatter']($data[$i]); } else { $row[$column['dt']] = $column['formatter']($data[$i][$column['db']], $data[$i]); } } else { if (!empty($column['db'])) { $row[$column['dt']] = $data[$i][$columns[$j]['db']]; } else { $row[$column['dt']] = ""; } } } $out[] = $row; } return $out; } public function limit(Builder $query, Request $request) { $query = clone $query; $offset = $request->get('start', 0); $limit = $request->get('length', 10); $query->limit($limit)->offset($offset); return $query; } public function order(Builder $query, Request $request, array $columns = []) { $query = clone $query; $order = $request->get('order', []); if (is_array($order) && count($order) == 0) { return $query; } $orderBy = []; $dtColumns = $this->pluck($columns, 'dt'); for ($i = 0, $ien = count($order); $i < $ien; $i++) { // Convert the column index into the column data property $columnIdx = intval($request['order'][$i]['column']); $requestColumn = $request['columns'][$columnIdx]; $columnIdx = array_search($requestColumn['data'], $dtColumns); $column = $columns[$columnIdx]; if ($requestColumn['orderable'] == 'true') { $dir = $request['order'][$i]['dir'] === 'asc' ? 'ASC' : 'DESC'; $orderBy[] = [$column['db'], $dir]; } } if (count($orderBy)) { foreach ($orderBy as $val) { [$columnName, $direction] = $val; } $query->orderBy($columnName, $direction); } return $query; } public function filter(Builder $query, Request $request, array $columns = []) { $query = clone $query; $globalSearch = []; $columnSearch = []; $dtColumns = $this->pluck($columns, 'dt'); $search = $request->filled('search') ? $request->get('search') : []; if ($request->has('search') && isset($search['value']) && $search['value'] != '') { $str = $search['value']; for ($i = 0, $ien = count($request['columns']) ; $i < $ien ; $i++) { $requestColumn = $request['columns'][$i]; $columnIdx = array_search($requestColumn['data'], $dtColumns); $column = $columns[ $columnIdx ]; if ($requestColumn['searchable'] == 'true') { if(!empty($column['db'])) { $globalSearch[] = [$column['db'], 'ilike', '%'.$str.'%']; } } } } // Individual column filtering if ($request->has('columns')) { $reqColumns = $request->get('columns'); for ($i = 0, $ien = count($reqColumns) ; $i < $ien ; $i++) { $requestColumn = $reqColumns[$i]; $columnIdx = array_search($requestColumn['data'], $dtColumns); $column = $columns[ $columnIdx ]; $str = $requestColumn['search']['value']; if ($requestColumn['searchable'] == 'true' && $str != '') { if(!empty($column['db'])) { $columnSearch[] = [$column['db'], 'ilike', '%' . $str . '%']; } } } } // Combine the filters into a single string if (count($globalSearch)) { $query->where(function (Builder $query) use ($globalSearch) { foreach ($globalSearch as $val) { [$column, $op, $value] = $val; $query->orWhere($column, $op, $value); } }); } if (count($columnSearch)) { foreach ($columnSearch as $val) { [$column, $op, $value] = $val; $query->where($column, $op, $value); } } return $query; } /** * Pull a particular property from each assoc. array in a numeric array, * returning and array of the property values from each item. * * @param array $a Array to get data from * @param string $prop Property to read * @return array Array of property values */ public function pluck(array $a, string $prop): array { $out = []; for ($i = 0, $len = count($a); $i < $len; $i++) { if (empty($a[$i][$prop])) { continue; } //removing the $out array index confuses the filter method in doing proper binding, //adding it ensures that the array data are mapped correctly $out[$i] = $a[$i][$prop]; } return $out; } public function flatten(mixed $a, string $join = ' AND '): string { if (! $a) { return ''; } elseif ($a && is_array($a)) { return implode($join, $a); } return $a; } }