@@ -49,29 +49,68 @@ class Explorer
4949 private ?Structure $ structure = null ;
5050
5151
52- public function __construct (
52+ public static function createFromParameters (
53+ #[\SensitiveParameter]
54+ ...$ params ,
55+ ): self
56+ {
57+ $ params = count ($ params ) === 1 && is_array ($ params [0 ] ?? null ) ? $ params [0 ] : $ params ;
58+
59+ if ($ class = $ params ['driverClass ' ] ?? null ) {
60+ if (!is_subclass_of ($ class , Drivers \Driver::class)) {
61+ throw new \LogicException ("Driver class ' $ class' is not subclass of " . Drivers \Driver::class);
62+ }
63+ unset($ params ['driverClass ' ]);
64+
65+ } elseif ($ driver = $ params ['driver ' ] ?? null ) {
66+ $ class = self ::Drivers[$ driver ] ?? throw new \LogicException ("Unknown driver ' $ driver'. " );
67+ unset($ params ['driver ' ]);
68+
69+ } elseif ($ dsn = $ params ['dsn ' ] ?? null ) {
70+ $ driver = explode (': ' , $ dsn )[0 ];
71+ $ class = self ::Drivers['pdo- ' . $ driver ] ?? throw new \LogicException ("Unknown PDO driver ' $ driver'. " );
72+
73+ } else {
74+ throw new \LogicException ("Missing options 'driver', 'driverClass' or 'dsn'. " );
75+ }
76+
77+ $ args = array_diff_key ($ params , array_flip (self ::TypeConverterOptions));
78+ $ explorer = new self (new $ class (...$ args ));
79+ array_map (fn ($ opt ) => isset ($ params [$ opt ]) && ($ explorer ->typeConverter ->$ opt = (bool ) $ params [$ opt ]), self ::TypeConverterOptions);
80+ return $ explorer ;
81+ }
82+
83+
84+ public static function createFromDsn (
5385 string $ dsn ,
5486 ?string $ username = null ,
5587 #[\SensitiveParameter]
5688 ?string $ password = null ,
5789 array $ options = [],
58- ) {
59- $ driver = explode (': ' , $ dsn )[0 ];
60- $ class = empty ($ options ['driverClass ' ])
61- ? (self ::Drivers['pdo- ' . $ driver ] ?? throw new \LogicException ("Unknown PDO driver ' $ driver'. " ))
62- : $ options ['driverClass ' ];
63- $ args = compact ('dsn ' , 'username ' , 'password ' , 'options ' );
64- unset($ options ['lazy ' ], $ options ['driverClass ' ]);
90+ ): self
91+ {
92+ $ params = compact ('dsn ' , 'username ' , 'password ' , 'options ' );
6593 foreach ($ options as $ key => $ value ) {
6694 if (!is_int ($ key ) && $ value !== null ) {
67- $ args [$ key ] = $ value ;
68- unset($ args ['options ' ][$ key ]);
95+ $ params [$ key ] = $ value ;
96+ unset($ params ['options ' ][$ key ]);
6997 }
7098 }
71- $ args = array_diff_key ($ args , array_flip (self ::TypeConverterOptions));
72- $ this ->driver = new $ class (...$ args );
73- $ this ->typeConverter = new TypeConverter ;
74- array_map (fn ($ opt ) => isset ($ options [$ opt ]) && ($ this ->typeConverter ->$ opt = (bool ) $ options [$ opt ]), self ::TypeConverterOptions);
99+ unset($ params ['lazy ' ]);
100+ return self ::createFromParameters ($ params );
101+ }
102+
103+
104+ public function __construct (
105+ Drivers \Driver |string $ driver ,
106+ ) {
107+ if (is_string ($ driver )) { // back compatibility with version 3.x
108+ $ explorer = self ::createFromDsn (...func_get_args ());
109+ [$ this ->driver , $ this ->typeConverter ] = [$ explorer ->driver , $ explorer ->typeConverter ];
110+ } else {
111+ $ this ->driver = $ driver ;
112+ $ this ->typeConverter = new TypeConverter ;
113+ }
75114 }
76115
77116
0 commit comments