mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-02-12 14:58:42 +00:00
Optimize mapper loops
This commit is contained in:
parent
aa89b83746
commit
71a13da619
|
|
@ -15,6 +15,7 @@ declare(strict_types=1);
|
||||||
namespace phpOMS\DataStorage\Database;
|
namespace phpOMS\DataStorage\Database;
|
||||||
|
|
||||||
use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
|
use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
|
||||||
|
use phpOMS\DataStorage\Database\Query\QueryType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database query builder.
|
* Database query builder.
|
||||||
|
|
@ -48,7 +49,7 @@ abstract class BuilderAbstract
|
||||||
* @var int
|
* @var int
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected $type = null;
|
protected $type = QueryType::EMPTY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefix.
|
* Prefix.
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ use phpOMS\DataStorage\DataMapperInterface;
|
||||||
use phpOMS\Message\RequestAbstract;
|
use phpOMS\Message\RequestAbstract;
|
||||||
use phpOMS\DataStorage\Database\Exception\InvalidMapperException;
|
use phpOMS\DataStorage\Database\Exception\InvalidMapperException;
|
||||||
use phpOMS\Util\ArrayUtils;
|
use phpOMS\Util\ArrayUtils;
|
||||||
|
use phpOMS\DataStorage\Database\Query\QueryType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Datamapper for databases.
|
* Datamapper for databases.
|
||||||
|
|
@ -400,45 +401,39 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
$query = new Builder(self::$db);
|
$query = new Builder(self::$db);
|
||||||
$query->prefix(self::$db->getPrefix())->into(static::$table);
|
$query->prefix(self::$db->getPrefix())->into(static::$table);
|
||||||
|
|
||||||
$properties = $refClass->getProperties();
|
foreach (static::$columns as $key => $column) {
|
||||||
|
$propertyName = $column['internal'];
|
||||||
foreach ($properties as $property) {
|
|
||||||
$propertyName = $property->getName();
|
|
||||||
|
|
||||||
if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName])) {
|
if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$property = $refClass->getProperty($propertyName);
|
||||||
|
|
||||||
if (!($isPublic = $property->isPublic())) {
|
if (!($isPublic = $property->isPublic())) {
|
||||||
$property->setAccessible(true);
|
$property->setAccessible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (static::$columns as $key => $column) {
|
if (isset(static::$ownsOne[$propertyName])) {
|
||||||
if (isset(static::$ownsOne[$propertyName]) && $column['internal'] === $propertyName) {
|
$id = self::createOwnsOne($propertyName, $property->getValue($obj));
|
||||||
$id = self::createOwnsOne($propertyName, $property->getValue($obj));
|
$value = self::parseValue($column['type'], $id);
|
||||||
$value = self::parseValue($column['type'], $id);
|
|
||||||
|
|
||||||
$query->insert($column['name'])->value($value, $column['type']);
|
$query->insert($column['name'])->value($value, $column['type']);
|
||||||
break;
|
} elseif (isset(static::$belongsTo[$propertyName])) {
|
||||||
} elseif (isset(static::$belongsTo[$propertyName]) && $column['internal'] === $propertyName) {
|
$id = self::createBelongsTo($propertyName, $property->getValue($obj));
|
||||||
$id = self::createBelongsTo($propertyName, $property->getValue($obj));
|
$value = self::parseValue($column['type'], $id);
|
||||||
$value = self::parseValue($column['type'], $id);
|
|
||||||
|
|
||||||
$query->insert($column['name'])->value($value, $column['type']);
|
$query->insert($column['name'])->value($value, $column['type']);
|
||||||
break;
|
} elseif ($column['name'] !== static::$primaryField) {
|
||||||
} elseif ($column['internal'] === $propertyName && $column['type'] !== static::$primaryField) {
|
$tValue = $property->getValue($obj);
|
||||||
$tValue = $property->getValue($obj);
|
if (stripos($column['internal'], '/') !== false) {
|
||||||
if (stripos($column['internal'], '/') !== false) {
|
$path = explode($column['internal']);
|
||||||
$path = explode($column['internal']);
|
$path = implode('/', array_shift($path));
|
||||||
$path = implode('/', array_shift($path));
|
$tValue = ArrayUtils::getArray($path, $tValue, '/');
|
||||||
$tValue = ArrayUtils::getArray($path, $tValue, '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
$value = self::parseValue($column['type'], $tValue);
|
|
||||||
|
|
||||||
$query->insert($column['name'])->value($value, $column['type']);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$value = self::parseValue($column['type'], $tValue);
|
||||||
|
|
||||||
|
$query->insert($column['name'])->value($value, $column['type']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($isPublic)) {
|
if (!($isPublic)) {
|
||||||
|
|
@ -446,8 +441,9 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (static::$table === 'exchange') {
|
// if a table only has a single column = primary key column. This must be done otherwise the query is empty
|
||||||
var_dump($query->toSql());
|
if ($query->getType() === QueryType::EMPTY) {
|
||||||
|
$query->insert(static::$primaryField)->value(0, static::$columns[static::$primaryField]['type']);
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$db->con->prepare($query->toSql())->execute();
|
self::$db->con->prepare($query->toSql())->execute();
|
||||||
|
|
@ -470,7 +466,9 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
$query->prefix(self::$db->getPrefix())->into(static::$table);
|
$query->prefix(self::$db->getPrefix())->into(static::$table);
|
||||||
|
|
||||||
foreach (static::$columns as $key => $column) {
|
foreach (static::$columns as $key => $column) {
|
||||||
if (isset(static::$hasMany[$key]) || isset(static::$hasOne[$key])) {
|
if (isset(static::$hasMany[$key])
|
||||||
|
|| isset(static::$hasOne[$key])
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -494,7 +492,7 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
|
|
||||||
$query->insert($column['name'])->value($value, $column['type']);
|
$query->insert($column['name'])->value($value, $column['type']);
|
||||||
break;
|
break;
|
||||||
} elseif ($column['internal'] === $path && $column['type'] !== static::$primaryField) {
|
} elseif ($column['internal'] === $path) {
|
||||||
$value = self::parseValue($column['type'], $property);
|
$value = self::parseValue($column['type'], $property);
|
||||||
|
|
||||||
$query->insert($column['name'])->value($value, $column['type']);
|
$query->insert($column['name'])->value($value, $column['type']);
|
||||||
|
|
@ -519,8 +517,8 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
*/
|
*/
|
||||||
private static function getObjectId($obj, \ReflectionClass $refClass = null)
|
private static function getObjectId($obj, \ReflectionClass $refClass = null)
|
||||||
{
|
{
|
||||||
$refClass = $refClass ?? new \ReflectionClass($obj);
|
$refClass = $refClass ?? new \ReflectionClass($obj);
|
||||||
$refProp = $refClass->getProperty(static::$columns[static::$primaryField]['internal']);
|
$refProp = $refClass->getProperty(static::$columns[static::$primaryField]['internal']);
|
||||||
|
|
||||||
if (!($isPublic = $refProp->isPublic())) {
|
if (!($isPublic = $refProp->isPublic())) {
|
||||||
$refProp->setAccessible(true);
|
$refProp->setAccessible(true);
|
||||||
|
|
@ -539,8 +537,8 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
* Set id to model
|
* Set id to model
|
||||||
*
|
*
|
||||||
* @param \ReflectionClass $refClass Reflection class
|
* @param \ReflectionClass $refClass Reflection class
|
||||||
* @param Object $obj Object to create
|
* @param Object $obj Object to create
|
||||||
* @param mixed $objId Id to set
|
* @param mixed $objId Id to set
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
|
@ -566,8 +564,8 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
* Create has many
|
* Create has many
|
||||||
*
|
*
|
||||||
* @param \ReflectionClass $refClass Reflection class
|
* @param \ReflectionClass $refClass Reflection class
|
||||||
* @param Object $obj Object to create
|
* @param Object $obj Object to create
|
||||||
* @param mixed $objId Id to set
|
* @param mixed $objId Id to set
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
|
@ -704,7 +702,7 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
* Create has one
|
* Create has one
|
||||||
*
|
*
|
||||||
* @param \ReflectionClass $refClass Property name to initialize
|
* @param \ReflectionClass $refClass Property name to initialize
|
||||||
* @param Object $obj Object to create
|
* @param Object $obj Object to create
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @todo implement???
|
* @todo implement???
|
||||||
|
|
@ -905,8 +903,8 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
* Update has many
|
* Update has many
|
||||||
*
|
*
|
||||||
* @param \ReflectionClass $refClass Reflection class
|
* @param \ReflectionClass $refClass Reflection class
|
||||||
* @param Object $obj Object to create
|
* @param Object $obj Object to create
|
||||||
* @param mixed $objId Id to set
|
* @param mixed $objId Id to set
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
|
@ -1101,8 +1099,8 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
/**
|
/**
|
||||||
* Update object in db.
|
* Update object in db.
|
||||||
*
|
*
|
||||||
* @param Object $obj Model to update
|
* @param Object $obj Model to update
|
||||||
* @param mixed $objId Model id
|
* @param mixed $objId Model id
|
||||||
* @param \ReflectionClass $refClass Reflection class
|
* @param \ReflectionClass $refClass Reflection class
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
|
@ -1116,48 +1114,43 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
->update(static::$table)
|
->update(static::$table)
|
||||||
->where(static::$table . '.' . static::$primaryField, '=', $objId);
|
->where(static::$table . '.' . static::$primaryField, '=', $objId);
|
||||||
|
|
||||||
$properties = $refClass->getProperties();
|
foreach (static::$columns as $key => $column) {
|
||||||
|
$propertyName = $column['internal'];
|
||||||
foreach ($properties as $property) {
|
if (isset(static::$hasMany[$propertyName])
|
||||||
$propertyName = $property->getName();
|
|| isset(static::$hasOne[$propertyName])
|
||||||
|
|| $column['internal'] === static::$primaryField
|
||||||
if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName])) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$property = $refClass->getProperty($propertyName);
|
||||||
|
|
||||||
if (!($isPublic = $property->isPublic())) {
|
if (!($isPublic = $property->isPublic())) {
|
||||||
$property->setAccessible(true);
|
$property->setAccessible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: the order of updating could be a problem. maybe looping through ownsOne and belongsTo first is better.
|
if (isset(static::$ownsOne[$propertyName])) {
|
||||||
|
$id = self::updateOwnsOne($propertyName, $property->getValue($obj));
|
||||||
|
$value = self::parseValue($column['type'], $id);
|
||||||
|
|
||||||
foreach (static::$columns as $key => $column) {
|
// todo: should not be done if the id didn't change. but for now don't know if id changed
|
||||||
if (isset(static::$ownsOne[$propertyName]) && $column['internal'] === $propertyName) {
|
$query->set([static::$table . '.' . $column['name'] => $value], $column['type']);
|
||||||
$id = self::updateOwnsOne($propertyName, $property->getValue($obj));
|
} elseif (isset(static::$belongsTo[$propertyName])) {
|
||||||
$value = self::parseValue($column['type'], $id);
|
$id = self::updateBelongsTo($propertyName, $property->getValue($obj));
|
||||||
|
$value = self::parseValue($column['type'], $id);
|
||||||
|
|
||||||
// todo: should not be done if the id didn't change. but for now don't know if id changed
|
// todo: should not be done if the id didn't change. but for now don't know if id changed
|
||||||
$query->set([static::$table . '.' . $column['name'] => $value], $column['type']);
|
$query->set([static::$table . '.' . $column['name'] => $value], $column['type']);
|
||||||
break;
|
} elseif ($column['name'] !== static::$primaryField) {
|
||||||
} elseif (isset(static::$belongsTo[$propertyName]) && $column['internal'] === $propertyName) {
|
$tValue = $property->getValue($obj);
|
||||||
$id = self::updateBelongsTo($propertyName, $property->getValue($obj));
|
if (stripos($column['internal'], '/') !== false) {
|
||||||
$value = self::parseValue($column['type'], $id);
|
$path = explode($column['internal']);
|
||||||
|
$path = implode('/', array_shift($path));
|
||||||
// todo: should not be done if the id didn't change. but for now don't know if id changed
|
$tValue = ArrayUtils::getArray($path, $tValue, '/');
|
||||||
$query->set([static::$table . '.' . $column['name'] => $value], $column['type']);
|
|
||||||
break;
|
|
||||||
} elseif ($column['internal'] === $propertyName && $column['type'] !== static::$primaryField) {
|
|
||||||
$tValue = $property->getValue($obj);
|
|
||||||
if (stripos($column['internal'], '/') !== false) {
|
|
||||||
$path = explode($column['internal']);
|
|
||||||
$path = implode('/', array_shift($path));
|
|
||||||
$tValue = ArrayUtils::getArray($path, $tValue, '/');
|
|
||||||
}
|
|
||||||
$value = self::parseValue($column['type'], $tValue);
|
|
||||||
|
|
||||||
$query->set([static::$table . '.' . $column['name'] => $value], $column['type']);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
$value = self::parseValue($column['type'], $tValue);
|
||||||
|
|
||||||
|
$query->set([static::$table . '.' . $column['name'] => $value], $column['type']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($isPublic)) {
|
if (!($isPublic)) {
|
||||||
|
|
@ -1212,10 +1205,10 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
/**
|
/**
|
||||||
* Delete has many
|
* Delete has many
|
||||||
*
|
*
|
||||||
* @param \ReflectionClass $refClass Reflection class
|
* @param \ReflectionClass $refClass Reflection class
|
||||||
* @param Object $obj Object to create
|
* @param Object $obj Object to create
|
||||||
* @param mixed $objId Id to set
|
* @param mixed $objId Id to set
|
||||||
* @param int $relations Delete all relations as well
|
* @param int $relations Delete all relations as well
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
|
@ -1332,10 +1325,10 @@ class DataMapperAbstract implements DataMapperInterface
|
||||||
/**
|
/**
|
||||||
* Delete object in db.
|
* Delete object in db.
|
||||||
*
|
*
|
||||||
* @param Object $obj Model to delete
|
* @param Object $obj Model to delete
|
||||||
* @param mixed $objId Model id
|
* @param mixed $objId Model id
|
||||||
* @param int $relations Delete all relations as well
|
* @param int $relations Delete all relations as well
|
||||||
* @param \ReflectionClass $refClass Reflection class
|
* @param \ReflectionClass $refClass Reflection class
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,5 @@ abstract class QueryType extends Enum
|
||||||
public const DELETE = 3;
|
public const DELETE = 3;
|
||||||
public const RANDOM = 4;
|
public const RANDOM = 4;
|
||||||
public const RAW = 5;
|
public const RAW = 5;
|
||||||
|
public const EMPTY = 6;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class QueryTypeTest extends \PHPUnit\Framework\TestCase
|
||||||
{
|
{
|
||||||
public function testEnums()
|
public function testEnums()
|
||||||
{
|
{
|
||||||
self::assertEquals(6, count(QueryType::getConstants()));
|
self::assertEquals(7, count(QueryType::getConstants()));
|
||||||
self::assertEquals(QueryType::getConstants(), array_unique(QueryType::getConstants()));
|
self::assertEquals(QueryType::getConstants(), array_unique(QueryType::getConstants()));
|
||||||
|
|
||||||
self::assertEquals(0, QueryType::SELECT);
|
self::assertEquals(0, QueryType::SELECT);
|
||||||
|
|
@ -28,5 +28,6 @@ class QueryTypeTest extends \PHPUnit\Framework\TestCase
|
||||||
self::assertEquals(3, QueryType::DELETE);
|
self::assertEquals(3, QueryType::DELETE);
|
||||||
self::assertEquals(4, QueryType::RANDOM);
|
self::assertEquals(4, QueryType::RANDOM);
|
||||||
self::assertEquals(5, QueryType::RAW);
|
self::assertEquals(5, QueryType::RAW);
|
||||||
|
self::assertEquals(6, QueryType::EMPTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,17 @@ class BaseModelMapper extends DataMapperAbstract
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected static $columns = [
|
protected static $columns = [
|
||||||
'test_base_id' => ['name' => 'test_base_id', 'type' => 'int', 'internal' => 'id'],
|
'test_base_id' => ['name' => 'test_base_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
'test_base_string' => ['name' => 'test_base_string', 'type' => 'string', 'internal' => 'string'],
|
'test_base_string' => ['name' => 'test_base_string', 'type' => 'string', 'internal' => 'string'],
|
||||||
'test_base_int' => ['name' => 'test_base_int', 'type' => 'int', 'internal' => 'int'],
|
'test_base_int' => ['name' => 'test_base_int', 'type' => 'int', 'internal' => 'int'],
|
||||||
'test_base_bool' => ['name' => 'test_base_bool', 'type' => 'bool', 'internal' => 'bool'],
|
'test_base_bool' => ['name' => 'test_base_bool', 'type' => 'bool', 'internal' => 'bool'],
|
||||||
'test_base_null' => ['name' => 'test_base_null', 'type' => 'int', 'internal' => 'null'],
|
'test_base_null' => ['name' => 'test_base_null', 'type' => 'int', 'internal' => 'null'],
|
||||||
'test_base_float' => ['name' => 'test_base_float', 'type' => 'float', 'internal' => 'float'],
|
'test_base_float' => ['name' => 'test_base_float', 'type' => 'float', 'internal' => 'float'],
|
||||||
'test_base_json' => ['name' => 'test_base_json', 'type' => 'Json', 'internal' => 'json'],
|
'test_base_json' => ['name' => 'test_base_json', 'type' => 'Json', 'internal' => 'json'],
|
||||||
'test_base_jsonSerialize' => ['name' => 'test_base_jsonSerialize', 'type' => 'jsonSerializable', 'internal' => 'jsonSerialize'],
|
'test_base_json_serializable' => ['name' => 'test_base_json_serializable', 'type' => 'Json', 'internal' => 'jsonSerializable'],
|
||||||
'test_base_datetime' => ['name' => 'test_base_datetime', 'type' => 'DateTime', 'internal' => 'datetime'],
|
'test_base_datetime' => ['name' => 'test_base_datetime', 'type' => 'DateTime', 'internal' => 'datetime'],
|
||||||
'test_base_owns_one_self' => ['name' => 'test_base_owns_one_self', 'type' => 'int', 'internal' => 'ownsOneSelf'],
|
'test_base_owns_one_self' => ['name' => 'test_base_owns_one_self', 'type' => 'int', 'internal' => 'ownsOneSelf'],
|
||||||
'test_base_belongs_to_one' => ['name' => 'test_base_belongs_to_one', 'type' => 'int', 'internal' => 'belongsToOne'],
|
'test_base_belongs_to_one' => ['name' => 'test_base_belongs_to_one', 'type' => 'int', 'internal' => 'belongsToOne'],
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $belongsTo = [
|
protected static $belongsTo = [
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user