orm refactoring

This commit is contained in:
Yuri Kuznetsov
2020-08-04 17:46:50 +03:00
parent 4ea2455958
commit 1d0476e1b8
7 changed files with 271 additions and 91 deletions
+145 -5
View File
@@ -44,7 +44,7 @@ use PDO;
*/
abstract class BaseQuery
{
protected static $selectParamList = [
protected static $paramList = [
'select',
'whereClause',
'offset',
@@ -66,6 +66,7 @@ abstract class BaseQuery
'maxTextColumnsLength',
'useIndex',
'withDeleted',
'update',
];
protected static $sqlOperators = [
@@ -269,6 +270,7 @@ abstract class BaseQuery
const SELECT_METHOD = 'SELECT';
const DELETE_METHOD = 'DELETE';
const UPDATE_METHOD = 'UPDATE';
const INSERT_METHOD = 'INESRT';
protected $entityFactory;
@@ -332,10 +334,12 @@ abstract class BaseQuery
/**
* Compose an UPDATE query.
*/
public function createUpdateQuery(string $entityType, ?array $params = null, array $values) : string
public function createUpdateQuery(string $entityType, ?array $params = null) : string
{
$params = $this->normilizeParams(self::UPDATE_METHOD, $params);
$values = $params['update'];
$entity = $this->getSeed($entityType);
$wherePart = $this->getWherePart($entity, $params['whereClause'], 'AND', $params);
@@ -356,11 +360,85 @@ abstract class BaseQuery
return $sql;
}
public function createInsertQuery(string $entityType, array $params) : string
{
$params = $this->normilizeInsertParams($params);
$columns = $params['columns'];
$values = $params['values'];
$isMass = $params['isMass'];
$update = $params['update'];
$columnsPart = $this->getInsertColumnsPart($columns);
if ($isMass) {
$valuesPart = [];
foreach ($values as $item) {
$valuesPart[] = $this->getInsertValuesPart($columns, $item);
}
} else {
$valuesPart = $this->getInsertValuesPart($columns, $values);
}
$updatePart = null;
if ($update) {
$updatePart = $this->getInsertUpdatePart($update);
}
return $this->composeInsertQuery($this->toDb($entityType), $columnsPart, $valuesPart, $updatePart);
}
protected function normilizeInsertParams(array $params) : array
{
$columns = $params['columns'] ?? null;
if (empty($columns) || !is_array($columns)) {
throw new Error("ORM Query: 'columns' is empty for INSERT.");
}
$params['isMass'] = $params['isMass'] ?? false;
$values = $params['values'] ?? null;
if (empty($values) || !is_array($values)) {
throw new Error("ORM Query: 'values' is empty for INSERT.");
}
$isMass = array_keys($values)[0] === 0;
$params['isMass'] = $isMass;
if (!$isMass) {
foreach ($columns as $item) {
if (!array_key_exists($item, $values)) {
throw new Error("ORM Query: 'values' should contain all items listed in 'columns'.");
}
}
} else {
foreach ($values as $valuesItem) {
foreach ($columns as $item) {
if (!array_key_exists($item, $valuesItem)) {
throw new Error("ORM Query: 'values' should contain all items listed in 'columns'.");
}
}
}
}
$update = $params['update'] = $params['update'] ?? null;
if ($update && !is_array($update)) {
throw new Error("ORM Query: Bad 'update' param.");
}
return $params;
}
protected function normilizeParams(string $method, ?array $params) : array
{
$params = $params ?? [];
foreach (self::$selectParamList as $k) {
foreach (self::$paramList as $k) {
$params[$k] = array_key_exists($k, $params) ? $params[$k] : null;
}
@@ -373,14 +451,24 @@ abstract class BaseQuery
if ($method !== self::SELECT_METHOD) {
if (isset($params['aggregation'])) {
throw new Error("ORM Query: Aggregation is not allowed for '{$method}'.");
throw new Error("ORM Query: Param 'aggregation' is not allowed for '{$method}'.");
}
if (isset($params['offset'])) {
throw new Error("ORM Query: Offset is not allowed for '{$method}'.");
throw new Error("ORM Query: Param 'offset' is not allowed for '{$method}'.");
}
}
if ($method !== self::UPDATE_METHOD && $method !== self::INSERT_METHOD) {
if (isset($params['update'])) {
throw new Error("ORM Query: Param 'update' is not allowed for '{$method}'.");
}
}
if (isset($params['update']) && !is_array($params['update'])) {
throw new Error("ORM Query: Param 'update' should be an array.");
}
return $params;
}
@@ -2336,6 +2424,25 @@ abstract class BaseQuery
return $sql;
}
protected function composeInsertQuery(string $table, string $columns, $values, ?string $update = null) : string
{
$sql = "INSERT INTO `{$table}`";
$sql .= " ({$columns})";
if (is_array($values)) {
$sql .= " VALUES (" . implode("), (", $values) . ")";
} else {
$sql .= " VALUES ({$values})";
}
if ($update) {
$sql .= " ON DUPLICATE KEY UPDATE " . $update;
}
return $sql;
}
protected function getSetPart(Entity $entity, array $values) : string
{
if (!count($values)) {
@@ -2375,6 +2482,39 @@ abstract class BaseQuery
return implode(', ', $list);
}
protected function getInsertColumnsPart(array $columnList) : string
{
$list = [];
foreach ($columnList as $column) {
$list[] = '`'.$this->toDb($this->sanitize($column)) . '`';
}
return implode(', ', $list);
}
protected function getInsertValuesPart(array $columnList, array $values) : string
{
$list = [];
foreach ($columnList as $column) {
$list[] = $this->quote($values[$column]);
}
return implode(', ', $list);
}
protected function getInsertUpdatePart(array $values) : string
{
$list = [];
foreach ($values as $column => $value) {
$list[] = "`" . $this->toDb($this->sanitize($column)) . "` = " . $this->quote($value);
}
return implode(', ', $list);
}
/**
* Add a LIMIT part to a SQL query.
*/