DbRecord

DbRecord is a lightweight active record implementation built on top of PDO.

An active record is an object that represents a database record. It can be used to create / update / delete entities in db tables without writing any sql requests.

Moreover, inherited class represents a model entity where instance of it can be used in a controller (See Controllers) or in a view script (See Views).

installation

composer require piko/db-record

This command will install the DbRecord components.

The component needs a PDO connexion. Ensure that a PDO component is registered in the application configuration.

Example of Mysql configuration:

return [
    //...
    'components' => [
        PDO::class => [
            'construct' => [
                'mysql:dbname=' . getenv('MYSQL_DB') . ';host=' . getenv('MYSQL_HOST'),
                getenv('MYSQL_USER'),
                getenv('MYSQL_PASSWORD'),
            ]
        ],
    ],
];

Suppose we have a table in our database created with :

CREATE TABLE contact (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  `order` INTEGER
)

To represent the model entity of the contact table, we have to declare a class Contact that inherit from DbRecord. In this declaration, we have to set two properties: $tableName which is the entity’s table name and $schema which is the entity’s schema as declared above:

use Piko\DbRecord;

class Contact extends DbRecord
{
    protected $tableName = 'contact';

    protected $schema = [
        'id'        => self::TYPE_INT,
        'name'      => self::TYPE_STRING,
        'order'     => self::TYPE_INT
    ];
}

Contact class usage:

$db = $app->getComponent(PDO::class);

// Create entity
$contact = new Contact($db);
$contact->name = 'Joe';
$contact->order = 1;
$contact->save();

echo $contact->id; // 1

$st = $db->prepare('SELECT * FROM contact');
$st->execute();

// Returns an array of Contact instances
$rows = $st->fetchAll(PDO::FETCH_CLASS, 'Contact'); 

print_r($rows);

// Update entity
$contact = new Contact(1); // Loads entity with id = 1
echo $contact->name; // Joe
$contact->name = 'John';
$contact->save();

$contact = new Contact(1);
echo $contact->name; // John

// Delete entity
$contact->delete();

print_r($st->fetchAll());

DbRecord events

Concept of events

beforeSave

Before saving an entity in the database, dbRecord check if the operation is possible by invoking the beforeSave method. This method also trigger a BeforeSaveEvent.

It is possible to customize this behavior in two ways:

Override beforeSave method in the inherited class:

use Piko\DbRecord;

class Contact extends DbRecord
{
    //...

    protected function beforeSave(): bool
    {
        if (!$this->name) {
            return false;
        }

        return parent::beforeSave();
    }
}

Using an event listener:

use Piko\DbRecord\Event\BeforeSaveEvent;
//...
$contact = new Contact($db);
$contact->on(BeforeSaveEvent::class, function(BeforeSaveEvent $event) {
    if (!$event->record->name) {
        return false;
    }
});

beforeDelete

It’s possible to interact with the beforeDelete event in the same way than the beforeSave event. See beforeDelete method. This method also trigger a BeforeDeleteEvent.

afterSave

After saving an entity in the database, dbRecord invokes the afterSave method. This method also trigger an AfterSaveEvent..

It is possible to customize this behavior in two ways:

Override afterSave method in the inherited class:

use Piko\DbRecord;

class Contact extends DbRecord
{
    //...

    protected function afterSave(): void
    {
        // Do something particular
        return parent::afterSave();
    }
}

Using a callback listening the event:

use Piko\DbRecord\Event\AfterSaveEvent;
// ...
$contact = new Contact($db);
$contact->on(AfterSaveEvent::class, function(AfterSaveEvent $event) {
    // Do something particular
});

afterDelete

It’s possible to interact with the afterDelete event in the same way than the afterSave event. See afterDelete method. This method also trigger an AfterDeleteEvent..