DataMapper rewrite for performance increase

Implemented caching (was bugged). Caching is now per request and not per object. Made code visually a tiny bit better, still horrible though.
This commit is contained in:
Dennis Eichhorn 2017-12-03 21:26:58 +01:00
parent fc329ad002
commit e92df825fe
2 changed files with 88 additions and 67 deletions

View File

@ -303,7 +303,7 @@ class DataMapperAbstract implements DataMapperInterface
// clear parent and objects // clear parent and objects
if (static::class === self::$parentMapper) { if (static::class === self::$parentMapper) {
self::$initObjects = []; //self::$initObjects = []; // todo: now all objects are cached for the whole request
self::$parentMapper = null; self::$parentMapper = null;
} }
} }
@ -346,13 +346,11 @@ class DataMapperAbstract implements DataMapperInterface
{ {
self::extend(__CLASS__); self::extend(__CLASS__);
if (!isset($obj) || if (!isset($obj) || self::isNullObject($obj)) {
(strpos($className = get_class($obj), '\Null') !== false && is_object($obj))
) {
return null; return null;
} }
$reflectionClass = new \ReflectionClass($className); $reflectionClass = new \ReflectionClass($obj);
$objId = self::createModel($obj, $reflectionClass); $objId = self::createModel($obj, $reflectionClass);
self::setObjectId($reflectionClass, $obj, $objId); self::setObjectId($reflectionClass, $obj, $objId);
@ -1158,7 +1156,7 @@ class DataMapperAbstract implements DataMapperInterface
{ {
self::extend(__CLASS__); self::extend(__CLASS__);
if (!isset($obj) || strpos(get_class($obj), '\Null') !== false) { if (!isset($obj) || self::isNullObject($obj)) {
return null; return null;
} }
@ -1166,6 +1164,9 @@ class DataMapperAbstract implements DataMapperInterface
$objId = self::getObjectId($obj, $reflectionClass); $objId = self::getObjectId($obj, $reflectionClass);
$update = true; $update = true;
// todo: maybe don't remove obj and just update cache... ? since it might have to be loaded again
self::removeInitialized(static::class, $objId);
if (empty($objId)) { if (empty($objId)) {
$update = false; $update = false;
self::create($obj, $relations); self::create($obj, $relations);
@ -1379,6 +1380,8 @@ class DataMapperAbstract implements DataMapperInterface
return null; return null;
} }
self::removeInitialized(static::class, $objId);
if ($relations !== RelationType::NONE) { if ($relations !== RelationType::NONE) {
self::deleteHasMany($reflectionClass, $obj, $objId, $relations); self::deleteHasMany($reflectionClass, $obj, $objId, $relations);
} }
@ -1487,11 +1490,6 @@ class DataMapperAbstract implements DataMapperInterface
$mapper = static::$hasMany[$member]['mapper']; $mapper = static::$hasMany[$member]['mapper'];
$reflectionProperty = $reflectionClass->getProperty($member); $reflectionProperty = $reflectionClass->getProperty($member);
$values = array_diff($values, array_keys(self::$initObjects[$mapper] ?? []));
if (empty($values)) {
continue;
}
if (!($accessible = $reflectionProperty->isPublic())) { if (!($accessible = $reflectionProperty->isPublic())) {
$reflectionProperty->setAccessible(true); $reflectionProperty->setAccessible(true);
} }
@ -1523,11 +1521,6 @@ class DataMapperAbstract implements DataMapperInterface
if (!empty($values)) { if (!empty($values)) {
/** @var string $mapper */ /** @var string $mapper */
$mapper = static::$hasMany[$member]['mapper']; $mapper = static::$hasMany[$member]['mapper'];
$values = array_diff($values, array_keys(self::$initObjects[$mapper] ?? []));
if (empty($values)) {
continue;
}
$objects = $mapper::getArray($values, RelationType::ALL, $depth); $objects = $mapper::getArray($values, RelationType::ALL, $depth);
$obj[$member] = $objects; $obj[$member] = $objects;
@ -1562,13 +1555,15 @@ class DataMapperAbstract implements DataMapperInterface
/** @var string $mapper */ /** @var string $mapper */
$mapper = static::$hasOne[$member]['mapper']; $mapper = static::$hasOne[$member]['mapper'];
$id = $reflectionProperty->getValue($obj);
if (self::isInitialized($mapper, ($id = $reflectionProperty->getValue($obj)))) { if (self::isNullObject($id)) {
$value = self::$initObjects[$mapper][$id]; continue;
} else {
$value = $mapper::get($reflectionProperty->getValue($obj), RelationType::ALL, null, $depth);
} }
$id = is_object($id) ? self::getObjectId($id) : $id;
$value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth);
$reflectionProperty->setValue($obj, $value); $reflectionProperty->setValue($obj, $value);
if (!$accessible) { if (!$accessible) {
@ -1595,14 +1590,7 @@ class DataMapperAbstract implements DataMapperInterface
foreach (static::$hasOne as $member => $one) { foreach (static::$hasOne as $member => $one) {
/** @var string $mapper */ /** @var string $mapper */
$mapper = static::$hasOne[$member]['mapper']; $mapper = static::$hasOne[$member]['mapper'];
$obj[$member] = self::getInitialized($mapper, $obj['member']) ?? $mapper::getArray($obj[$member], RelationType::ALL, $depth);
if (self::isInitialized($mapper, $obj['member'])) {
$value = self::$initObjects[$mapper][$obj['member']];
} else {
$value = $mapper::getArray($obj[$member], RelationType::ALL, $depth);
}
$obj[$member] = $value;
} }
} }
@ -1633,13 +1621,15 @@ class DataMapperAbstract implements DataMapperInterface
/** @var string $mapper */ /** @var string $mapper */
$mapper = static::$ownsOne[$member]['mapper']; $mapper = static::$ownsOne[$member]['mapper'];
$id = $reflectionProperty->getValue($obj);
if (self::isInitialized($mapper, ($id = $reflectionProperty->getValue($obj)))) { if (self::isNullObject($id)) {
$value = self::$initObjects[$mapper][$id]; continue;
} else {
$value = $mapper::get($reflectionProperty->getValue($obj), RelationType::ALL, null, $depth);
} }
$id = is_object($id) ? self::getObjectId($id) : $id;
$value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth);
$reflectionProperty->setValue($obj, $value); $reflectionProperty->setValue($obj, $value);
if (!$accessible) { if (!$accessible) {
@ -1666,14 +1656,7 @@ class DataMapperAbstract implements DataMapperInterface
foreach (static::$ownsOne as $member => $one) { foreach (static::$ownsOne as $member => $one) {
/** @var string $mapper */ /** @var string $mapper */
$mapper = static::$ownsOne[$member]['mapper']; $mapper = static::$ownsOne[$member]['mapper'];
$obj[$member] = self::getInitialized($mapper, $obj[$member]) ?? $mapper::getArray($obj[$member], RelationType::ALL, $depth);
if (self::isInitialized($mapper, $obj[$member])) {
$value = self::$initObjects[$mapper][$obj[$member]];
} else {
$value = $mapper::getArray($obj[$member], RelationType::ALL, $depth);
}
$obj[$member] = $value;
} }
} }
@ -1704,13 +1687,15 @@ class DataMapperAbstract implements DataMapperInterface
/** @var string $mapper */ /** @var string $mapper */
$mapper = static::$belongsTo[$member]['mapper']; $mapper = static::$belongsTo[$member]['mapper'];
$id = $reflectionProperty->getValue($obj);
if (self::isInitialized($mapper, ($id = $reflectionProperty->getValue($obj)))) { if (self::isNullObject($id)) {
$value = self::$initObjects[$mapper][$id]; continue;
} else {
$value = $mapper::get($reflectionProperty->getValue($obj), RelationType::ALL, null, $depth);
} }
$id = is_object($id) ? self::getObjectId($id) : $id;
$value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth);
$reflectionProperty->setValue($obj, $value); $reflectionProperty->setValue($obj, $value);
if (!$accessible) { if (!$accessible) {
@ -1736,14 +1721,7 @@ class DataMapperAbstract implements DataMapperInterface
foreach (static::$belongsTo as $member => $one) { foreach (static::$belongsTo as $member => $one) {
/** @var string $mapper */ /** @var string $mapper */
$mapper = static::$belongsTo[$member]['mapper']; $mapper = static::$belongsTo[$member]['mapper'];
$obj[$member] = self::getInitialized($mapper, $obj[$member]) ?? $mapper::get($obj[$member]);
if (self::isInitialized($mapper, $obj[$member])) {
$value = self::$initObjects[$mapper][$obj[$member]];
} else {
$value = $mapper::get($obj[$member]);
}
$obj[$member] = $value;
} }
} }
@ -1865,6 +1843,7 @@ class DataMapperAbstract implements DataMapperInterface
foreach ($primaryKey as $key => $value) { foreach ($primaryKey as $key => $value) {
if (self::isInitialized(static::class, $value)) { if (self::isInitialized(static::class, $value)) {
$obj[$value] = self::$initObjects[static::class][$value];
continue; continue;
} }
@ -1879,7 +1858,7 @@ class DataMapperAbstract implements DataMapperInterface
$obj[$value]->initialize(); $obj[$value]->initialize();
} }
self::addInitialized(static::class, $value); self::addInitialized(static::class, $value, $obj[$value]);
} }
self::fillRelations($obj, $relations, isset($depth) ? --$depth : null); self::fillRelations($obj, $relations, isset($depth) ? --$depth : null);
@ -1943,12 +1922,13 @@ class DataMapperAbstract implements DataMapperInterface
foreach ($primaryKey as $key => $value) { foreach ($primaryKey as $key => $value) {
if (self::isInitialized(static::class, $value)) { if (self::isInitialized(static::class, $value)) {
$obj[$value] = self::$initObjects[static::class][$value];
continue; continue;
} }
$obj[$value] = self::populateAbstractArray(self::getRaw($value)); $obj[$value] = self::populateAbstractArray(self::getRaw($value));
self::addInitialized(static::class, $value); self::addInitialized(static::class, $value, $obj[$value]);
} }
self::fillRelationsArray($obj, $relations, isset($depth) ? --$depth : null); self::fillRelationsArray($obj, $relations, isset($depth) ? --$depth : null);
@ -2585,11 +2565,43 @@ class DataMapperAbstract implements DataMapperInterface
* *
* @since 1.0.0 * @since 1.0.0
*/ */
private static function isInitialized($mapper, $id) : bool private static function isInitialized(string $mapper, $id) : bool
{ {
return isset(self::$initObjects[$mapper]) && isset(self::$initObjects[$mapper][$id]); return isset(self::$initObjects[$mapper]) && isset(self::$initObjects[$mapper][$id]);
} }
/**
* Get initialized object
*
* @param string $mapper Mapper name
* @param mixed $id Object id
*
* @return mixed
*
* @since 1.0.0
*/
private static function getInitialized(string $mapper, $id)
{
return self::$initObjects[$mapper][$id] ?? null;
}
/**
* Remove initialized object
*
* @param string $mapper Mapper name
* @param mixed $id Object id
*
* @return mixed
*
* @since 1.0.0
*/
private static function removeInitialized(string $mapper, $id)
{
if (self::isInitialized($mapper, $id)) {
unset(self::$initObjects[$mapper][$id]);
}
}
/** /**
* Define the highest mapper of this request * Define the highest mapper of this request
* *
@ -2648,4 +2660,18 @@ class DataMapperAbstract implements DataMapperInterface
throw new \Exception('Invalid member name'); throw new \Exception('Invalid member name');
} }
/**
* Test if object is null object
*
* @param object $obj Object to check
*
* @return bool
*
* @since 1.0.0
*/
private static function isNullObject($obj) : bool
{
return is_object($obj) && strpos(get_class($obj), '\Null') !== false;
}
} }

View File

@ -238,24 +238,19 @@ abstract class GrammarAbstract
$identifier = $this->systemIdentifier; $identifier = $this->systemIdentifier;
foreach ($this->specialKeywords as $keyword) { foreach ($this->specialKeywords as $keyword) {
if ($keyword === '' || strrpos($system, $keyword, -strlen($system)) !== false) { if (strrpos($system, $keyword, -strlen($system)) !== false) {
$prefix = ''; $prefix = '';
$identifier = ''; $identifier = '';
} }
} }
// todo: move remaining * test also here not just if .* but also if * (should be done in else?) // todo: move remaining * test also here not just if .* but also if * (should be done in else?)
if (count($split = explode('.', $system)) == 2) { if (count($split = explode('.', $system)) === 2) {
if ($split[1] === '*') { $system = $split[1] === '*' ? $split[1] : $this->compileSystem($split[1]);
$system = $split[1];
} else {
$system = $this->compileSystem($split[1]);
}
return $this->compileSystem($prefix . $split[0]) . '.' . $system; return $this->compileSystem($prefix . $split[0]) . '.' . $system;
} else {
return $identifier . $prefix . $system . $identifier;
} }
}
return $identifier . $prefix . $system . $identifier;
}
} }