1<?php 2 3namespace Doctrine\DBAL\Query\Expression; 4 5use Doctrine\DBAL\Connection; 6use Doctrine\Deprecations\Deprecation; 7 8use function func_get_arg; 9use function func_get_args; 10use function func_num_args; 11use function implode; 12use function sprintf; 13 14/** 15 * ExpressionBuilder class is responsible to dynamically create SQL query parts. 16 */ 17class ExpressionBuilder 18{ 19 public const EQ = '='; 20 public const NEQ = '<>'; 21 public const LT = '<'; 22 public const LTE = '<='; 23 public const GT = '>'; 24 public const GTE = '>='; 25 26 /** 27 * The DBAL Connection. 28 * 29 * @var Connection 30 */ 31 private $connection; 32 33 /** 34 * Initializes a new <tt>ExpressionBuilder</tt>. 35 * 36 * @param Connection $connection The DBAL Connection. 37 */ 38 public function __construct(Connection $connection) 39 { 40 $this->connection = $connection; 41 } 42 43 /** 44 * Creates a conjunction of the given expressions. 45 * 46 * @param string|CompositeExpression $expression 47 * @param string|CompositeExpression ...$expressions 48 */ 49 public function and($expression, ...$expressions): CompositeExpression 50 { 51 return CompositeExpression::and($expression, ...$expressions); 52 } 53 54 /** 55 * Creates a disjunction of the given expressions. 56 * 57 * @param string|CompositeExpression $expression 58 * @param string|CompositeExpression ...$expressions 59 */ 60 public function or($expression, ...$expressions): CompositeExpression 61 { 62 return CompositeExpression::or($expression, ...$expressions); 63 } 64 65 /** 66 * @deprecated Use `and()` instead. 67 * 68 * @param mixed $x Optional clause. Defaults = null, but requires 69 * at least one defined when converting to string. 70 * 71 * @return CompositeExpression 72 */ 73 public function andX($x = null) 74 { 75 Deprecation::trigger( 76 'doctrine/dbal', 77 'https://github.com/doctrine/dbal/pull/3851', 78 'ExpressionBuilder::andX() is deprecated, use ExpressionBuilder::and() instead.' 79 ); 80 81 return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); 82 } 83 84 /** 85 * @deprecated Use `or()` instead. 86 * 87 * @param mixed $x Optional clause. Defaults = null, but requires 88 * at least one defined when converting to string. 89 * 90 * @return CompositeExpression 91 */ 92 public function orX($x = null) 93 { 94 Deprecation::trigger( 95 'doctrine/dbal', 96 'https://github.com/doctrine/dbal/pull/3851', 97 'ExpressionBuilder::orX() is deprecated, use ExpressionBuilder::or() instead.' 98 ); 99 100 return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args()); 101 } 102 103 /** 104 * Creates a comparison expression. 105 * 106 * @param mixed $x The left expression. 107 * @param string $operator One of the ExpressionBuilder::* constants. 108 * @param mixed $y The right expression. 109 * 110 * @return string 111 */ 112 public function comparison($x, $operator, $y) 113 { 114 return $x . ' ' . $operator . ' ' . $y; 115 } 116 117 /** 118 * Creates an equality comparison expression with the given arguments. 119 * 120 * First argument is considered the left expression and the second is the right expression. 121 * When converted to string, it will generated a <left expr> = <right expr>. Example: 122 * 123 * [php] 124 * // u.id = ? 125 * $expr->eq('u.id', '?'); 126 * 127 * @param mixed $x The left expression. 128 * @param mixed $y The right expression. 129 * 130 * @return string 131 */ 132 public function eq($x, $y) 133 { 134 return $this->comparison($x, self::EQ, $y); 135 } 136 137 /** 138 * Creates a non equality comparison expression with the given arguments. 139 * First argument is considered the left expression and the second is the right expression. 140 * When converted to string, it will generated a <left expr> <> <right expr>. Example: 141 * 142 * [php] 143 * // u.id <> 1 144 * $q->where($q->expr()->neq('u.id', '1')); 145 * 146 * @param mixed $x The left expression. 147 * @param mixed $y The right expression. 148 * 149 * @return string 150 */ 151 public function neq($x, $y) 152 { 153 return $this->comparison($x, self::NEQ, $y); 154 } 155 156 /** 157 * Creates a lower-than comparison expression with the given arguments. 158 * First argument is considered the left expression and the second is the right expression. 159 * When converted to string, it will generated a <left expr> < <right expr>. Example: 160 * 161 * [php] 162 * // u.id < ? 163 * $q->where($q->expr()->lt('u.id', '?')); 164 * 165 * @param mixed $x The left expression. 166 * @param mixed $y The right expression. 167 * 168 * @return string 169 */ 170 public function lt($x, $y) 171 { 172 return $this->comparison($x, self::LT, $y); 173 } 174 175 /** 176 * Creates a lower-than-equal comparison expression with the given arguments. 177 * First argument is considered the left expression and the second is the right expression. 178 * When converted to string, it will generated a <left expr> <= <right expr>. Example: 179 * 180 * [php] 181 * // u.id <= ? 182 * $q->where($q->expr()->lte('u.id', '?')); 183 * 184 * @param mixed $x The left expression. 185 * @param mixed $y The right expression. 186 * 187 * @return string 188 */ 189 public function lte($x, $y) 190 { 191 return $this->comparison($x, self::LTE, $y); 192 } 193 194 /** 195 * Creates a greater-than comparison expression with the given arguments. 196 * First argument is considered the left expression and the second is the right expression. 197 * When converted to string, it will generated a <left expr> > <right expr>. Example: 198 * 199 * [php] 200 * // u.id > ? 201 * $q->where($q->expr()->gt('u.id', '?')); 202 * 203 * @param mixed $x The left expression. 204 * @param mixed $y The right expression. 205 * 206 * @return string 207 */ 208 public function gt($x, $y) 209 { 210 return $this->comparison($x, self::GT, $y); 211 } 212 213 /** 214 * Creates a greater-than-equal comparison expression with the given arguments. 215 * First argument is considered the left expression and the second is the right expression. 216 * When converted to string, it will generated a <left expr> >= <right expr>. Example: 217 * 218 * [php] 219 * // u.id >= ? 220 * $q->where($q->expr()->gte('u.id', '?')); 221 * 222 * @param mixed $x The left expression. 223 * @param mixed $y The right expression. 224 * 225 * @return string 226 */ 227 public function gte($x, $y) 228 { 229 return $this->comparison($x, self::GTE, $y); 230 } 231 232 /** 233 * Creates an IS NULL expression with the given arguments. 234 * 235 * @param string $x The expression to be restricted by IS NULL. 236 * 237 * @return string 238 */ 239 public function isNull($x) 240 { 241 return $x . ' IS NULL'; 242 } 243 244 /** 245 * Creates an IS NOT NULL expression with the given arguments. 246 * 247 * @param string $x The expression to be restricted by IS NOT NULL. 248 * 249 * @return string 250 */ 251 public function isNotNull($x) 252 { 253 return $x . ' IS NOT NULL'; 254 } 255 256 /** 257 * Creates a LIKE() comparison expression with the given arguments. 258 * 259 * @param string $x Field in string format to be inspected by LIKE() comparison. 260 * @param mixed $y Argument to be used in LIKE() comparison. 261 * 262 * @return string 263 */ 264 public function like($x, $y/*, ?string $escapeChar = null */) 265 { 266 return $this->comparison($x, 'LIKE', $y) . 267 (func_num_args() >= 3 ? sprintf(' ESCAPE %s', func_get_arg(2)) : ''); 268 } 269 270 /** 271 * Creates a NOT LIKE() comparison expression with the given arguments. 272 * 273 * @param string $x Field in string format to be inspected by NOT LIKE() comparison. 274 * @param mixed $y Argument to be used in NOT LIKE() comparison. 275 * 276 * @return string 277 */ 278 public function notLike($x, $y/*, ?string $escapeChar = null */) 279 { 280 return $this->comparison($x, 'NOT LIKE', $y) . 281 (func_num_args() >= 3 ? sprintf(' ESCAPE %s', func_get_arg(2)) : ''); 282 } 283 284 /** 285 * Creates a IN () comparison expression with the given arguments. 286 * 287 * @param string $x The field in string format to be inspected by IN() comparison. 288 * @param string|string[] $y The placeholder or the array of values to be used by IN() comparison. 289 * 290 * @return string 291 */ 292 public function in($x, $y) 293 { 294 return $this->comparison($x, 'IN', '(' . implode(', ', (array) $y) . ')'); 295 } 296 297 /** 298 * Creates a NOT IN () comparison expression with the given arguments. 299 * 300 * @param string $x The expression to be inspected by NOT IN() comparison. 301 * @param string|string[] $y The placeholder or the array of values to be used by NOT IN() comparison. 302 * 303 * @return string 304 */ 305 public function notIn($x, $y) 306 { 307 return $this->comparison($x, 'NOT IN', '(' . implode(', ', (array) $y) . ')'); 308 } 309 310 /** 311 * Quotes a given input parameter. 312 * 313 * @param mixed $input The parameter to be quoted. 314 * @param int|null $type The type of the parameter. 315 * 316 * @return string 317 */ 318 public function literal($input, $type = null) 319 { 320 return $this->connection->quote($input, $type); 321 } 322} 323