nyholm / dsn
以强大和灵活的方式解析DSN字符串
Requires
- php: >=7.1
Requires (Dev)
- symfony/phpunit-bridge: ^5.1
This package is auto-updated.
Last update: 2024-09-18 15:20:46 UTC
README
将DSN字符串解析为值对象,以便更容易使用、传递和处理。
安装
通过Composer
composer require nyholm/dsn
快速使用
use Nyholm\Dsn\DsnParser; $dsn = DsnParser::parse('http://127.0.0.1/foo/bar?key=value'); echo get_class($dsn); // "Nyholm\Dsn\Configuration\Url" echo $dsn->getHost(); // "127.0.0.1" echo $dsn->getPath(); // "/foo/bar" echo $dsn->getPort(); // null
DSN字符串格式
DSN是一种用于配置许多服务的字符串。常见的DSN可能看起来像一个URL,其他则像文件路径。
memcached://127.0.0.1
mysql://user:password@127.0.0.1:3306/my_table
memcached:///var/local/run/memcached.socket?weight=25
这两种类型都可以有参数、用户和密码。我们使用的确切定义可以在页面底部找到。
DSN函数
DSN可能包含零个或多个函数。DSN解析器支持函数语法,但不支持其功能本身。函数参数必须用空格或逗号分隔。以下是一些示例函数。
failover(dummy://a dummy://a)
failover(dummy://a,dummy://a)
failover:(dummy://a,dummy://a)
roundrobin(dummy://a failover(dummy://b dummy://a) dummy://b)
解析
有两种解析方法;DsnParser::parse()
和 DsnParser::parseFunc()
。后者用于支持DSN函数的情况。
use Nyholm\Dsn\DsnParser; $dsn = DsnParser::parse('scheme://127.0.0.1/foo/bar?key=value'); echo get_class($dsn); // "Nyholm\Dsn\Configuration\Url" echo $dsn->getHost(); // "127.0.0.1" echo $dsn->getPath(); // "/foo/bar" echo $dsn->getPort(); // null
如果支持函数(如Symfony Mailer组件),我们可以使用 DsnParser::parseFunc()
use Nyholm\Dsn\DsnParser; $func = DsnParser::parseFunc('failover(sendgrid://KEY@default smtp://127.0.0.1)'); echo $func->getName(); // "failover" echo get_class($func->first()); // "Nyholm\Dsn\Configuration\Url" echo $func->first()->getHost(); // "default" echo $func->first()->getUser(); // "KEY"
use Nyholm\Dsn\DsnParser; $func = DsnParser::parseFunc('foo(udp://localhost failover:(tcp://localhost:61616,tcp://remotehost:61616)?initialReconnectDelay=100)?start=now'); echo $func->getName(); // "foo" echo $func->getParameters()['start']; // "now" $args = $func->getArguments(); echo get_class($args[0]); // "Nyholm\Dsn\Configuration\Url" echo $args[0]->getScheme(); // "udp" echo $args[0]->getHost(); // "localhost" echo get_class($args[1]); // "Nyholm\Dsn\Configuration\DsnFunction"
当使用 DsnParser::parseFunc()
对不包含任何DSN函数的字符串进行解析时,解析器会自动添加一个默认的 "dsn" 函数。这是为了提供方法的一致返回类型。
使用 DsnParser::parseFunc()
时,字符串 redis://127.0.0.1
将自动转换为 dsn(redis://127.0.0.1)
。
use Nyholm\Dsn\DsnParser; $func = DsnParser::parseFunc('smtp://127.0.0.1'); echo $func->getName(); // "dsn" echo get_class($func->first()); // "Nyholm\Dsn\Configuration\Url" echo $func->first()->getHost(); // "127.0.0.1" $func = DsnParser::parseFunc('dsn(smtp://127.0.0.1)'); echo $func->getName(); // "dsn" echo get_class($func->first()); // "Nyholm\Dsn\Configuration\Url" echo $func->first()->getHost(); // "127.0.0.1"
解析无效的DSN
如果您尝试解析无效的DSN字符串,将抛出 InvalidDsnException
。
use Nyholm\Dsn\DsnParser; use Nyholm\Dsn\Exception\InvalidDsnException; try { DsnParser::parse('foobar'); } catch (InvalidDsnException $e) { echo $e->getMessage(); }
消费
解析DSN字符串的结果是 DsnFunction
或 Dsn
。一个 DsnFunction
有一个 name
、argument
,可能还有 parameters
。一个参数是一个 DsnFunction
或一个 Dsn
。
Dsn
可以是一个 Path
或 Url
。所有3个对象都有用于获取DSN字符串部分的方法。
getScheme()
getUser()
getPassword()
getHost()
getPort()
getPath()
getParameters()
您还可以使用 with*
方法替换DSN的部分。DSN是不可变的,您将得到一个新的对象。
use Nyholm\Dsn\DsnParser; $dsn = DsnParser::parse('scheme://127.0.0.1/foo/bar?key=value'); echo $dsn->getHost(); // "127.0.0.1" $new = $dsn->withHost('nyholm.tech'); echo $dsn->getHost(); // "127.0.0.1" echo $new->getHost(); // "nyholm.tech"
不受支持
智能合并选项
当前的DSN是有效的,但是消费者需要确保host1和host2都包含 global_option
。
redis://(host1:1234,host2:1234?node2_option=a)?global_option=b
特殊DSN
以下DSN语法不受支持。
// Rust
pgsql://user:pass@tcp(localhost:5555)/dbname
// Java
jdbc:informix-sqli://<server>[:<port>]/<databaseName>:informixserver=<dbservername>
我们不支持像ODBC连接这样的DSN字符串
Driver={ODBC Driver 13 for SQL Server};server=localhost;database=WideWorldImporters;trusted_connection=Yes;
然而,我们支持“仅参数”
ocdb://?Driver=ODBC+Driver+13+for+SQL+Server&server=localhost&database=WideWorldImporters&trusted_connection=Yes
定义
没有官方的DSN RFC。我们已将DSN配置字符串定义为使用以下定义。DSN的“URL看起来”部分基于RFC 3986。
configuration:
{ function | dsn }
function:
function_name[:](configuration[,configuration])[?query]
function_name:
REGEX: [a-zA-Z0-9\+-]+
dsn:
{ scheme:[//]authority[path][?query] | scheme:[//][userinfo]path[?query] | host:port[path][?query] }
scheme:
REGEX: [a-zA-Z0-9\+-\.]+
authority:
[userinfo@]host[:port]
userinfo:
{ user[:password] | :password }
path:
"Normal" URL path according to RFC3986 section 3.3.
REGEX: (/? | (/[a-zA-Z0-9-\._~%!\$&'\(\}\*\+,;=:@]+)+)
query:
"Normal" URL query according to RFC3986 section 3.4.
REGEX: [a-zA-Z0-9-\._~%!\$&'\(\}\*\+,;=:@]+
user:
This value can be URL encoded.
REGEX: [a-zA-Z0-9-\._~%!\$&'\(\}\*\+,;=]+
password:
This value can be URL encoded.
REGEX: [a-zA-Z0-9-\._~%!\$&'\(\}\*\+,;=]+
host:
REGEX: [a-zA-Z0-9-\._~%!\$&'\(\}\*\+,;=]+
post:
REGEX: [0-9]+
支持格式的示例
- scheme://127.0.0.1/foo/bar?key=value
- scheme://user:pass@127.0.0.1/foo/bar?key=value
- scheme:///var/local/run/memcached.socket?weight=25
- scheme://user:pass@/var/local/run/memcached.socket?weight=25
- scheme:?host[localhost]&host[localhost:12345]=3
- scheme://a
- scheme://
- server:80