55use Lkrms \Concept \FluentInterface ;
66use Lkrms \Concern \TReadable ;
77use Lkrms \Contract \IReadable ;
8- use UnexpectedValueException ;
8+ use LogicException ;
99
1010/**
1111 * A simple representation of a SQL query
@@ -20,21 +20,23 @@ final class SqlQuery extends FluentInterface implements IReadable
2020 public const OR = 'OR ' ;
2121
2222 /**
23- * A list of optionally nested WHERE clauses
23+ * A list of optionally nested WHERE conditions
2424 *
25- * To join a list of clauses with an explicit operator:
25+ * To join a list of conditions with an explicit operator:
2626 *
2727 * ```php
28+ * <?php
2829 * [
2930 * '__' => SqlQuery::AND,
3031 * 'Id = ?',
3132 * 'Deleted IS NULL',
3233 * ]
3334 * ```
3435 *
35- * To use nested clauses :
36+ * To use nested conditions :
3637 *
3738 * ```php
39+ * <?php
3840 * [
3941 * '__' => SqlQuery::AND,
4042 * 'ItemKey = ?',
@@ -46,7 +48,7 @@ final class SqlQuery extends FluentInterface implements IReadable
4648 * ]
4749 * ```
4850 *
49- * @var array<int|string,string|array >
51+ * @var array<int|string,string|mixed[] >
5052 */
5153 public $ Where = [];
5254
@@ -58,21 +60,23 @@ final class SqlQuery extends FluentInterface implements IReadable
5860 protected $ Values = [];
5961
6062 /**
61- * @var callable
63+ * @var callable(string): string
6264 */
6365 protected $ ParamCallback ;
6466
67+ /**
68+ * @inheritDoc
69+ */
6570 public static function getReadable (): array
6671 {
6772 return ['Values ' ];
6873 }
6974
7075 /**
71- * @param callable $paramCallback Applied to the name of each parameter
72- * added to the query.
73- * ```php
74- * function (string $name): string
75- * ```
76+ * Creates a new SqlQuery object
77+ *
78+ * @param callable(string): string $paramCallback Applied to the name of
79+ * each parameter added to the query.
7680 */
7781 public function __construct (callable $ paramCallback )
7882 {
@@ -82,12 +86,13 @@ public function __construct(callable $paramCallback)
8286 /**
8387 * Add a parameter and assign its query placeholder to a variable
8488 *
89+ * @param mixed $value
8590 * @return $this
8691 */
8792 public function addParam (string $ name , $ value , ?string &$ placeholder )
8893 {
8994 if (array_key_exists ($ name , $ this ->Values )) {
90- throw new UnexpectedValueException ( " Parameter already added: $ name" );
95+ throw new LogicException ( sprintf ( ' Parameter already added: %s ' , $ name) );
9196 }
9297
9398 $ placeholder = ($ this ->ParamCallback )($ name );
@@ -97,73 +102,85 @@ public function addParam(string $name, $value, ?string &$placeholder)
97102 }
98103
99104 /**
100- * Add a WHERE clause
105+ * Add a WHERE condition
101106 *
102- * See { @see SqlQuery::$Where}.
107+ * @see SqlQuery::$Where
103108 *
104- * @param callable|string|array $clause A string, an array, or a callback
105- * that returns a string or array.
106- * ```php
107- * fn(): string|array
108- * ```
109+ * @param (callable(): (string|mixed[]))|string|mixed[] $condition
109110 * @return $this
110111 */
111- public function where ($ clause )
112+ public function where ($ condition )
112113 {
113- $ this ->Where [] = is_callable ($ clause ) ? $ clause () : $ clause ;
114+ $ this ->Where [] = is_callable ($ condition ) ? $ condition () : $ condition ;
114115
115116 return $ this ;
116117 }
117118
118119 /**
119- * Add "<name> IN (<value>[,<value>])" to the query unless a list of values
120- * is empty
120+ * Add a list of values as a WHERE condition ( "<name> IN (<value>...)")
121+ * unless the list is empty
121122 *
123+ * @param mixed ...$value
122124 * @return $this
123125 */
124126 public function whereValueInList (string $ name , ...$ value )
125127 {
126- if (!count ( $ value) ) {
128+ if (!$ value ) {
127129 return $ this ;
128130 }
129131
130- $ expr = [];
131- foreach ($ value as $ _value ) {
132- $ expr [] = $ this ->addNextParam ($ _value );
132+ foreach ($ value as $ val ) {
133+ $ expr [] = $ this ->addNextParam ($ val );
133134 }
134135 $ this ->Where [] = "$ name IN ( " . implode (', ' , $ expr ) . ') ' ;
135136
136137 return $ this ;
137138 }
138139
140+ /**
141+ * Prepare a WHERE condition for use in a SQL statement
142+ *
143+ * @param array<string,mixed>|null $values
144+ */
139145 public function getWhere (?array &$ values = null ): ?string
140146 {
141147 $ values = $ this ->Values ;
148+ $ where = $ this ->buildWhere ($ this ->Where );
142149
143- return $ this ->buildWhere ($ this ->Where ) ?: null ;
150+ return $ where === ''
151+ ? null
152+ : $ where ;
144153 }
145154
155+ /**
156+ * @param mixed $value
157+ */
146158 private function addNextParam ($ value ): string
147159 {
148160 $ this ->addParam ('param_ ' . count ($ this ->Values ), $ value , $ param );
149161
150162 return $ param ;
151163 }
152164
153- private function buildWhere (array $ where )
165+ /**
166+ * @param array<int|string,string|mixed[]> $where
167+ */
168+ private function buildWhere (array $ where ): string
154169 {
155170 $ glue = $ where ['__ ' ] ?? self ::AND ;
156171 unset($ where ['__ ' ]);
157- foreach ($ where as $ i => $ clause ) {
158- if (is_array ($ clause )) {
159- if (!($ clause = $ this ->buildWhere ($ clause ))) {
172+ foreach ($ where as $ i => $ condition ) {
173+ if (is_array ($ condition )) {
174+ $ condition = $ this ->buildWhere ($ condition );
175+ if ($ condition === '' ) {
160176 unset($ where [$ i ]);
161177 continue ;
162178 }
163- $ where [$ i ] = "( $ clause ) " ;
179+ $ where [$ i ] = "( $ condition ) " ;
164180 }
165181 }
166182
183+ /** @var string[] $where */
167184 return implode (" $ glue " , $ where );
168185 }
169186}
0 commit comments