nyholm/dsn
PHP DSN parser and value object for working with connection strings. Parse and normalize DSNs for common schemes, access components like scheme, host, port, user and path, and build DSNs safely for databases, queues, mailers and more.
Installation:
composer require nyholm/dsn
No additional configuration is required—just autoload the package.
First Use Case: Parse a DSN (Data Source Name) string into a structured array:
use Nyholm\Dsn\Dsn;
$dsn = Dsn::fromString('amqp://user:pass@host:5672/vhost?option=value');
$parsed = $dsn->toArray();
// Returns:
// [
// 'scheme' => 'amqp',
// 'user' => 'user',
// 'pass' => 'pass',
// 'host' => 'host',
// 'port' => 5672,
// 'path' => '/vhost',
// 'query' => ['option' => 'value'],
// ]
Where to Look First:
Nyholm\Dsn\Dsn class methods: fromString(), toArray(), toString().tests/ folder) for edge cases.Parsing DSNs in Config:
// config/broadcasting.php
'connections' => [
'amqp' => [
'dsn' => env('AMQP_DSN'),
'options' => [],
],
],
Parse in a service provider:
$dsn = Dsn::fromString(config('broadcasting.connections.amqp.dsn'));
$config = $dsn->toArray();
Dynamic DSN Generation:
$dsn = (new Dsn())
->setScheme('redis')
->setHost('127.0.0.1')
->setPort(6379)
->setUser('user')
->setPass('pass');
$connectionString = $dsn->toString(); // "redis://user:pass@127.0.0.1:6379"
Validation + Parsing:
use Nyholm\Dsn\Exception\InvalidDsnException;
try {
$dsn = Dsn::fromString($input);
// Proceed with validated DSN.
} catch (InvalidDsnException $e) {
abort(422, 'Invalid DSN format.');
}
Query Parameter Handling:
$dsn = Dsn::fromString('postgres://user:pass@host/db?sslmode=require&connect_timeout=10');
$query = $dsn->getQuery(); // ['sslmode' => 'require', 'connect_timeout' => '10']
$dsn->setQuery(['sslmode' => 'disable']); // Override.
$this->app->singleton('amqp.dsn', function () {
return Dsn::fromString(config('amqp.dsn'));
});
env() helper:
$dsn = Dsn::fromString(env('RABBITMQ_DSN'));
$mockDsn = \Mockery::mock(Dsn::class);
$mockDsn->shouldReceive('toArray')->andReturn(['host' => 'test']);
Empty Components:
Dsn::fromString('postgres://@host') will set user and pass to null, not empty strings.null if your logic requires empty strings.Port Parsing:
null (e.g., postgres://host → port = null).if ($dsn->getPort() === null) {
throw new \RuntimeException('Port is required.');
}
Query Parameter Overwriting:
setQuery() replaces all existing query parameters. Use addQuery() (if available in future versions) or merge manually:
$query = $dsn->getQuery();
$query['new_param'] = 'value';
$dsn->setQuery($query);
Scheme-Specific Validation:
if ($dsn->getScheme() === 'redis' && $dsn->getPort() !== 6379) {
throw new \InvalidArgumentException('Redis must use port 6379.');
}
Invalid DSN Errors:
Nyholm\Dsn\Exception\InvalidDsnException for malformed input.Dsn::fromString() with a known valid DSN to test parsing logic.Query Parameter Issues:
= for key-value pairs (e.g., ?key=value, not ?key).?param=hello%20world).Custom DSN Schemes:
Nyholm\Dsn\Dsn and overriding parse():
class CustomDsn extends Dsn {
protected function parse(string $dsn): void {
parent::parse($dsn);
// Add scheme-specific logic.
}
}
Additional Components:
setTls()) by extending the class:
class ExtendedDsn extends Dsn {
private $tls;
public function setTls(bool $enabled): self {
$this->tls = $enabled;
return $this;
}
public function getTls(): ?bool {
return $this->tls;
}
}
Query Parameter Normalization:
getQuery() to normalize values (e.g., cast strings to booleans):
public function getQuery(): array {
$query = parent::getQuery();
return array_map(function ($value) {
return $value === 'true' ? true : $value;
}, $query);
}
$dsn = Dsn::fromString($config['dsn']);
// Reuse $dsn->toArray() across requests.
How can I help you explore Laravel packages today?