aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Lange <code@nerdmind.de>2021-08-10 17:42:11 +0200
committerThomas Lange <code@nerdmind.de>2021-08-10 19:41:49 +0200
commite3f05b25f961e0169185acabd32566e2ae5198fe (patch)
tree8c60ddc5d558983ad3bf4b20ca643b109410082b
parent49f03ac48efcce79822bed1ec40ad48bf5c6e450 (diff)
downloadblog-e3f05b25f961e0169185acabd32566e2ae5198fe.tar.gz
blog-e3f05b25f961e0169185acabd32566e2ae5198fe.tar.xz
blog-e3f05b25f961e0169185acabd32566e2ae5198fe.zip
Add a better mechanism to detect Entity changes
Implement and use a better mechanism to detect changes of attributes of the Entity objects by using a private variable which keeps track of the changed Entity attributes ("properties") via the "set" method. The "insert" and "update" method of the Repository now calls the method "getModifiedKeys" of the Entity class to get a list of properties which have been changed and builds the database query accordingly. This makes the use of "FALSE" as default value for the Entity attributes obsolete, so they have been set to the initial PHP default ("NULL").
-rw-r--r--core/namespace/ORM/Entities/Category.php10
-rw-r--r--core/namespace/ORM/Entities/Page.php10
-rw-r--r--core/namespace/ORM/Entities/Post.php12
-rw-r--r--core/namespace/ORM/Entities/User.php14
-rw-r--r--core/namespace/ORM/Entity.php16
-rw-r--r--core/namespace/ORM/Repositories/CategoryRepository.php23
-rw-r--r--core/namespace/ORM/Repository.php44
7 files changed, 68 insertions, 61 deletions
diff --git a/core/namespace/ORM/Entities/Category.php b/core/namespace/ORM/Entities/Category.php
index cf3ca5f..e8c4496 100644
--- a/core/namespace/ORM/Entities/Category.php
+++ b/core/namespace/ORM/Entities/Category.php
@@ -3,9 +3,9 @@ namespace ORM\Entities;
use ORM\Entity;
class Category extends Entity {
- protected $parent = FALSE;
- protected $slug = FALSE;
- protected $name = FALSE;
- protected $body = FALSE;
- protected $argv = FALSE;
+ protected $parent;
+ protected $slug;
+ protected $name;
+ protected $body;
+ protected $argv;
}
diff --git a/core/namespace/ORM/Entities/Page.php b/core/namespace/ORM/Entities/Page.php
index 96ff233..1a65c01 100644
--- a/core/namespace/ORM/Entities/Page.php
+++ b/core/namespace/ORM/Entities/Page.php
@@ -3,9 +3,9 @@ namespace ORM\Entities;
use ORM\Entity;
class Page extends Entity {
- protected $user = FALSE;
- protected $slug = FALSE;
- protected $name = FALSE;
- protected $body = FALSE;
- protected $argv = FALSE;
+ protected $user;
+ protected $slug;
+ protected $name;
+ protected $body;
+ protected $argv;
}
diff --git a/core/namespace/ORM/Entities/Post.php b/core/namespace/ORM/Entities/Post.php
index 6a52a1f..8403a65 100644
--- a/core/namespace/ORM/Entities/Post.php
+++ b/core/namespace/ORM/Entities/Post.php
@@ -3,10 +3,10 @@ namespace ORM\Entities;
use ORM\Entity;
class Post extends Entity {
- protected $user = FALSE;
- protected $category = FALSE;
- protected $slug = FALSE;
- protected $name = FALSE;
- protected $body = FALSE;
- protected $argv = FALSE;
+ protected $user;
+ protected $category;
+ protected $slug;
+ protected $name;
+ protected $body;
+ protected $argv;
}
diff --git a/core/namespace/ORM/Entities/User.php b/core/namespace/ORM/Entities/User.php
index 65d5345..78e03db 100644
--- a/core/namespace/ORM/Entities/User.php
+++ b/core/namespace/ORM/Entities/User.php
@@ -3,11 +3,11 @@ namespace ORM\Entities;
use ORM\Entity;
class User extends Entity {
- protected $slug = FALSE;
- protected $username = FALSE;
- protected $password = FALSE;
- protected $fullname = FALSE;
- protected $mailaddr = FALSE;
- protected $body = FALSE;
- protected $argv = FALSE;
+ protected $slug;
+ protected $username;
+ protected $password;
+ protected $fullname;
+ protected $mailaddr;
+ protected $body;
+ protected $argv;
}
diff --git a/core/namespace/ORM/Entity.php b/core/namespace/ORM/Entity.php
index 9cc7755..a19b1f4 100644
--- a/core/namespace/ORM/Entity.php
+++ b/core/namespace/ORM/Entity.php
@@ -6,6 +6,9 @@ abstract class Entity implements EntityInterface {
protected $time_insert;
protected $time_update;
+ # Modified attributes
+ private $_modified = [];
+
#===============================================================================
# Get attribute
#===============================================================================
@@ -17,6 +20,11 @@ abstract class Entity implements EntityInterface {
# Set attribute
#===============================================================================
public function set(string $attribute, $value) {
+ if($this->{$attribute} !== $value) {
+ !in_array($attribute, $this->_modified) &&
+ array_push($this->_modified, $attribute);
+ }
+
return $this->{$attribute} = $value;
}
@@ -39,11 +47,9 @@ abstract class Entity implements EntityInterface {
}
#===============================================================================
- # Get array with all non-false attributes
+ # Get an array of modified attribute keys
#===============================================================================
- public function getFilteredAttributes(): array {
- return array_filter(get_object_vars($this), function($value) {
- return $value !== FALSE;
- });
+ public function getModifiedKeys(): array {
+ return $this->_modified;
}
}
diff --git a/core/namespace/ORM/Repositories/CategoryRepository.php b/core/namespace/ORM/Repositories/CategoryRepository.php
index b62485a..8692079 100644
--- a/core/namespace/ORM/Repositories/CategoryRepository.php
+++ b/core/namespace/ORM/Repositories/CategoryRepository.php
@@ -96,36 +96,31 @@ class CategoryRepository extends Repository {
# Update category (and check for parent/child circular loops)
#===============================================================================
public function update(EntityInterface $Entity): bool {
- # Entity parent might have changed *in memory*, so we re-fetch the original
- # parent of the entity from the database and save it in a variable.
- # TODO: Repository/Entity class should have a mechanism to detect changes!
+ # Skip circular loop check if parent is unchanged
+ if(!in_array('parent', $Entity->getModifiedKeys())) {
+ return parent::update($Entity);
+ }
+
$query = 'SELECT parent FROM %s WHERE id = ?';
$query = sprintf($query, static::getTableName());
$Statement = $this->Database->prepare($query);
$Statement->execute([$Entity->getID()]);
- $parent = $Statement->fetchColumn();
-
- # If parent is unchanged, circular loop check is not needed.
- if($parent === $Entity->get('parent')) {
- return parent::update($Entity);
- }
-
$_parent = $Entity->get('parent');
# Fetch the parent of the *new* parent category and let the while loop run through
# the tree until either a parent of "NULL" was found or if the new parent category
# is a *child* of the *current* category which would cause a circular loop.
while($Statement->execute([$_parent]) && $_parent = $Statement->fetchColumn()) {
- if($_parent == $Entity->get('id')) {
+ if($_parent == $Entity->getID()) {
# Set parent of the *new* parent category to the *original* parent category
# of the *current* category (one level up) to prevent a circular loop.
- $query = 'UPDATE %s SET parent = ? WHERE id = ?';
- $query = sprintf($query, static::getTableName());
+ $query = 'UPDATE %s SET parent = (SELECT parent FROM %s WHERE id = ?) WHERE id = ?';
+ $query = sprintf($query, static::getTableName(), static::getTableName());
$UpdateStatement = $this->Database->prepare($query);
- $UpdateStatement->execute([$parent, $Entity->get('parent')]);
+ $UpdateStatement->execute([$_parent, $Entity->get('parent')]);
break;
} else if($_parent === NULL) {
break;
diff --git a/core/namespace/ORM/Repository.php b/core/namespace/ORM/Repository.php
index 423a286..e7750cb 100644
--- a/core/namespace/ORM/Repository.php
+++ b/core/namespace/ORM/Repository.php
@@ -76,40 +76,46 @@ abstract class Repository {
# Insert entity
#===========================================================================
public function insert(EntityInterface $Entity): bool {
- $attributes = $Entity->getFilteredAttributes();
-
- foreach($attributes as $field => $value) {
- $fields[] = $field;
+ foreach($Entity->getModifiedKeys() as $attribute) {
+ $params[] = $Entity->get($attribute);
+ $fields[] = $attribute;
$values[] = '?';
}
- $fields = implode(', ', $fields ?? []);
- $values = implode(', ', $values ?? []);
+ if(isset($params, $fields, $values)) {
+ $fields = implode(', ', $fields);
+ $values = implode(', ', $values);
- $query = 'INSERT INTO %s (%s) VALUES(%s)';
- $query = sprintf($query, static::getTableName(), $fields, $values);
+ $query = sprintf('INSERT INTO %s (%s) VALUES(%s)',
+ static::getTableName(), $fields, $values);
- $Statement = $this->Database->prepare($query);
- return $Statement->execute(array_values($attributes));
+ $Statement = $this->Database->prepare($query);
+ return $Statement->execute($params);
+ }
+
+ return FALSE;
}
#===========================================================================
# Update entity
#===========================================================================
public function update(EntityInterface $Entity): bool {
- $attributes = $Entity->getFilteredAttributes();
-
- foreach($attributes as $field => $value) {
- $params[] = "$field = ?";
+ foreach($Entity->getModifiedKeys() as $attribute) {
+ $params[] = $Entity->get($attribute);
+ $fields[] = "$attribute = ?";
}
- $params = implode(', ', $params ?? []);
+ if(isset($params, $fields)) {
+ $fields = implode(', ', $fields);
- $query = 'UPDATE %s SET %s WHERE id = '.intval($Entity->getID());
- $query = sprintf($query, static::getTableName(), $params);
+ $query = sprintf('UPDATE %s SET %s WHERE id = %d',
+ static::getTableName(), $fields, $Entity->getID());
- $Statement = $this->Database->prepare($query);
- return $Statement->execute(array_values($attributes));
+ $Statement = $this->Database->prepare($query);
+ return $Statement->execute($params);
+ }
+
+ return FALSE;
}
#===========================================================================