DatabaseObject library is a set of classes that make work with database just a bit easier. Here are the key concepts:
- Types - entities that map to a single table,
- Entities - type instances that map to a single row of a type table,
- Entity Manager - instances that provide access to custom type specific manipulation methods,
- Collections - a group of objects that meets the given criteria. This group is perfect for HTTP responses because collections support data tagging and tag validation (ETag and HTTP 304),
- Pool - manage registered types and make multi-type interaction possible,
- Producers - customise the way pool produces new instances,
- Validators - validate object properties before saving them to the database.
If you wish to work with entire tables, use CRUD methods provided by ConnectionInterface
:
ConnectionInterface::insert()
- insert one or more rowsConnectionInterface::update()
- update a set of rows that match the given conditions, if anyConnectionInterface::delete()
- drop a set of rows taht match the given conditions, if any
When you need to work with individual instances, PoolInterface
provides following handy methods:
PoolInterface::produce()
- create a new record based on the given parameters,PoolInterface::modify()
- change the given object with a set of parameters,PoolInterface::scrap()
- trash or permanently delete the given object.
Recently we added ScrapInterface
. This interface should be implemented by models which support object trashing, instead of instant deletion. When PoolInterface::scrap()
method is called, objects that implement ScrapInterface
will be scrapped (marked as deleted or trashed, depending on a particular implementation), instead of being permanently deleted.
To set conditions, use where
method:
$pool->find(Writer::class)
->where('`birthday` > ?', '1800-01-01')
->ids();
This method can be called multiple times, and all conditions will be joined in one block with AND
operator:
$pool->find(Writer::class)
->where('`birthday` > ?', '1800-01-01')
->where('`birthday` < ?', '1825-01-01')
->ids();
Finder can join a table, either by table name:
$pool->find(Writer::class)
->joinTable('writer_groups')
->where('`writer_groups`.`group_id` = ?', $group_id)
->ids();
or by related type:
$pool->find(Writer::class)
->join(WriterGroup::class)
->where('`writer_groups`.`group_id` = ?', $group_id)
->ids();
Note that in the second case, WriterGroup
type needs to be registered in the pool.
Pool implements ActiveCollab\ContainerAccess\ContainerAccessInterface
, so you can set any container that implements Interop\Container\ContainerInterface
interface, and that container will be passed on and made available in finders, producers and objects:
$container = new Container([
'dependency' => 'it works!',
]);
$pool->setContainer($container);
foreach ($pool->find(Writer::class)->all() as $writer) {
print $writer->dependency . "\n"; // Prints it works!
}
Generated fields are fields that exist in tables, but they are not controlled or managed by the entity class itself. Instead, values of these models are set elsewhere:
- They are specifief as generated columns in table's definition,
- Trigger set the values,
- Values are set by external systems or processes.
Library provides access to values of these fields, via accessors methods, but these values can't be set using setter methods:
<?php
use ActiveCollab\DatabaseObject\Entity\Entity;
class StatsSnapshot extends Entity
{
/**
* Generated fields that are loaded, but not managed by the entity.
*
* @var array
*/
protected $generated_fields = ['is_used_on_day', 'plan_name', 'number_of_users'];
/**
* Return value of is_used_on_day field.
*
* @return bool
*/
public function isUsedOnDay()
{
return $this->getFieldValue('is_used_on_day');
}
/**
* Return value of is_used_on_day field.
*
* @return bool
* @deprecated use isUsedOnDay()
*/
public function getIsUsedOnDay()
{
return $this->getFieldValue('is_used_on_day');
}
/**
* Return value of plan_name field.
*
* @return string
*/
public function getPlanName()
{
return $this->getFieldValue('plan_name');
}
/**
* Return value of number_of_users field.
*
* @return int
*/
public function getNumberOfUsers()
{
return $this->getFieldValue('number_of_users');
}
}
Value casting can be set during entity configuration:
<?php
use ActiveCollab\DatabaseConnection\Record\ValueCaster;
use ActiveCollab\DatabaseConnection\Record\ValueCasterInterface;
use ActiveCollab\DatabaseObject\Entity\Entity;
class StatsSnapshot extends Entity
{
protected function configure(): void
{
$this->setGeneratedFieldsValueCaster(new ValueCaster([
'is_used_on_day' => ValueCasterInterface::CAST_BOOL,
'plan_name' => ValueCasterInterface::CAST_STRING,
'number_of_users' => ValueCasterInterface::CAST_INT,
]));
}
}
Entity class also refreshes the values of these fields on object save so fresh values are instantly available in case they are recalculated in the background (by a trigger or generated field expression).
- Caching,
Remove deprecatedObjectInterface
andObject
class.