Skip to content

Commit 48e1fe2

Browse files
committed
Update docs
1 parent 94f36c2 commit 48e1fe2

File tree

3 files changed

+493
-151
lines changed

3 files changed

+493
-151
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ A tiny, fully featured dependency injection container as a DSL.
88

99
## Table of contents
1010

11-
- [Contributing](CONTRIBUTING.md)
12-
- [Feature Guide](docs/README.md)
11+
- [Feature Guide](docs/README.md) - Full feature guide.
12+
- [INI DSL](docs/DSL.md) - Support for .ini files.
1313
- [Installation](docs/INSTALL.md)
14+
- [Contributing](CONTRIBUTING.md)
1415
- [License](LICENSE.md)
15-
- [What is a DSL?](docs/DSL.md)

docs/DSL.md

Lines changed: 277 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,281 @@
1-
# What is a DSL?
1+
# INI DSL Guide
22

3-
DSLs are Domain Specific Languages, small languages implemented for specific
4-
domains. Respect\Config is an **internal DSL** hosted on the INI format to
5-
hold dependency injection containers.
3+
Respect\Config extends the standard INI format with a DSL for declaring dependency
4+
injection containers. Everything in this guide maps to the PHP API described in the
5+
[Feature Guide](README.md) — if you haven't read that first, start there.
6+
7+
## Loading INI
8+
9+
```php
10+
use Respect\Config\IniLoader;
11+
12+
// From a file
13+
$container = IniLoader::load('services.ini');
14+
15+
// From a string
16+
$container = IniLoader::load('db_host = localhost');
17+
18+
// Onto an existing container
19+
IniLoader::load('overrides.ini', $container);
20+
```
21+
22+
## Simple Values
23+
24+
```ini
25+
app_name = "My Application"
26+
per_page = 20
27+
tax_rate = 0.075
28+
error_mode = PDO::ERRMODE_EXCEPTION
29+
severity = E_USER_ERROR
30+
```
31+
32+
```php
33+
$container->get('per_page'); // 20 (int)
34+
$container->get('tax_rate'); // 0.075 (float)
35+
$container->get('error_mode'); // 2 (PDO::ERRMODE_EXCEPTION)
36+
```
37+
38+
## Sequences
39+
40+
Comma-separated values inside brackets produce PHP arrays:
41+
42+
```ini
43+
allowed_origins = [http://localhost:8000, http://localhost:3000]
44+
```
45+
46+
```php
47+
// ['http://localhost:8000', 'http://localhost:3000']
48+
$container->get('allowed_origins');
49+
```
50+
51+
## Instances
52+
53+
Create instances using INI sections. The section name becomes the container key,
54+
the class name follows after a space:
55+
56+
```ini
57+
[connection PDO]
58+
dsn = "sqlite:app.db"
59+
```
60+
61+
```php
62+
$container->get('connection'); // PDO instance
63+
```
64+
65+
The `instanceof` keyword uses the class name itself as the container key:
66+
67+
```ini
68+
[instanceof PDO]
69+
dsn = "sqlite:app.db"
70+
```
71+
72+
```php
73+
$container->get(PDO::class); // PDO instance, keyed by class name
74+
```
75+
76+
## Constructor Parameters
77+
78+
Parameter names under a section are matched to the class constructor via reflection:
79+
80+
```ini
81+
[connection PDO]
82+
dsn = "sqlite:app.db"
83+
username = "root"
84+
password = "secret"
85+
```
86+
87+
You can also pass all constructor arguments as a positional list:
88+
89+
```ini
90+
[connection PDO]
91+
__construct = ["sqlite:app.db", "root", "secret"]
92+
```
93+
94+
1. Set only the parameters you need — unset parameters keep their defaults.
95+
2. Trailing `null` parameters are automatically stripped so defaults apply.
96+
97+
## References
98+
99+
Use `[name]` as a parameter value to reference another container entry. This is
100+
the INI equivalent of passing an `Instantiator` object as a parameter in PHP:
101+
102+
Given the class:
103+
104+
```php
105+
class Mapper {
106+
public function __construct(public PDO $db) {}
107+
}
108+
```
109+
110+
Wire it with `[name]` references:
111+
112+
```ini
113+
[connection PDO]
114+
dsn = "sqlite:app.db"
115+
116+
[mapper Mapper]
117+
db = [connection]
118+
```
119+
120+
```php
121+
$container->get('mapper'); // Mapper instance with the PDO connection injected
122+
```
123+
124+
References also work inside sequences:
125+
126+
```ini
127+
admin = admin@example.com
128+
notify = [[admin], ops@example.com]
129+
```
130+
131+
```php
132+
$container->get('notify'); // ['admin@example.com', 'ops@example.com']
133+
```
134+
135+
## Method Calls
136+
137+
Call methods on an instance after construction using `[]` syntax.
138+
Each `methodName[]` entry is one call:
139+
140+
```ini
141+
[connection PDO]
142+
dsn = "sqlite:app.db"
143+
setAttribute[] = [PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION]
144+
setAttribute[] = [PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC]
145+
exec[] = "PRAGMA journal_mode=WAL"
146+
exec[] = "PRAGMA foreign_keys=ON"
147+
```
148+
149+
```php
150+
$container->get('connection'); // PDO with attributes set and PRAGMAs executed
151+
```
152+
153+
## Static Factory Methods
154+
155+
Static methods use the same `[]` syntax. They are detected automatically via
156+
reflection:
157+
158+
```ini
159+
[y2k DateTime]
160+
createFromFormat[] = [Y-m-d, 2000-01-01]
161+
```
162+
163+
```php
164+
$container->get('y2k'); // DateTime for 2000-01-01
165+
```
166+
167+
The `Container` will skip the constructor and use the factory, same as the pure
168+
PHP version.
169+
170+
## Properties
171+
172+
Names that don't match a constructor parameter or method are set as public
173+
properties on the instance:
174+
175+
```php
176+
class Request {
177+
public int $timeout = 10;
178+
public string $base_url = '';
179+
}
180+
```
181+
182+
```ini
183+
[request Request]
184+
timeout = 30
185+
base_url = "https://api.example.com"
186+
```
187+
188+
```php
189+
$container->get('request')->base_url; // 'https://api.example.com'
190+
```
191+
192+
The resolution order is: constructor parameter → static method → instance method → property.
193+
194+
## Autowiring
195+
196+
Use the `autowire` modifier to enable automatic type-hint resolution:
197+
198+
```php
199+
class UserRepository {
200+
public bool $cacheEnabled = false;
201+
public function __construct(public PDO $db) {}
202+
}
203+
```
204+
205+
```ini
206+
[connection PDO]
207+
dsn = "sqlite:app.db"
208+
209+
[repository autowire UserRepository]
210+
```
211+
212+
```php
213+
$container->get('repository'); // UserRepository with PDO auto-injected
214+
```
215+
216+
The `PDO` instance is injected automatically because the container has an
217+
entry keyed by `PDO`, matching the type hint on the constructor.
218+
219+
Explicit parameters can be mixed in alongside autowiring:
220+
221+
```ini
222+
[repository autowire UserRepository]
223+
cacheEnabled = true
224+
```
225+
226+
## Factory (Fresh Instances)
227+
228+
Use the `new` modifier to create a fresh instance on every access:
229+
230+
```php
231+
class PostController {
232+
public function __construct(public Mapper $mapper) {}
233+
}
234+
```
235+
236+
```ini
237+
[controller new PostController]
238+
mapper = [mapper]
239+
```
240+
241+
```php
242+
$a = $container->get('controller'); // new PostController
243+
$b = $container->get('controller'); // another new PostController
244+
assert($a !== $b);
245+
```
246+
Dependencies like `[mapper]` are still resolved and cached normally.
247+
248+
## String Interpolation
249+
250+
The `[name]` placeholder syntax can also be used inline within a string to
251+
build composite values. This always produces a string:
252+
253+
```ini
254+
db_driver = mysql
255+
db_host = localhost
256+
db_name = myapp
257+
db_dsn = "[db_driver]:host=[db_host];dbname=[db_name]"
258+
```
259+
260+
```php
261+
$container->get('db_dsn'); // "mysql:host=localhost;dbname=myapp"
262+
```
263+
264+
Only root-level simple scalars can be interpolated.
265+
266+
## State Precedence
267+
268+
When loading INI onto a pre-populated container, existing non-Instantiator
269+
values take precedence:
270+
271+
```php
272+
$container = new Container(['env' => 'production']);
273+
IniLoader::load('config.ini', $container);
274+
// If config.ini has env = development, the existing 'production' value wins
275+
```
276+
277+
This allows environment-specific values to be set before loading the INI file,
278+
ensuring they are not overwritten.
6279

7280
***
8281

0 commit comments

Comments
 (0)