diff --git a/lib/models/SimpleORMap.class.php b/lib/models/SimpleORMap.class.php
index 4bce0cf05409ea81906391dfb574a847841fe2d7..ab00b3d178bcce6e57ae4514bf9c8468099e26d4 100644
--- a/lib/models/SimpleORMap.class.php
+++ b/lib/models/SimpleORMap.class.php
@@ -16,6 +16,8 @@
 
 class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
 {
+    use SimpleORMapConfigurationTrait;
+
     /**
      * Defines `_` as character used when joining composite primary keys.
      */
diff --git a/lib/models/SimpleORMapConfigurationTrait.php b/lib/models/SimpleORMapConfigurationTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..675752a1ce16e1f6558ee94ed7766b8aef80f355
--- /dev/null
+++ b/lib/models/SimpleORMapConfigurationTrait.php
@@ -0,0 +1,124 @@
+<?php
+trait SimpleORMapConfigurationTrait
+{
+    protected static function configureDbTable(array &$config, string $db_table)
+    {
+        $config['db_table'] = $db_table;
+    }
+
+    // Relationships
+    protected static function configureBelongsTo(array &$config, string $relation, string $class_name, array $options = [])
+    {
+        self::configureRelation($config, 'belongs_to', $relation, $class_name, $options);
+    }
+
+    protected static function configureHasOne(array &$config, string $relation, string $class_name, array $options = [])
+    {
+        self::configureRelation($config, 'has_one', $relation, $class_name, $options);
+    }
+
+    protected static function configureHasMany(array &$config, string $relation, string $class_name, array $options = [])
+    {
+        self::configureRelation($config, 'has_many', $relation, $class_name, $options);
+    }
+
+    protected static function configureHasAndBelongsToMany(array &$config, string $relation, string $class_name, array $options = [])
+    {
+        self::configureRelation($config, 'has_and_belongs_to_many', $relation, $class_name, $options);
+    }
+
+    private static function configureRelation(array &$config, string $relation_type, string $relation, string $class_name, array $options = [])
+    {
+        if (!self::validateRelationOptions($relation_type, $options)) {
+            throw new Exception('Options for relation are invalid');
+        }
+
+        if (!isset($config[$relation_type])) {
+            $config[$relation_type] = [];
+        }
+
+        $config[$relation_type][$relation] = array_merge(compact('class_name'), $options);
+    }
+
+    private static function validateRelationOptions(string $relation_type, array $options): bool
+    {
+        return true;
+    }
+
+    // Callbacks
+    protected static function registerBeforeCreateCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'before_create', $callback, $prepend);
+    }
+
+    protected static function registerAfterCreateCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'after_create', $callback, $prepend);
+    }
+
+    protected static function registerBeforeUpdateCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'before_update', $callback, $prepend);
+    }
+
+    protected static function registerAfterUpdateCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'after_update', $callback, $prepend);
+    }
+
+    protected static function registerBeforeStoreCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'before_store', $callback, $prepend);
+    }
+
+    protected static function registerAfterStoreCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'after_store', $callback, $prepend);
+    }
+
+    protected static function registerBeforeDeleteCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'before_delete', $callback, $prepend);
+    }
+
+    protected static function registerAfterDeleteCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'after_delete', $callback, $prepend);
+    }
+
+    protected static function registerBeforeInitializeCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'before_initialize', $callback, $prepend);
+    }
+
+    protected static function registerAfterInitializeCallback(array &$config, $callback, bool $prepend = false)
+    {
+        self::registerCallback($config, 'after_initialize', $callback, $prepend);
+    }
+
+    protected static function registerCallback(array &$config, string $callback_type, $callback, bool $prepend = false)
+    {
+        if (!self::validateCallback($callback)) {
+            throw new Exception('Callback is invalid');
+        }
+
+        if (!isset($config['registered_callbacks'])) {
+            $config['registered_callbacks'] = [];
+        }
+
+        if (!isset($config['registered_callbacks'][$callback_type])) {
+            $config['registered_callbacks'][$callback_type] = [];
+        }
+
+        if ($prepend) {
+            array_unshift($config['registered_callbacks'][$callback_type], $callback);
+        } else {
+            $config['registered_callbacks'][$callback_type][] = $callback;
+        }
+    }
+
+    private static function validateCallback($callback): bool
+    {
+        return true;
+    }
+}