diff --git a/src/Common/EntityField.php b/src/Common/EntityField.php index 1af3f96..52e218e 100644 --- a/src/Common/EntityField.php +++ b/src/Common/EntityField.php @@ -27,7 +27,7 @@ class EntityField # Must use REFLECTION before throwing this value. # Should first check if it's a relation field, and if it is, # it's real key must be returned (PK usually) - return $useAlias ? "{$this->alias}.\"{$this->name}\"" : "\"{$this->name}\""; + return $useAlias ? "{$this->alias}.`{$this->name}`" : "`{$this->name}`"; } public static function isScalarType($type) : bool diff --git a/src/Common/PdoObject.php b/src/Common/PdoObject.php index fc6c33e..e9af73a 100644 --- a/src/Common/PdoObject.php +++ b/src/Common/PdoObject.php @@ -8,8 +8,6 @@ use PDO, class PdoObject extends PDO { public function select(string $sql, array $parameters = []): PDOStatement { - # var_dump($sql, $parameters); die(); - try { if (false !== ( $statement = $this->prepare($sql) )) { $statement = $this->execute($statement, $parameters, false); @@ -23,8 +21,6 @@ class PdoObject extends PDO { } public function runQuery(string $sql, array $parameters = []): ? PDOStatement { - # dump($sql, $parameters); return null; - try { if (false !== ( $statement = $this->prepare($sql) )) { return $this->execute($statement, $parameters, true); @@ -50,8 +46,9 @@ class PdoObject extends PDO { } return $statement; - } else { - throw new PDOException('Could not begin transaction or given statement is invalid.'); + } + else { + throw new \PDOException($statement->errorCode() . " - " . json_encode($statement->errorInfo())); } } catch (\PDOException $e) { $this->rollback(); diff --git a/src/EntityTrait.php b/src/EntityTrait.php index 0c33a76..089e30a 100644 --- a/src/EntityTrait.php +++ b/src/EntityTrait.php @@ -153,8 +153,21 @@ trait EntityTrait { foreach($entityResolver->fieldList() as $key => $field) { $annotation = $entityResolver->searchFieldAnnotation($key, new Field() ); - if ( isset($this->$key) ) { - $dataset[ $annotation->name ?? $key ] = is_object($this->$key) ? Ulmus::convertObject($this->$key) : $this->$key; + if ( isset($this->$key) ) { + $realKey = $annotation->name ?? $key; + + switch (true) { + case is_object($this->$key): + $dataset[$realKey] = Ulmus::convertObject($this->$key); + break; + + case is_array($this->$key): + $dataset[$realKey] = Ulmus::encodeArray($this->$key); + break; + + default: + $dataset[$realKey] = $this->$key; + } } elseif ( $field['nullable'] ) { $dataset[ $annotation->name ?? $key ] = null; diff --git a/src/Query/Fragment.php b/src/Query/Fragment.php index d17c3de..7754a2c 100644 --- a/src/Query/Fragment.php +++ b/src/Query/Fragment.php @@ -10,6 +10,6 @@ abstract class Fragment { protected function renderSegments(array $segments, string $glue = " ") : string { - return implode($glue, array_filter($segments)); + return implode($glue, array_filter($segments, function($i) { return ! is_null($i) && $i !== false && $i !== ""; })); } } diff --git a/src/Query/Insert.php b/src/Query/Insert.php index 6aac5bf..124ca48 100644 --- a/src/Query/Insert.php +++ b/src/Query/Insert.php @@ -31,6 +31,6 @@ class Insert extends Fragment { protected function renderTable() : string { - return $this->table; + return "`$this->table`"; } } diff --git a/src/Query/Offset.php b/src/Query/Offset.php index 5b84d2b..b9d8d7e 100644 --- a/src/Query/Offset.php +++ b/src/Query/Offset.php @@ -11,6 +11,7 @@ class Offset extends Fragment { public function set($offset) : self { $this->offset = $offset; + return $this; } diff --git a/src/Query/OrderBy.php b/src/Query/OrderBy.php index b88a1d4..c4143af 100644 --- a/src/Query/OrderBy.php +++ b/src/Query/OrderBy.php @@ -10,12 +10,14 @@ class OrderBy extends Fragment { public function set(array $order) : self { $this->orderBy = $order; + return $this; } public function add(string $field, ? string $direction = null) : self { $this->orderBy[] = [ $field, $direction ]; + return $this; } @@ -23,6 +25,7 @@ class OrderBy extends Fragment { { $list = array_map(function($item) { list($field, $direction) = $item; + return $field . ( $direction ? " $direction" : "" ); }, $this->orderBy); diff --git a/src/Query/Update.php b/src/Query/Update.php index d825a40..dfd0050 100644 --- a/src/Query/Update.php +++ b/src/Query/Update.php @@ -24,12 +24,12 @@ class Update extends Fragment { 'UPDATE', ( $this->priority ?? false ), ( $this->ignore ? 'IGNORE' : false ), - $this->table, + $this->renderTable(), ]); } protected function renderTable() : string { - return $this->table; + return "`$this->table`"; } } diff --git a/src/Query/Values.php b/src/Query/Values.php index b7e8416..45fc348 100644 --- a/src/Query/Values.php +++ b/src/Query/Values.php @@ -33,7 +33,7 @@ class Values extends Fragment { public function render() : string { $this->queryBuilder->addValues($this->flattenRowsArray()); - + return $this->renderSegments([ 'VALUES', $this->renderParameterPlaceholders(), ]); diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 42865b5..800b731 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -165,7 +165,7 @@ class QueryBuilder $this->where = $where = new Query\Where($this); $this->push($where); } - + $this->conditionOperator = $operator; $where->add($field, $value, $operator, $condition, $not); diff --git a/src/Repository.php b/src/Repository.php index d5c8c2b..7de41a3 100644 --- a/src/Repository.php +++ b/src/Repository.php @@ -53,15 +53,11 @@ class Repository public function count() : int { - $this->select("count(*) as totalItem")->selectSqlQuery(); + $this->select("count(*)")->selectSqlQuery(); $this->finalizeQuery(); - - foreach(Ulmus::iterateQueryBuilder($this->queryBuilder, $this->adapter) as $entityData) { - return $entityData['totalItem']; - } - return 0; + return Ulmus::runQuery($this->queryBuilder, $this->adapter)->fetchColumn(0); } public function deleteOne() @@ -218,6 +214,15 @@ class Repository return $this; } + public function wheres(array $fieldValues, string $operator = Query\Where::OPERATOR_EQUAL) : self + { + foreach($fieldValues as $field => $value) { + $this->where($field, $value, $operator); + } + + return $this; + } + public function and($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self { return $this->where($field, $value, $operator); @@ -237,9 +242,9 @@ class Repository return $this; } - public function orNot($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self + public function orNot($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self { - $this->queryBuilder->notWhere($condition, Query\Where::CONDITION_OR, true); + $this->queryBuilder->notWhere($field, $value, $operator, Query\Where::CONDITION_OR, true); return $this; } @@ -289,11 +294,21 @@ class Repository public function notLike($field, $value) : self { - $this->queryBuilder->where($field, $value, Query\Where::OPERATOR_LIKE, Query\Where::CONDITION_AND, true); + $this->queryBuilder->notWhere($field, $value, Query\Where::OPERATOR_LIKE, Query\Where::CONDITION_AND, true); return $this; } + + public function likes(array $fieldValues) : self + { + foreach($fieldValues as $field => $value) { + $this->like($field, $value); + } + + return $this; + } + public function match() : self { @@ -316,10 +331,15 @@ class Repository public function groupBy() : self { - #$this->queryBuilder->groupBy(); return $this; } + public function groups(array $groups) : self + { + # foreach($this->groups) + return $this; + } + public function orderBy($field, ? string $direction = null) : self { $this->queryBuilder->orderBy($field, $direction); @@ -327,6 +347,16 @@ class Repository return $this; } + public function orders(array $orderList) : self + { + foreach($orderList as $field => $direction) { + $this->queryBuilder->orderBy($field, $direction); + } + + return $this; + } + + public function limit(int $value) : self { $this->queryBuilder->limit($value); @@ -362,9 +392,24 @@ class Repository return $this->where($primaryKeyField[$pkField]->name ?? $pkField, $value); } + public function filterServerRequest(SearchRequest\SearchRequestInterface $searchRequest) : self + { + $searchRequest->count = (clone $this)->wheres($searchRequest->wheres()) + ->likes($searchRequest->likes()) + ->orders($searchRequest->orders()) + ->groups($searchRequest->groups()) + ->count(); + + return $this->wheres($searchRequest->wheres()) + ->likes($searchRequest->likes()) + ->orders($searchRequest->orders()) + ->groups($searchRequest->groups()) + ->offset($searchRequest->offset()) + ->limit($searchRequest->limit()); + } + protected function collectionFromQuery() : EntityCollection { - $class = $this->entityClass; $entityCollection = new EntityCollection(); diff --git a/src/SearchRequest/SearchRequestInterface.php b/src/SearchRequest/SearchRequestInterface.php new file mode 100644 index 0000000..59b6d7a --- /dev/null +++ b/src/SearchRequest/SearchRequestInterface.php @@ -0,0 +1,17 @@ +count = $itemCount; + $this->page = $page; + } + + public function pageCount() : int + { + return ceil($this->count / $this->limit()); + } + + public function hasPagination() : int + { + return $this->pageCount() > 1; + } +} diff --git a/src/SearchRequest/SearchableInterface.php b/src/SearchRequest/SearchableInterface.php new file mode 100644 index 0000000..1df871f --- /dev/null +++ b/src/SearchRequest/SearchableInterface.php @@ -0,0 +1,11 @@ +closeCursor(); + $queryBuilder->reset(); return [ @@ -68,12 +69,17 @@ abstract class Ulmus { return ( static::$objectInstanciator ?? static::$objectInstanciator = new Entity\ObjectInstanciator() )->instanciate($type, $arguments); } - + public static function convertObject(object $obj) { return ( static::$objectInstanciator ?? static::$objectInstanciator = new Entity\ObjectInstanciator() )->convert($obj); } + public static function encodeArray(array $array) + { + return json_encode($array); + } + public static function registerAdapter(ConnectionAdapter $adapter, bool $default = false) : void { if ($default) {