Skip to content

Commit 6e7ab63

Browse files
committed
add option "from" to allow to bind multiple parameters even if their number is unknown
1 parent 05ef584 commit 6e7ab63

File tree

3 files changed

+157
-112
lines changed

3 files changed

+157
-112
lines changed

src/Builder/AlternativeLookup.php

Lines changed: 138 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -34,71 +34,78 @@ public function withState(Node\Expr $state): StepBuilderInterface
3434
return $this;
3535
}
3636

37-
public function addStringParam(int|string $key, Node\Expr $param): StepBuilderInterface
37+
public function addStringParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface
3838
{
3939
$this->parameters[$key] = [
4040
'value' => $param,
4141
'type' => 'string',
42+
'iterable' => $iterable,
4243
];
4344

4445
return $this;
4546
}
4647

47-
public function addIntegerParam(int|string $key, Node\Expr $param): StepBuilderInterface
48+
public function addIntegerParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface
4849
{
4950
$this->parameters[$key] = [
5051
'value' => $param,
5152
'type' => 'integer',
53+
'iterable' => $iterable,
5254
];
5355

5456
return $this;
5557
}
5658

57-
public function addBooleanParam(int|string $key, Node\Expr $param): StepBuilderInterface
59+
public function addBooleanParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface
5860
{
5961
$this->parameters[$key] = [
6062
'value' => $param,
6163
'type' => 'boolean',
64+
'iterable' => $iterable,
6265
];
6366

6467
return $this;
6568
}
6669

67-
public function addDateParam(int|string $key, Node\Expr $param): self
70+
public function addDateParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self
6871
{
6972
$this->parameters[$key] = [
7073
'value' => $param,
7174
'type' => 'date',
75+
'iterable' => $iterable,
7276
];
7377

7478
return $this;
7579
}
7680

77-
public function addDateTimeParam(int|string $key, Node\Expr $param): self
81+
public function addDateTimeParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self
7882
{
7983
$this->parameters[$key] = [
8084
'value' => $param,
8185
'type' => 'datetime',
86+
'iterable' => $iterable,
8287
];
8388

8489
return $this;
8590
}
8691

87-
public function addJSONParam(int|string $key, Node\Expr $param): self
92+
public function addJSONParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self
8893
{
8994
$this->parameters[$key] = [
9095
'value' => $param,
9196
'type' => 'json',
97+
'iterable' => $iterable,
9298
];
9399

94100
return $this;
95101
}
96102

97-
public function addBinaryParam(int|string $key, Node\Expr $param): self
103+
public function addBinaryParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self
98104
{
99105
$this->parameters[$key] = [
100106
'value' => $param,
101107
'type' => 'binary',
108+
'iterable' => $iterable,
102109
];
103110

104111
return $this;
@@ -151,7 +158,7 @@ public function getAlternativeLookupNode(): Node
151158
),
152159
),
153160
),
154-
...$this->compileParameters(),
161+
...$this->getParameters(),
155162
new Node\Stmt\Expression(
156163
expr: new Node\Expr\MethodCall(
157164
var: new Node\Expr\Variable('stmt'),
@@ -233,121 +240,141 @@ class: new Node\Name\FullyQualified('PDO'),
233240
))->getNode();
234241
}
235242

236-
public function compileParameters(): iterable
243+
public function getParameters(): iterable
237244
{
238245
foreach ($this->parameters as $key => $parameter) {
239-
yield match ($parameter['type']) {
240-
'datetime' => new Node\Stmt\Expression(
241-
new Node\Expr\MethodCall(
242-
var: new Node\Expr\Variable('stmt'),
243-
name: new Node\Identifier('bindValue'),
244-
args: [
245-
new Node\Arg(
246-
\is_string($key) ? new Node\Scalar\Encapsed(
247-
[
248-
new Node\Scalar\EncapsedStringPart(':'),
249-
new Node\Scalar\EncapsedStringPart($key),
250-
]
251-
) : new Node\Scalar\LNumber($key)
252-
),
253-
new Node\Arg(
254-
value: new Node\Expr\StaticCall(
255-
class: new Node\Name('DateTimeImmutable'),
256-
name: new Node\Name('createFromFormat'),
257-
args: [
258-
new Node\Arg(
259-
value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS')
260-
),
261-
new Node\Arg(
262-
value: $parameter['value']
263-
),
264-
],
246+
if (true === $parameter['iterable']) {
247+
yield new Node\Stmt\Foreach_(
248+
expr: $parameter['value'],
249+
valueVar: new Node\Expr\Variable('value'),
250+
subNodes: [
251+
'keyVar' => new Node\Expr\Variable('key'),
252+
'stmts' => [
253+
$this->compileParameters(
254+
new Node\Arg(
255+
new Node\Expr\BinaryOp\Concat(
256+
new Node\Scalar\String_($key.'_'),
257+
new Node\Expr\Variable('key'),
258+
)
265259
),
260+
[
261+
'type' => $parameter['type'],
262+
'value' => new Node\Expr\Variable('value'),
263+
]
266264
),
267-
$this->compileParameterType($parameter),
268265
],
269-
),
270-
),
271-
'date' => new Node\Stmt\Expression(
272-
new Node\Expr\MethodCall(
273-
var: new Node\Expr\Variable('stmt'),
274-
name: new Node\Identifier('bindValue'),
275-
args: [
276-
new Node\Arg(
277-
\is_string($key) ? new Node\Scalar\Encapsed(
278-
[
279-
new Node\Scalar\EncapsedStringPart(':'),
280-
new Node\Scalar\EncapsedStringPart($key),
281-
]
282-
) : new Node\Scalar\LNumber($key)
283-
),
284-
new Node\Arg(
285-
value: new Node\Expr\StaticCall(
286-
class: new Node\Name('DateTimeImmutable'),
287-
name: new Node\Name('createFromFormat'),
288-
args: [
289-
new Node\Arg(
290-
value: new Node\Scalar\String_('YYYY-MM-DD')
291-
),
292-
new Node\Arg(
293-
value: $parameter['value']
294-
),
295-
],
296-
),
266+
]
267+
);
268+
} else {
269+
yield $this->compileParameters($key, $parameter);
270+
}
271+
}
272+
}
273+
274+
private function compileParameters(int|string|Node\Arg $key, array $parameter): Node\Stmt\Expression
275+
{
276+
return match ($parameter['type']) {
277+
'datetime' => new Node\Stmt\Expression(
278+
new Node\Expr\MethodCall(
279+
var: new Node\Expr\Variable('stmt'),
280+
name: new Node\Identifier('bindValue'),
281+
args: [
282+
$this->compileParameterKey($key),
283+
new Node\Arg(
284+
value: new Node\Expr\StaticCall(
285+
class: new Node\Name('DateTimeImmutable'),
286+
name: new Node\Name('createFromFormat'),
287+
args: [
288+
new Node\Arg(
289+
value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS')
290+
),
291+
new Node\Arg(
292+
value: $parameter['value']
293+
),
294+
],
297295
),
298-
$this->compileParameterType($parameter),
299-
],
300-
),
296+
),
297+
$this->compileParameterType($parameter),
298+
],
301299
),
302-
'json' => new Node\Stmt\Expression(
303-
new Node\Expr\MethodCall(
304-
var: new Node\Expr\Variable('stmt'),
305-
name: new Node\Identifier('bindValue'),
306-
args: [
307-
new Node\Arg(
308-
\is_string($key) ? new Node\Scalar\Encapsed(
309-
[
310-
new Node\Scalar\EncapsedStringPart(':'),
311-
new Node\Scalar\EncapsedStringPart($key),
312-
]
313-
) : new Node\Scalar\LNumber($key)
314-
),
315-
new Node\Arg(
316-
new Node\Expr\FuncCall(
317-
name: new Node\Name('json_decode'),
318-
args: [
319-
new Node\Arg(
320-
value: $parameter['value']
321-
),
322-
],
323-
),
300+
),
301+
'date' => new Node\Stmt\Expression(
302+
new Node\Expr\MethodCall(
303+
var: new Node\Expr\Variable('stmt'),
304+
name: new Node\Identifier('bindValue'),
305+
args: [
306+
$this->compileParameterKey($key),
307+
new Node\Arg(
308+
value: new Node\Expr\StaticCall(
309+
class: new Node\Name('DateTimeImmutable'),
310+
name: new Node\Name('createFromFormat'),
311+
args: [
312+
new Node\Arg(
313+
value: new Node\Scalar\String_('YYYY-MM-DD')
314+
),
315+
new Node\Arg(
316+
value: $parameter['value']
317+
),
318+
],
324319
),
325-
$this->compileParameterType($parameter),
326-
],
327-
),
320+
),
321+
$this->compileParameterType($parameter),
322+
],
328323
),
329-
default => new Node\Stmt\Expression(
330-
new Node\Expr\MethodCall(
331-
var: new Node\Expr\Variable('stmt'),
332-
name: new Node\Identifier('bindValue'),
333-
args: [
334-
new Node\Arg(
335-
\is_string($key) ? new Node\Scalar\Encapsed(
336-
[
337-
new Node\Scalar\EncapsedStringPart(':'),
338-
new Node\Scalar\EncapsedStringPart($key),
339-
]
340-
) : new Node\Scalar\LNumber($key)
341-
),
342-
new Node\Arg(
343-
$parameter['value']
324+
),
325+
'json' => new Node\Stmt\Expression(
326+
new Node\Expr\MethodCall(
327+
var: new Node\Expr\Variable('stmt'),
328+
name: new Node\Identifier('bindValue'),
329+
args: [
330+
$this->compileParameterKey($key),
331+
new Node\Arg(
332+
new Node\Expr\FuncCall(
333+
name: new Node\Name('json_decode'),
334+
args: [
335+
new Node\Arg(
336+
value: $parameter['value']
337+
),
338+
],
344339
),
345-
$this->compileParameterType($parameter),
346-
],
347-
),
340+
),
341+
$this->compileParameterType($parameter),
342+
],
343+
),
344+
),
345+
default => new Node\Stmt\Expression(
346+
new Node\Expr\MethodCall(
347+
var: new Node\Expr\Variable('stmt'),
348+
name: new Node\Identifier('bindValue'),
349+
args: [
350+
$this->compileParameterKey($key),
351+
new Node\Arg(
352+
$parameter['value']
353+
),
354+
$this->compileParameterType($parameter),
355+
],
348356
),
349-
};
357+
),
358+
};
359+
}
360+
361+
private function compileParameterKey(int|string|Node\Arg $key): Node\Arg
362+
{
363+
if (\is_string($key)) {
364+
return new Node\Arg(
365+
new Node\Scalar\Encapsed([
366+
new Node\Scalar\EncapsedStringPart(':'),
367+
new Node\Scalar\EncapsedStringPart($key),
368+
])
369+
);
370+
}
371+
if ($key instanceof Node\Arg) {
372+
return $key;
350373
}
374+
375+
return new Node\Arg(
376+
new Node\Scalar\LNumber($key)
377+
);
351378
}
352379

353380
private function compileParameterType(array $parameter): Node\Arg

src/Configuration/Parameters.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ public function getConfigTreeBuilder(): TreeBuilder
2626
->arrayPrototype()
2727
->children()
2828
->scalarNode('value')
29-
->isRequired()
29+
->validate()
30+
->ifTrue(isExpression())
31+
->then(asExpression())
32+
->end()
33+
->end()
34+
->scalarNode('from')
3035
->validate()
3136
->ifTrue(isExpression())
3237
->then(asExpression())

0 commit comments

Comments
 (0)