Installation
composer require aaronadal/persistence-bundle
Register the bundle in config/app.php under providers:
Aaronadal\PersistenceBundle\PersistenceServiceProvider::class,
Basic Configuration Publish the config file:
php artisan vendor:publish --provider="Aaronadal\PersistenceBundle\PersistenceServiceProvider" --tag="config"
Edit config/persistence.php to define your default repository and entity mappings.
First Use Case: Querying Entities
Inject the PersistenceManager into a service/controller:
use Aaronadal\PersistenceBundle\PersistenceManager;
class UserController extends Controller
{
protected $persistence;
public function __construct(PersistenceManager $persistence)
{
$this->persistence = $persistence;
}
public function index()
{
$users = $this->persistence->findAll(User::class);
return view('users.index', compact('users'));
}
}
Define Custom Repositories
Extend Aaronadal\PersistenceBundle\AbstractRepository for domain-specific logic:
namespace App\Repositories;
use Aaronadal\PersistenceBundle\AbstractRepository;
use App\Models\User;
class UserRepository extends AbstractRepository
{
public function findActiveUsers()
{
return $this->createQueryBuilder('u')
->where('u.is_active = :active')
->setParameter('active', true)
->getQuery()
->getResult();
}
}
Register Repositories
Bind repositories in PersistenceServiceProvider or via config:
$this->app->bind(UserRepository::class, function ($app) {
return new UserRepository($app->make('doctrine')->getManager());
});
Fluent Query Interface
Use the PersistenceManager to build queries dynamically:
$query = $this->persistence
->createQueryBuilder(User::class, 'u')
->where('u.email LIKE :email')
->setParameter('email', '%@example.com')
->orderBy('u.created_at', 'DESC')
->getQuery();
Pagination Integrate with Laravel’s pagination:
use Aaronadal\PersistenceBundle\Pagination\Paginator;
$paginator = new Paginator($this->persistence);
$users = $paginator->paginate(User::class, request('page', 1), 10);
Service Container Binding
Bind the PersistenceManager to a custom interface for better testability:
$this->app->bind(
\App\Contracts\PersistenceInterface::class,
\Aaronadal\PersistenceBundle\PersistenceManager::class
);
Event Listeners
Attach listeners to repository events (e.g., prePersist, postRemove):
$this->persistence->getEventManager()->addEventListener(
\Doctrine\ORM\Events::prePersist,
function ($event) {
$entity = $event->getEntity();
if ($entity instanceof User) {
$entity->setUpdatedAt(new \DateTime());
}
}
);
Entity Manager Injection
EntityManager. If using multiple managers (e.g., default and read), configure the bundle explicitly in config/persistence.php:
'entity_managers' => [
'default' => 'doctrine.orm.entity_manager',
'read' => 'doctrine.orm.read_entity_manager',
],
Query Caching
config/persistence.php:
'query_cache' => true,
Repository Autowiring
PersistenceManager to fetch repositories dynamically:
// ❌ Avoid (tight coupling)
public function __construct(UserRepository $repository) {}
// ✅ Preferred
public function __construct(PersistenceManager $persistence) {
$this->repository = $this->persistence->getRepository(User::class);
}
Query Logging
Enable SQL logging in config/persistence.php:
'logging' => true,
Logs will appear in storage/logs/laravel.log.
Event Debugging Dump event arguments for debugging:
$this->persistence->getEventManager()->addEventListener(
\Doctrine\ORM\Events::onFlush,
function ($event) {
\Log::debug('Flush event:', $event->getEntityManager()->getUnitOfWork()->getScheduledEntityInsertions());
}
);
Custom Query Types
Extend the bundle’s QueryBuilder to support custom DQL functions:
namespace Aaronadal\PersistenceBundle\Query;
class CustomQueryBuilder extends QueryBuilder
{
public function distance($x, $y)
{
return $this->expr()->func('DISTANCE', [$x, $y]);
}
}
Register the custom builder in the service provider.
Repository Factories Override the default repository factory to enforce custom implementations:
$this->app->bind(
\Aaronadal\PersistenceBundle\RepositoryFactory::class,
function ($app) {
return new CustomRepositoryFactory($app);
}
);
Transaction Management Use the bundle’s transaction helpers for complex operations:
$this->persistence->transactional(function () {
$user = $this->persistence->find(User::class, 1);
$user->update(['role' => 'admin']);
$this->persistence->flush();
});
How can I help you explore Laravel packages today?