Skip to content

Commit afcb969

Browse files
authored
Merge pull request #8 from blitz-php/1.x-devs
Corrections diverses
2 parents 0fe8516 + d09a870 commit afcb969

14 files changed

Lines changed: 563 additions & 259 deletions

File tree

src/Builder/BaseBuilder.php

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ public function fromSubquery(BuilderInterface $from, string $alias = ''): self
307307

308308
$this->reset();
309309
$this->tables = [$table];
310+
$this->bindings->merge($from->bindings);
310311

311312
return $this;
312313
}
@@ -489,7 +490,7 @@ public function set($key, $value = ''): self
489490
$this->values[$k] = $v;
490491
} else {
491492
$this->values[$k] = $v;
492-
$this->bindings->add($v);
493+
$this->bindings->add($v, 'values');
493494
}
494495
}
495496

@@ -756,11 +757,11 @@ public function execute(): ResultInterface
756757
{
757758
$this->applyBeforeQueryCallbacks();
758759

759-
$result = $this->query($this->toSql(), $this->bindings->getValues());
760-
761-
$this->reset();
762-
763-
return $result;
760+
try {
761+
return $this->query($this->toSql(), $this->getBindings());
762+
} finally {
763+
$this->reset();
764+
}
764765
}
765766

766767
/**
@@ -1078,7 +1079,7 @@ public function explain(): array
10781079
{
10791080
$sql = 'EXPLAIN ' . $this->toSql();
10801081

1081-
return $this->query($sql, $this->bindings->getValues())->resultArray();
1082+
return $this->query($sql, $this->getBindings())->resultArray();
10821083
}
10831084

10841085
/**
@@ -1103,9 +1104,32 @@ public function sql(bool $preserve = false): string
11031104
return $sql;
11041105
}
11051106

1107+
/**
1108+
* Nettoyage des bindings
1109+
*/
1110+
public function cleanBindings(array $bindings): array
1111+
{
1112+
return $this->bindings->clean($bindings);
1113+
}
1114+
1115+
/**
1116+
* Récupère les bindings utilisés
1117+
*/
11061118
public function getBindings(): array
11071119
{
1108-
return $this->db->prepareBindings($this->bindings->getValues());
1120+
$types = match($this->crud) {
1121+
'select' => ['where', 'having', 'order', 'union'],
1122+
'insert', 'replace' => ['values'],
1123+
'upsert' => ['values', 'uniqueBy'], // Si on a des bindings pour les conflits
1124+
'update' => ['values', 'where', 'join'],
1125+
'delete' => ['where', 'join'],
1126+
'truncate' => null, // Pas de bindings pour TRUNCATE
1127+
default => [], // Fallback à tous
1128+
};
1129+
1130+
return $types === null
1131+
? []
1132+
: $this->db->prepareBindings($this->bindings->getOrdered($types));
11091133
}
11101134

11111135
/**

src/Builder/BindingCollection.php

Lines changed: 164 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,71 @@
1111

1212
namespace BlitzPHP\Database\Builder;
1313

14+
use BlitzPHP\Database\Query\Expression;
15+
use InvalidArgumentException;
1416
use PDO;
1517
use PDOStatement;
1618

1719
class BindingCollection
1820
{
19-
protected array $values = [];
21+
/**
22+
* Types de bindings supportés
23+
*/
24+
public const TYPES = [
25+
'select', 'from', 'join', 'where', 'having',
26+
'order', 'union', 'values', 'uniqueBy',
27+
];
28+
29+
/**
30+
* Bindings organisés par type
31+
*
32+
* @var array<string, list<mixed>>
33+
*/
34+
protected array $bindings = [];
35+
36+
/**
37+
* Types PDO pour chaque binding (optionnel)
38+
*
39+
* @var array<string, list<int>>
40+
*/
2041
protected array $types = [];
2142

43+
public function __construct()
44+
{
45+
foreach (self::TYPES as $type) {
46+
$this->bindings[$type] = [];
47+
$this->types[$type] = [];
48+
}
49+
}
50+
2251
/**
23-
* Ajoute un binding
52+
* Ajoute un binding dans un contexte spécifique
53+
*
54+
* @param mixed $value Valeur à binder
55+
* @param string $type Contexte ('where', 'values', etc.)
56+
* @param int|null $pdoType Type PDO (optionnel)
57+
*
58+
* @throws InvalidArgumentException
2459
*/
25-
public function add(mixed $value, ?int $type = null): self
60+
public function add(mixed $value, string $type = 'where', ?int $pdoType = null): self
2661
{
27-
$this->values[] = $value;
28-
$this->types[] = $type ?? $this->guessType($value);
29-
62+
if (!in_array($type, self::TYPES, true)) {
63+
throw new InvalidArgumentException("Type de binding invalide: {$type}");
64+
}
65+
66+
$this->bindings[$type][] = $value;
67+
$this->types[$type][] = $pdoType ?? $this->guessType($value);
68+
3069
return $this;
3170
}
3271

3372
/**
34-
* Ajoute plusieurs bindings
73+
* Ajoute plusieurs bindings dans un contexte
3574
*/
36-
public function addMany(array $values): self
75+
public function addMany(array $values, string $type = 'where'): self
3776
{
3877
foreach ($values as $value) {
39-
$this->add($value);
78+
$this->add($value, $type);
4079
}
4180

4281
return $this;
@@ -45,84 +84,156 @@ public function addMany(array $values): self
4584
/**
4685
* Ajoute un binding nommé
4786
*/
48-
public function addNamed(string $name, mixed $value, ?int $type = null): self
87+
public function addNamed(string $name, mixed $value, string $type = 'where', ?int $pdoType = null): self
4988
{
50-
$this->values[$name] = $value;
51-
$this->types[$name] = $type ?? $this->guessType($value);
89+
$this->bindings[$type][$name] = $value;
90+
$this->types[$type][$name] = $pdoType ?? $this->guessType($value);
5291

5392
return $this;
5493
}
5594

5695
/**
57-
* Récupère toutes les valeurs
96+
* Récupère tous les bindings d'un contexte
97+
*
98+
* @return list<mixed>|mixed
5899
*/
59-
public function getValues(): array
100+
public function get(string $type, ?string $name = null)
60101
{
61-
return $this->values;
102+
$bindings = $this->bindings[$type] ?? [];
103+
104+
return $name ? ($bindings[$name] ?? null) : $bindings;
105+
}
106+
107+
/**
108+
* Récupère tous les bindings dans l'ordre de compilation
109+
*
110+
* @param list<string> $types
111+
*
112+
* @return list<mixed>
113+
*/
114+
public function getOrdered(array $types = []): array
115+
{
116+
if ($types === []) {
117+
$types = self::TYPES;
118+
}
119+
120+
$result = [];
121+
foreach ($types as $type) {
122+
if (!empty($this->bindings[$type])) {
123+
array_push($result, ...$this->bindings[$type]);
124+
}
125+
}
126+
127+
return $result;
62128
}
63129

64130
/**
65-
* Récupère tous les types
131+
* Récupère tous les types dans l'ordre
132+
*
133+
* @param list<string> $types
134+
*
135+
* @return list<int>
66136
*/
67-
public function getTypes(): array
137+
public function getTypesOrdered(array $types = []): array
68138
{
69-
return $this->types;
139+
if ($types === []) {
140+
$types = self::TYPES;
141+
}
142+
143+
$result = [];
144+
foreach ($types as $type) {
145+
if (!empty($this->types[$type])) {
146+
array_push($result, ...$this->types[$type]);
147+
}
148+
}
149+
150+
return $result;
70151
}
71152

72153
/**
73-
* Récupère un binding
154+
* Vérifie si un contexte a des bindings
74155
*/
75-
public function get(string|int $key): mixed
156+
public function has(string $type): bool
76157
{
77-
return $this->values[$key] ?? null;
158+
return !empty($this->bindings[$type]);
78159
}
79160

80161
/**
81-
* Récupère le type d'un binding
162+
* Compte le nombre total de bindings
82163
*/
83-
public function getType(string|int $key): ?int
164+
public function count(?string $type = null): int
84165
{
85-
return $this->types[$key] ?? null;
166+
if ($type !== null) {
167+
return count($this->bindings[$type] ?? []);
168+
}
169+
170+
return array_sum(array_map('count', $this->bindings));
86171
}
87172

88173
/**
89-
* Vérifie si des bindings existent
174+
* Vérifie si un contexte est vide
90175
*/
91-
public function isEmpty(): bool
176+
public function isEmpty(?string $type = null): bool
92177
{
93-
return empty($this->values);
178+
return $this->count($type) === 0;
94179
}
95180

96181
/**
97-
* Vide la collection
182+
* Vide tous les bindings
98183
*/
99-
public function clear(): self
184+
public function clear(?string $type = null): self
100185
{
101-
$this->values = [];
102-
$this->types = [];
103-
186+
if ($type !== null) {
187+
$this->bindings[$type] = [];
188+
$this->types[$type] = [];
189+
} else {
190+
foreach (self::TYPES as $t) {
191+
$this->bindings[$t] = [];
192+
$this->types[$t] = [];
193+
}
194+
}
195+
104196
return $this;
105197
}
106198

107199
/**
108-
* Compte le nombre de bindings
200+
* Vide les bindings d'un contexte spécifique
109201
*/
110-
public function count(): int
202+
public function clearType(string $type): self
111203
{
112-
return count($this->values);
204+
if (isset($this->bindings[$type])) {
205+
$this->bindings[$type] = [];
206+
$this->types[$type] = [];
207+
}
208+
209+
return $this;
113210
}
114211

115212
/**
116213
* Fusionne une autre collection
117214
*/
118-
public function merge(self $bindings): self
215+
public function merge(self $collection): self
119216
{
120-
$this->values = array_merge($this->values, $bindings->values);
121-
$this->types = array_merge($this->types, $bindings->types);
122-
217+
foreach (self::TYPES as $type) {
218+
array_push($this->bindings[$type], ...$collection->bindings[$type]);
219+
array_push($this->types[$type], ...$collection->types[$type]);
220+
}
221+
123222
return $this;
124223
}
125224

225+
/**
226+
* Retire les expressions des bindings (elles ne doivent pas être bindées)
227+
*
228+
* @param list<mixed> $bindings
229+
*
230+
* @return list<mixed>
231+
*/
232+
public function clean(array $bindings): array
233+
{
234+
return array_filter($bindings, fn($binding) => !$binding instanceof Expression);
235+
}
236+
126237
/**
127238
* Devine le type PDO d'une valeur
128239
*/
@@ -138,10 +249,21 @@ protected function guessType(mixed $value): int
138249
}
139250

140251
/**
141-
* Clone la collection
252+
* Pour le débogage
142253
*/
254+
public function toArray(): array
255+
{
256+
return $this->bindings;
257+
}
258+
143259
public function __clone()
144260
{
145-
// Rien de spécial à faire, les tableaux sont copiés
261+
foreach ($this->bindings as $type => $bindings) {
262+
$this->bindings[$type] = $bindings;
263+
}
264+
265+
foreach ($this->types as $type => $types) {
266+
$this->types[$type] = $types;
267+
}
146268
}
147-
}
269+
}

0 commit comments

Comments
 (0)