graham-campbell/manager
Laravel Manager provides a lightweight base for building driver-based “manager” services in Laravel apps. Supports PHP 7.4–8.5 and Laravel 8–13, offering consistent configuration, driver creation, and resolution patterns for your own integrations.
composer require graham-campbell/manager:^5.3
AbstractManager in your package:
use GrahamCampbell\Manager\AbstractManager;
class MyServiceManager extends AbstractManager
{
protected function createConnection(array $config): MyServiceInterface
{
return new MyService($config);
}
protected function getConfigName(): string
{
return 'myservice';
}
}
$this->app->singleton(MyServiceManager::class, function ($app) {
return new MyServiceManager($app);
});
config/myservice.php:
return [
'default' => 'driver_name',
'drivers' => [
'driver_name' => [
'key' => 'value',
],
],
];
Lazy-load a connection and call methods directly:
$manager = app(MyServiceManager::class);
$manager->methodOnDefaultConnection(); // Dynamic method call
// OR
$connection = $manager->connection('driver_name');
$connection->doSomething();
Driver-Based Service Resolution
extend() to dynamically add drivers:
$manager->extend('custom_driver', function ($app, array $config) {
return new CustomDriver($config);
});
connection() (cached) or reconnect() (fresh instance).Configuration Management
$config = $manager->getConnectionConfig('driver_name');
$manager->setDefaultConnection('driver_name');
$default = $manager->getDefaultConnection();
Dynamic Method Dispatch
$manager->uploadFile($file); // Delegates to default connection
Connection Pooling
$connections = $manager->getConnections();
$manager->disconnect('driver_name');
AbstractManager as the base for your package’s service manager (e.g., CacheManager, DatabaseManager).$manager = Mockery::mock(MyServiceManager::class);
$manager->shouldReceive('connection')
->with('driver_name')
->andReturn($mockConnection);
config/{package}.php under a drivers key.Connection Leaks
disconnect() can lead to memory leaks if connections are heavyweight (e.g., database, API clients).reconnect() to force a fresh instance when needed.Dynamic Method Calls
__call may accidentally trigger undefined methods if not guarded.__call in your manager to validate method existence:
public function __call($method, $parameters)
{
if (!method_exists($this->getDefaultConnection(), $method)) {
throw new BadMethodCallException("Method {$method} does not exist.");
}
return call_user_func_array([$this->getDefaultConnection(), $method], $parameters);
}
Config Validation
createConnection():
if (empty($config['required_key'])) {
throw new InvalidArgumentException('Config missing required key.');
}
Thread Safety
reconnect() or disconnect() before/after queue jobs.dd($manager->getConnections());
dd($manager->getConnectionConfig('driver_name'));
createConnection() to trace driver initialization:
\Log::debug('Creating connection for driver: ' . $config['driver']);
Custom Drivers
$manager->extend('new_driver', function ($app, array $config) {
return new NewDriver($config);
});
Config Overrides
getNamedConfig() to fetch config for a specific driver:
$config = $manager->getNamedConfig('driver_name');
Event Hooks
ConnectionCreated, ConnectionDisconnected):
protected function createConnection(array $config)
{
event(new ConnectionCreating($config));
$connection = new MyService($config);
event(new ConnectionCreated($connection));
return $connection;
}
connection().reconnect(): Use sparingly—it bypasses the pool and may duplicate resources.How can I help you explore Laravel packages today?