solophp / abstract-repository
An abstract repository implementation for PHP applications, providing a standardized way to interact with database tables using the Solo Query Builder.
v1.3.0
2025-06-04 11:26 UTC
Requires
- php: >=8.2
- solophp/query-builder: ^2.0
README
An abstract repository implementation for PHP applications, providing a standardized way to interact with database tables using the Solo Query Builder.
Installation
composer require solophp/abstract-repository
Features
- 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
Basic Usage
Creating a Repository
<?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']); } }
Basic Operations
// 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']);
Advanced Usage
Querying with Criteria
// 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']);
Aggregation Functions
// 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]);
Working with Soft Deletes
// 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);
Record Existence Checks
// 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 );
Bulk Operations
// 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);
Transaction Support
// 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]); // ... });
Available Methods
Read Operations
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 |
Write Operations
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 |
Aggregation Operations
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 |
Utility Methods
Method | Description |
---|---|
exists(array $criteria): bool |
Check if a record exists |
existsExcluding(array $criteria, int $excludeId): bool |
Check if a record exists, excluding ID |
Transaction Methods
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 |
Requirements
- PHP 8.2 or higher
- solophp/query-builder package
License
The MIT License (MIT). Please see License File for more information.