Pular para o conteúdo principal

The Repository class

The Repository class is the class that connects the model with the database.

To achieve this, you need to create an instance of the Repository class and pass the database driver and the model class.

$dbDriver = \ByJG\AnyDataset\Db\Factory::getDbInstance('mysql://user:password@server/schema');

$repository = new \ByJG\MicroOrm\Repository($dbDriver, MyModel::class);

Read and Write Separation

When you create a repository, it uses the same database connection for both read and write operations.

However, in some cases, you may want to use separate database connections for read and write operations. This is useful for database replication scenarios where you have a master database for writing and one or more read-only replicas for reading.

To configure separate database connections, you can use the addDbDriverForWrite method:

// Main connection used for reading
$dbDriverRead = \ByJG\AnyDataset\Db\Factory::getDbInstance('mysql://user:password@readserver/schema');

// Separate connection for write operations
$dbDriverWrite = \ByJG\AnyDataset\Db\Factory::getDbInstance('mysql://user:password@writeserver/schema');

$repository = new \ByJG\MicroOrm\Repository($dbDriverRead, MyModel::class);
$repository->addDbDriverForWrite($dbDriverWrite);

Alternatively, you can use the setRepositoryReadOnly method to make the repository read-only:

$repository->setRepositoryReadOnly();

Repository Helper Methods

The Repository class has the following helper methods:

entity

The entity method creates an instance of the model with the properties set.

$model = $repository->entity([
'company_id' => 1
]);

queryInstance

The queryInstance method creates an instance of the Query class pre-setting the table and filters based on the Mapper and in the values of the model.

$model = $repository->entity();
$model->setCompanyId(1);
$query = $repository->queryInstance($model);

You can also add additional tables for joins:

$query = $repository->queryInstance($model, 'other_table', 'third_table');

getMapper

The getMapper method returns the Mapper object that defines the relationship between the model and the database.

$mapper = $repository->getMapper();

getDbDriver

The getDbDriver method returns the database driver used for read operations. It allows you to use SQL commands directly. To find more about the database driver, please refer to the AnyDataset documentation and the Query.

$dbDriver = $repository->getDbDriver();
$iterator = $dbDriver->getIterator('select * from mytable');

getDbDriverWrite

The getDbDriverWrite method returns the database driver used for write operations. If no separate write driver was configured, it returns the same driver as getDbDriver().

$dbDriverWrite = $repository->getDbDriverWrite();

Repository Query Methods

The Repository class has the following methods for querying data:

get

The get method retrieves a record from the database by the primary key.

$myModel = $repository->get(1);

You can also use an array for composite primary keys:

$myModel = $repository->get(['id' => 1, 'type' => 'user']);

getByFilter

The getByFilter method retrieves an array of models from the database using an IteratorFilter.

use ByJG\AnyDataset\Core\IteratorFilter;
use ByJG\AnyDataset\Core\Enum\Relation;

$filter = new IteratorFilter();
$filter->addRelation('name', Relation::EQUAL, 'John');

$result = $repository->getByFilter($filter);

You can also add pagination:

// Get page 2 with 10 items per page
$result = $repository->getByFilter($filter, page: 2, limit: 10);

getByQuery

The getByQuery method retrieves an array of the model from the database by a query.

$query = Query::getInstance()
->where('company_id = :cid', ['cid' => 1])
->orderBy('name');

$result = $repository->getByQuery($query);

Or, build a query from a filter model:

$filterModel = $repository->entity([
'company_id' => 1
]);

$query = $repository->queryInstance($filterModel);
$query->orderBy('name');

$result = $repository->getByQuery($query);

You can also join with other tables/mappers:

$query = Query::getInstance()
->table('users')
->join('orders', 'users.id = orders.user_id');

$result = $repository->getByQuery($query, [$orderRepository->getMapper()]);

getByQueryRaw

The getByQueryRaw method retrieves raw data from the database (array of associative arrays) instead of model instances:

$query = Query::getInstance()
->field('name')
->field('COUNT(*) as count')
->groupBy('name');

$result = $repository->getByQueryRaw($query);

getScalar

The getScalar method retrieves a single scalar value from the database by a query.

$query = Query::getInstance()
->field('count(*)')
->where('company_id = :cid', ['cid' => 1]);

$result = $repository->getScalar($query);

filterIn

The filterIn method retrieves records that match an array of values for a specific field:

// Get users with ids in [1, 2, 5]
$users = $repository->filterIn([1, 2, 5]);

// Get users with specific names
$users = $repository->filterIn(['John', 'Jane', 'Bob'], 'name');

Repository Update Methods

The Repository class has the following methods for modifying data:

save

Update or insert a record in the database. If the primary key is set, it will update the record. Otherwise, it will insert a new record.

$myModel = $repository->get(1);
$myModel->setName('New Name');
$repository->save($myModel);

You can also use update constraints:

use ByJG\MicroOrm\UpdateConstraint;

$updateConstraint = new UpdateConstraint();
$updateConstraint->addField('name');
$updateConstraint->addField('email');

$myModel = $repository->get(1);
$myModel->setName('New Name');
$myModel->setEmail('newemail@example.com');
$myModel->setAge(30); // This won't be updated due to constraint

$repository->save($myModel, $updateConstraint);

delete

Delete a record from the database by its primary key:

$repository->delete(1);

Or by a composite key:

$repository->delete(['id' => 1, 'type' => 'user']);

deleteByQuery

Delete records from the database by a query allowing complex filters.

$deleteQuery = DeleteQuery::getInstance()
->table('users')
->where('name like :name', ['name'=>'Jane%']);

$repository->deleteByQuery($deleteQuery);

Hook Methods

setBeforeInsert

Set a processor to be called before inserting a record. You can use either a closure or an implementation of EntityProcessorInterface.

// Using a closure
$repository->setBeforeInsert(function($instance) {
// Modify the instance before inserting
$instance->createdAt = date('Y-m-d H:i:s');
return $instance;
});

// Using EntityProcessorInterface (recommended)
use ByJG\MicroOrm\Interface\EntityProcessorInterface;
use Override;

class BeforeInsertProcessor implements EntityProcessorInterface
{
#[Override]
public function process(array $instance): array
{
// Modify the instance before inserting
if (!isset($instance['created_at'])) {
$instance['created_at'] = date('Y-m-d H:i:s');
}
return $instance;
}
}

$repository->setBeforeInsert(new BeforeInsertProcessor());

setBeforeUpdate

Set a processor to be called before updating a record. You can use either a closure or an implementation of EntityProcessorInterface.

// Using a closure
$repository->setBeforeUpdate(function($instance) {
// Modify the instance before updating
$instance->updatedAt = date('Y-m-d H:i:s');
return $instance;
});

// Using EntityProcessorInterface (recommended)
use ByJG\MicroOrm\Interface\EntityProcessorInterface;
use Override;

class BeforeUpdateProcessor implements EntityProcessorInterface
{
#[Override]
public function process(array $instance): array
{
// Modify the instance before updating
if (!isset($instance['updated_at'])) {
$instance['updated_at'] = date('Y-m-d H:i:s');
}
return $instance;
}
}

$repository->setBeforeUpdate(new BeforeUpdateProcessor());

Observers

addObserver

Add an observer to the repository to monitor database operations.

class MyObserver implements ObserverProcessorInterface
{
public function update(ObserverData $observerData): void
{
// Process the update event
$action = $observerData->getAction(); // INSERT, UPDATE, DELETE
$model = $observerData->getModel();
$oldModel = $observerData->getOldModel();
}
}

$repository->addObserver(new MyObserver());

See Observers for more details.