8000 Datatables desteği eklendi · InitPHP/Database@9942427 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9942427

Browse files
committed
Datatables desteği eklendi
1 parent 10f857e commit 9942427

File tree

6 files changed

+308
-15
lines changed

6 files changed

+308
-15
lines changed

src/Database.php

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313

1414
namespace InitPHP\Database;
1515

16-
use InitPHP\Database\Utils\Pagination;
16+
use InitPHP\Database\Utils\{Pagination,
17+
Datatables};
1718
use \InitPHP\Database\Exceptions\{WritableException,
1819
ReadableException,
1920
UpdatableException,
@@ -475,10 +476,16 @@ public function createBatch(array $set)
475476
*/
476477
public function count(): int
477478
{
479+
$select = $this->_STRUCTURE['select'];
480+
$this->_STRUCTURE['select'][] = 'COUNT(*) AS row_count';
478481
$this->_deleteFieldBuild(false);
482+
$parameters = Parameters::get(false);
479483
$res = $this->query($this->_readQuery());
480-
481-
return $res->numRows();
484+
$count = $res->toArray()['row_count'] ?? 0;
485+
unset($res);
486+
Parameters::merge($parameters);
487+
$this->_STRUCTURE['select'] = $select;
488+
return $count;
482489
}
483490

484491
public function pagination(int $page = 1, int $per_page_limit = 10, string $link = '?page={page}'): Pagination
@@ -492,6 +499,11 @@ public function pagination(int $page = 1, int $per_page_limit = 10, string $link
492499
return new Pagination($res, $page, $per_page_limit, $total_row, $link);
493500
}
494501

502+
public function datatables(array $columns, int $method = Datatables::GET_REQUEST): string
503+
{
504+
return (new Datatables($this, $columns, $method))->__toString();
505+
}
506+
495507
/**
496508
* @param array $selector
497509
* @param array $conditions
@@ -650,6 +662,31 @@ public function all(int $limit = 100, int $offset = 0)
650662
->read();
651663
}
652664

665+
public function group(\Closure $group, string $logical = 'AND'): self
666+
{
667+
$logical = \str_replace(['&&', '||'], ['AND', 'OR'], \strtoupper($logical));
668+
if(!\in_array($logical, ['AND', 'OR'], true)){
669+
throw new \InvalidArgumentException('Logical operator OR, AND, && or || it could be.');
670+
}
671+
672+
$clone = clone $this;
673+
$clone->reset();
674+
675+
\call_user_func_array($group, [$clone]);
676+
677+
$where = $clone->_whereQuery();
678+
if($where !== ''){
679+
$this->_STRUCTURE['where'][$logical][] = '(' . $where . ')';
680+
}
681+
682+
$having = $clone->_havingQuery();
683+
if($having !== ''){
684+
$this->_STRUCTURE['having'][$logical][] = '(' . $having . ')';
685+
}
686+
unset($clone);
687+
return $this;
688+
}
689+
653690
public function onlyDeleted(): self
654691
{
655692
$this->_isOnlyDeletes = true;
@@ -667,12 +704,17 @@ public function _readQuery(): string
667704
if($this->getSchema() !== null){
668705
$this->table($this->getSchema());
669706
}
670-
707+
$where = $this->_whereQuery();
708+
if($where !== ''){
709+
$where = ' WHERE ' . $where;
710+
}else{
711+
$where = ' WHERE 1';
712+
}
671713
return 'SELECT '
672714
. (empty($this->_STRUCTURE['select']) ? '*' : \implode(', ', $this->_STRUCTURE['select']))
673715
. ' FROM ' . \implode(', ', $this->_STRUCTURE['table'])
674716
. (!empty($this->_STRUCTURE['join']) ? ' ' . \implode(', ', $this->_STRUCTURE['join']) : '')
675-
. $this->_whereQuery()
717+
. $where
676718
. $this->_havingQuery()
677719
. (!empty($this->_STRUCTURE['group_by']) ? ' GROUP BY ' . \implode(', ', $this->_STRUCTURE['group_by']) : '')
678720
. (!empty($this->_STRUCTURE['order_by']) ? ' ORDER BY ' . \implode(', ', $this->_STRUCTURE['order_by']) : '')
@@ -759,11 +801,17 @@ public function _updateQuery(array $data): string
759801
if($schemaID !== null && isset($data[$schemaID])){
760802
$this->where($schemaID, $data[$schemaID]);
761803
}
804+
$where = $this->_whereQuery();
805+
if($where !== ''){
806+
$where = ' WHERE ' . $where;
807+
}else{
808+
$where = ' WHERE 1';
809+
}
762810
return 'UPDATE '
763811
. (empty($this->_STRUCTURE['table']) ? $this->getSchema() : end($this->_STRUCTURE['table']))
764812
. ' SET '
765813
. \implode(', ', $update)
766-
. $this->_whereQuery()
814+
. $where
767815
. $this->_havingQuery()
768816
. $this->_limitQuery();
769817
}
@@ -812,22 +860,33 @@ public function _updateBatchQuery(array $data, $referenceColumn): string
812860
$update[] = $syntax;
813861
}
814862
$this->in($referenceColumn, $where);
815-
863+
$where = $this->_whereQuery();
864+
if($where !== ''){
865+
$where = ' WHERE ' . $where;
866+
}else{
867+
$where = ' WHERE 1';
868+
}
816869
return 'UPDATE '
817870
. (empty($this->_STRUCTURE['table']) ? $this->getSchema() : end($this->_STRUCTURE['table']))
818871
. ' SET '
819872
. \implode(', ', $update)
820-
. $this->_whereQuery()
873+
. $where
821874
. $this->_havingQuery()
822875
. $this->_limitQuery();
823876
}
824877

825878
public function _deleteQuery(): string
826879
{
880+
$where = $this->_whereQuery();
881+
if($where !== ''){
882+
$where = ' WHERE ' . $where;
883+
}else{
884+
$where = ' WHERE 1';
885+
}
827886
return 'DELETE FROM'
828887
. ' '
829888
. (empty($this->_STRUCTURE['table']) ? $this->getSchema() : end($this->_STRUCTURE['table']))
830-
. $this->_whereQuery()
889+
. $where
831890
. $this->_havingQuery()
832891
. $this->_limitQuery();
833892
}
@@ -865,10 +924,9 @@ private function _whereQuery(): string
865924
$isAndEmpty = empty($this->_STRUCTURE['where']['AND']);
866925
$isOrEmpty = empty($this->_STRUCTURE['where']['OR']);
867926
if($isAndEmpty && $isOrEmpty){
868-
return ' WHERE 1';
927+
return '';
869928
}
870-
return ' WHERE '
871-
. (!$isAndEmpty ? \implode(' AND ', $this->_STRUCTURE['where']['AND']) : '')
929+
return (!$isAndEmpty ? \implode(' AND ', $this->_STRUCTURE['where']['AND']) : '')
872930
. (!$isAndEmpty && !$isOrEmpty ? ' AND ' : '')
873931
. (!$isOrEmpty ? \implode(' OR ', $this->_STRUCTURE['where']['OR']) : '');
874932
}

src/Init.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@
3434
require_once __DIR__ . DIRECTORY_SEPARATOR . 'Raw.php';
3535
require_once __DIR__ . DIRECTORY_SEPARATOR . 'Result.php';
3636
require_once __DIR__ . DIRECTORY_SEPARATOR . 'Utils/Pagination.php';
37+
require_once __DIR__ . DIRECTORY_SEPARATOR . 'Utils/Datatables.php';

src/QueryBuilder.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ public function reset(): void
4343
$this->_STRUCTURE = self::STRUCTURE;
4444
}
4545

46+
public function importQB(array $structure): self
47+
{
48+
$this->_STRUCTURE = $structure;
49+
50+
return $this;
51+
}
52+
53+
public function exportQB(): array
54+
{
55+
return $this->_STRUCTURE;
56+
}
57+
58+
59+
4660
/**
4761
* @param string|Raw ...$columns
4862
* @return $this

src/Utils/Datatables.php

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
<?php
2+
/**
3+
* Utils/Datatables
4+
*
5+
* This file is part of InitPHP Database.
6+
*
7+
* @author Muhammet ŞAFAK <info@muhammetsafak.com.tr>
8+
* @copyright Copyright © 2022 Muhammet ŞAFAK
9+
* @license ./LICENSE MIT
10+
* @version 2.0.6
11+
* @link https://www.muhammetsafak.com.tr
12+
*/
13+
14+
namespace InitPHP\Database\Utils;
15+
16+
use InitPHP\Database\Database;
17+
18+
final class Datatables
19+
{
20+
21+
public const GET_REQUEST = 0;
22+
23+
public const POST_REQUEST = 1;
24+
25+
private Database $db;
26+
27+
private array $request = [];
28+
29+
private array $columns = [];
30+
31+
private int $total_row = 0;
32+
33+
private int $total_filtered_row = 0;
34+
35+
private array $results;
36+
37+
private int $draw = 0;
38+
39+
public function __construct(Database $db, $columns, $method = self::GET_REQUEST)
40+
{
41+
$this->db = $db;
42+
43+
switch ($method) {
44+
case self::GET_REQUEST:
45+
$this->request = $_GET ?? [];
46+
break;
47+
case self::POST_REQUEST:
48+
$this->request = $_POST ?? [];
49+
break;
50+
}
51+
$this->columns = $columns;
52+
53+
$this->total_row = $this->db->count();
54+
55+
$this->filterQuery();
56+
$this->orderQuery();
57+
$this->total_filtered_row = $this->db->count();
58+
$this->limitQuery();
59+
$this->results = $this->db->get()->toArray();
60+
61+
if(isset($this->request['draw'])){
62+
$this->draw = (int)$this->request['draw'];
63+
}
64+
}
65+
66+
public function __toString(): string
67+
{
68+
return \json_encode($this->getResults());
69+
}
70+
71+
public function getResults(): array
72+
{
73+
return [
74+
'draw' => $this->draw,
75+
'recordsTotal' => $this->total_row,
76+
'recordsFiltered' => $this->total_filtered_row,
77+
'data' => $this->output_prepare()
78+
];
79+
}
80+
81+
82+
private function orderQuery()
83+
{
84+
$columns = $this->columns;
85+
if(!isset($this->request['order'])){
86+
return;
87+
}
88+
$count = \count($this->request['order']);
89+
$dtColumns = $this->pluck($columns, 'dt');
90+
for($i = 0; $i < $count; ++$i){
91+
$columnId = \intval($this->request['order'][$i]['column']);
92+
$reqColumn = $this->request['columns'][$columnId];
93+
$columnId = \array_search($reqColumn['data'], $dtColumns);
94+
$column = $columns[$columnId];
95+
if(($reqColumn['orderable'] ?? 'false') != 'true' || !isset($column['db'])){
96+
continue;
97+
}
98+
$dir = ($this->request['order'][$i]['dir'] ?? 'asc') === 'asc' ? 'ASC' : 'DESC';
99+
$this->db->orderBy($column['db'], $dir);
100+
}
101+
}
102+
103+
private function filterQuery()
104+
{
105+
$columns = $this->columns;
106+
$dtColumns = $this->pluck($columns, 'dt');
107+
$str = $this->request['search']['value'] ?? '';
108+
if($str === '' || !isset($this->request['columns'])){
109+
return;
110+
}
111+
$columnsCount = \count($this->request['columns']);
112+
$this->db->group(function (Database $db) use ($str, $dtColumns, $columns, $columnsCount) {
113+
for ($i = 0; $i < $columnsCount; ++$i) {
114+
$reqColumn = $this->request['columns'][$i];
115+
$columnId = \array_search($reqColumn['data'], $dtColumns);
116+
$column = $columns[$columnId];
117+
if(empty($column['db'])){
118+
continue;
119+
}
120+
$db->orLike($column['db'], $str);
121+
}
122+
});
123+
if(isset($this->request['columns'])){
124+
for ($i = 0; $i < $columnsCount; ++$i) {
125+
$reqColumn = $this->request['columns'][$i];
126+
$columnId = \array_search($reqColumn['data'], $dtColumns);
127+
$column = $columns[$columnId];
128+
$str = $reqColumn['search']['value'] ?? '';
129+
if(($reqColumn['searchable'] ?? 'false') != 'true' || $str == '' || empty($column['db'])){
130+
continue;
131+
}
132+
$this->db->like($column['db'], $str);
133+
}
134+
}
135+
}
136+
137+
private function limitQuery()
138+
{
139+
if(isset($this->request['start']) && $this->request['length'] != -1){
140+
$this->db->offset((int)$this->request['start'])
141+
->limit((int)$this->request['length']);
142+
}
143+
}
144+
145+
private function output_prepare(): array
146+
{
147+
$out = [];
148+
$columns = $this->columns;
149+
$data = $this->results;
150+
$dataCount = \count($data);
151+
$columnCount = \count($columns);
152+
153+
for ($i = 0; $i < $dataCount; ++$i) {
154+
$row = [];
155+
156+
for ($y = 0; $y < $columnCount; ++$y) {
157+
$column = $columns[$y];
158+
if(isset($column['formatter'])){
159+
$row[$column['dt']] = \call_user_func_array($column['formatter'], (empty($column['db']) ? [$data[$i]] : [$data[$i][$column['db']], $data[$i]]));
160+
}else{
161+
$row[$column['dt']] = !empty($column['db']) ? $data[$i][$column['db']] : '';
162+
}
163+
}
164+
165+
$out[] = $row;
166+
}
167+
168+
169+
return 8F0C $out;
170+
}
171+
172+
private function pluck(array $array, string $prop): array
173+
{
174+
$out = [];
175+
$len = \count($array);
176+
for ($i = 0; $i < $len; ++$i) {
177+
if(empty($array[$i][$prop])){
178+
continue;
179+
}
180+
$out[$i] = $array[$i][$prop];
181+
}
182+
return $out;
183+
}
184+
185+
}

0 commit comments

Comments
 (0)
0