An abstract repository implementation for PHP applications, providing a standardized way to interact with database tables using the Solo Query Builder.
composer require solophp/abstract-repository
- Unified Repository Pattern: Standardized interface for database operations
- CRUD Operations: Complete set of Create, Read, Update, Delete methods
- Aggregation Functions: Built-in support for SUM, COUNT, AVG, MAX, MIN operations
- Bulk Operations: Mass update and delete operations with WHERE conditions
- Filtering and Sorting: Flexible criteria-based querying with sorting options
- Soft Delete Support: Optional soft deletion with restore capabilities
- Pagination: Built-in support for paginated results
- Record Synchronization: Efficient bulk operations for synchronizing datasets
- Transaction Support: Atomic operations for data integrity
<?php
namespace App\Repositories;
use Solo\AbstractRepository\Repository;
use Solo\QueryBuilder\Facade\Query;
class UserRepository extends Repository
{
// Optionally enable soft deletes
protected bool $softDeletes = true;
// Override primary key if not 'id'
protected string $primaryKey = 'user_id';
public function __construct(Query $queryBuilder)
{
parent::__construct($queryBuilder, 'users');
}
// Add your custom repository methods here
public function findActiveUsers(): array
{
return $this->getBy(['status' => 'active']);
}
}
// Instantiate your repository
$userRepo = new UserRepository($queryBuilder);
// Get by ID
$user = $userRepo->getById(123);
// Get all records
$allUsers = $userRepo->getAll();
// Create a new record
$userId = $userRepo->insert([
'name' => 'John Doe',
'email' => 'john@example.com',
'created_at' => date('Y-m-d H:i:s')
]);
// Insert multiple records
$affectedRows = $userRepo->insertBatch([
['name' => 'John Doe', 'email' => 'john@example.com'],
['name' => 'Jane Smith', 'email' => 'jane@example.com']
]);
// Update a record
$userRepo->update(123, [
'name' => 'Jane Smith',
'updated_at' => date('Y-m-d H:i:s')
]);
// Update multiple records by criteria
$affectedRows = $userRepo->updateBy(
['status' => 'pending'],
['status' => 'active', 'updated_at' => date('Y-m-d H:i:s')]
);
// Delete a record (soft delete if enabled)
$userRepo->deleteById(123);
// Delete multiple records by criteria (soft delete if enabled)
$userRepo->deleteBy(['status' => 'suspended']);
// Find records with criteria
$admins = $userRepo->getBy([
'role' => 'admin',
'status' => 'active'
]);
// With ordering
$sortedAdmins = $userRepo->getBy(
['role' => 'admin'],
['last_login' => 'DESC']
);
// With pagination
$paginatedUsers = $userRepo->getBy(
['status' => 'active'],
['created_at' => 'DESC'],
10, // limit per page
2 // page number
);
// Find first matching record
$firstAdmin = $userRepo->getFirstBy(['role' => 'admin']);
// Calculate sum of a field
$totalSales = $orderRepo->sumBy(['status' => 'completed'], 'total');
// Count records matching criteria
$activeUsers = $userRepo->countBy(['status' => 'active']);
$pendingOrders = $orderRepo->countBy(['status' => 'pending']);
// Calculate average
$avgOrderValue = $orderRepo->avgBy(['status' => 'completed'], 'total');
$avgUserAge = $userRepo->avgBy(['role' => 'customer'], 'age');
// Find maximum value
$highestOrder = $orderRepo->maxBy(['user_id' => 123], 'total');
$latestLogin = $userRepo->maxBy(['status' => 'active'], 'last_login');
// Find minimum value
$smallestOrder = $orderRepo->minBy(['user_id' => 123], 'total');
$earliestUser = $userRepo->minBy([], 'created_at');
// Real-world examples
$monthlyRevenue = $orderRepo->sumBy([
'status' => 'paid',
'created_at >=' => '2025-05-01'
], 'total');
$unverifiedPayments = $paymentRepo->countBy(['is_verified' => 0]);
// Soft delete (if enabled)
$userRepo->deleteById(123);
// Force delete (bypasses soft delete)
$userRepo->forceDeleteById(123);
// Soft delete multiple records (if enabled)
$userRepo->deleteBy(['status' => 'suspended']);
// Force delete multiple records (bypasses soft delete)
$userRepo->forceDeleteBy(['status' => 'suspended']);
// Get soft-deleted records
$deletedUsers = $userRepo->getDeleted();
// Restore a soft-deleted record
$userRepo->restoreById(123);
// Check if record exists with the email
$exists = $userRepo->exists(['email' => 'john@example.com']);
// Check if another record exists with the same email (excluding current record)
$duplicateExists = $userRepo->existsExcluding(
['email' => 'john@example.com'],
123
);
// Update multiple records matching criteria
$userRepo->updateBy(
['department' => 'IT', 'status' => 'active'],
['bonus_eligible' => true, 'updated_at' => date('Y-m-d H:i:s')]
);
// Delete multiple records matching criteria (respects soft deletes)
$userRepo->deleteBy(['status' => 'suspended']);
// Force delete multiple records (bypasses soft deletes)
$userRepo->forceDeleteBy(['status' => 'banned']);
// Synchronize collections
// - Creates new records
// - Updates existing records
// - Deletes records not in the newUsers array
$userRepo->syncById($newUsers, $currentUsers);
// Start a transaction manually
$userRepo->beginTransaction();
try {
$userId = $userRepo->insert(['name' => 'New User']);
$userRepo->update($userId, ['profile_created' => true]);
$userRepo->commit();
} catch (\Throwable $e) {
$userRepo->rollBack();
throw $e;
}
// Or use the convenient withTransaction method
$userRepo->withTransaction(function(Repository $repo) {
// Multiple operations in a single transaction
$userId = $repo->insert(['name' => 'New User']);
$repo->update($userId, ['profile_created' => true]);
// ...
});
Method | Description |
---|---|
getById(int $id): ?object |
Get a record by primary key |
getAll(): array |
Get all records |
getFirstBy(array $criteria, ?array $orderBy = null): ?object |
Get first record matching criteria |
getBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $page = null): array |
Get records matching criteria |
getDeleted(): array |
Get soft-deleted records |
Method | Description |
---|---|
insert(array $data): ?int |
Insert a single record and return its ID |
insertBatch(array $records): int |
Insert multiple records and return affected rows |
update(int $id, array $data): int |
Update a record |
updateBy(array $criteria, array $data): int |
Update records matching criteria |
deleteById(int $id): int |
Delete a record (soft if enabled) |
forceDeleteById(int $id): int |
Force delete a record |
deleteBy(array $criteria): int |
Delete records matching criteria (soft if enabled) |
forceDeleteBy(array $criteria): int |
Force delete records matching criteria |
restoreById(int $id): int |
Restore a soft-deleted record |
syncById(array $newRecords, array $currentRecords): void |
Synchronize records |
Method | Description |
---|---|
sumBy(array $criteria, string $field): float |
Calculate sum of a field |
countBy(array $criteria): int |
Count records matching criteria |
avgBy(array $criteria, string $field): float |
Calculate average value of a field |
maxBy(array $criteria, string $field): mixed |
Find maximum value of a field |
minBy(array $criteria, string $field): mixed |
Find minimum value of a field |
Method | Description |
---|---|
exists(array $criteria): bool |
Check if a record exists |
existsExcluding(array $criteria, int $excludeId): bool |
Check if a record exists, excluding ID |
Method | Description |
---|---|
beginTransaction(): bool |
Start a transaction |
commit(): bool |
Commit the current transaction |
rollBack(): bool |
Roll back the current transaction |
inTransaction(): bool |
Check if a transaction is currently active |
withTransaction(callable $callback): mixed |
Execute callback within transaction |
- PHP 8.2 or higher
- solophp/query-builder package
The MIT License (MIT). Please see License File for more information.