atlas/pdo
Decorates any PDO instance with a Connection that adds perform() (query + bind in one call), handy fetch*/yield* helpers, and query logging with backtraces. Includes a ConnectionLocator to manage named default/read/write connections.
DB facade already uses decorators (e.g., Connection, Grammar), so integrating Atlas.Pdo as a custom decorator layer is low-friction. This enables cross-cutting concerns like query logging, retries, or metrics without polluting business logic.ConnectionLocator abstracts read/write separation, which maps directly to Laravel’s connections configuration and DB::connection() method. However, Atlas.Pdo’s locator is more explicit about named connections (e.g., getRead() vs. Laravel’s dynamic read/write aliases), requiring alignment with Laravel’s multi-database strategies.perform(), fetch*(), and yield*() reduce boilerplate for raw SQL, complementing Laravel’s query builder but targeting use cases where:
yield* for large datasets).perform()).connection() method but offers finer-grained control. This is useful for:
DB facade is built on PDO, Atlas.Pdo integrates at the same layer. The decorator pattern ensures no breaking changes to Laravel’s core DB stack.ConnectionLocator can be registered as a Laravel service provider singleton, enabling DI:
$this->app->singleton(ConnectionLocator::class, function ($app) {
$locator = new ConnectionLocator();
// Configure connections (e.g., from Laravel's config/database.php)
return $locator;
});
Connections can then be injected into repositories/services:
public function __construct(private ConnectionLocator $locator) {}
DB syntax:
// AtlasFacade.php
class AtlasFacade extends Facade {
protected static function getFacadeAccessor() { return 'atlas.locator'; }
}
Usage:
$user = Atlas::perform("SELECT * FROM users WHERE id = ?", [$id])->fetch();
Atlas.Pdo and Laravel’s query builder can coexist. For example:
Atlas.Pdo for raw SQL or complex queries.prepare() + execute() with perform().fetch() loops with fetch*() or yield*().DB::connection() calls with ConnectionLocator where needed.#[ReturnTypeWillChange]) and assess Laravel compatibility.DB::reconnect() or Atlas.Pdo’s persistent connections for long-running processes.pdo_mysql_statistics().Atlas.Pdo for raw SQL or performance-critical paths.Atlas.Pdo for SQL").Atlas.Pdo updates. Mitigation:
Atlas.Pdo replace all raw PDO usage, or only specific paths (e.g., legacy code, reporting)?ConnectionLocator mirror Laravel’s config/database.php exactly, or use a custom schema?mysql/pgsql poolers)?perform() binding)?Atlas.Pdo logs be surfaced in Laravel Debugbar/Telescope?ConnectionLocator can be registered as a singleton, enabling DI.config/database.php for connection strings.composer require atlas/pdo.ConnectionLocator.queries channel).ConnectionLocator:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(ConnectionLocator::class, function ($app) {
$locator = new ConnectionLocator();
// Configure connections from Laravel's config/database.php
foreach (config('database.connections') as $name => $config) {
$locator->register($name, new Connection(
new PDO($config['dsn'], $config['username'], $config['password'])
));
}
return $locator;
});
}
// app/Facades/Atlas.php
class Atlas extends Facade {
protected static function getFacadeAccessor() { return 'atlas.locator'; }
}
prepare() + execute() with perform():
// Before
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
How can I help you explore Laravel packages today?