CaseStatementExpression
in package
implements
ExpressionInterface, TypedResultInterface
uses
CaseExpressionTrait, ExpressionTypeCasterTrait, TypeMapTrait
Represents a SQL case statement with a fluid API
Table of Contents
Interfaces
- ExpressionInterface
- An interface used by Expression objects.
- TypedResultInterface
- Represents an expression that is known to return a specific type
Properties
- $_typeMap : TypeMap|null
- $else : ExpressionInterface|object|scalar|null
- The else part result value.
- $elseType : string|null
- The else part result type.
- $isSimpleVariant : bool
- Whether this is a simple case expression.
- $returnType : string|null
- The return type.
- $validClauseNames : array<string|int, string>
- The names of the clauses that are valid for use with the `clause()` method.
- $value : ExpressionInterface|object|scalar|null
- The case value.
- $valueType : string|null
- The case value type.
- $when : array<string|int, WhenThenExpression>
- The `WHEN ... THEN ...` expressions.
- $whenBuffer : array<string|int, mixed>|null
- Buffer that holds values and types for use with `then()`.
Methods
- __clone() : void
- Clones the inner expression objects.
- __construct() : mixed
- Constructor.
- clause() : ExpressionInterface|object|array<string|int, WhenThenExpression>|scalar|null
- Returns the available data for the given clause.
- else() : $this
- Sets the `ELSE` result value.
- getDefaultTypes() : array<int|string, string>
- Gets default types of current type map.
- getReturnType() : string
- Returns the abstract type that this expression will return.
- getTypeMap() : TypeMap
- Returns the existing type map.
- setDefaultTypes() : $this
- Overwrite the default type mappings for fields in the implementing object.
- setReturnType() : $this
- Sets the abstract type that this expression will return.
- setTypeMap() : $this
- Creates a new TypeMap if $typeMap is an array, otherwise exchanges it for the given one.
- sql() : string
- Converts the Node into a SQL string fragment.
- then() : $this
- Sets the `THEN` result value for the last `WHEN ... THEN ...` statement that was opened using `when()`.
- traverse() : $this
- Iterates over each part of the expression recursively for every level of the expressions tree and executes the $callback callable passing as first parameter the instance of the expression currently being iterated.
- when() : $this
- Sets the `WHEN` value for a `WHEN ... THEN ...` expression, or a self-contained expression that holds both the value for `WHEN` and the value for `THEN`.
- _castToExpression() : mixed
- Conditionally converts the passed value to an ExpressionInterface object if the type class implements the ExpressionTypeInterface. Otherwise, returns the value unmodified.
- _requiresToExpressionCasting() : array<string|int, mixed>
- Returns an array with the types that require values to be casted to expressions, out of the list of type names passed as parameter.
Properties
$_typeMap
protected
TypeMap|null
$_typeMap
$else
The else part result value.
protected
ExpressionInterface|object|scalar|null
$else
= null
$elseType
The else part result type.
protected
string|null
$elseType
= null
$isSimpleVariant
Whether this is a simple case expression.
protected
bool
$isSimpleVariant
= false
$returnType
The return type.
protected
string|null
$returnType
= null
$validClauseNames
The names of the clauses that are valid for use with the `clause()` method.
protected
array<string|int, string>
$validClauseNames
= ['value', 'when', 'else']
$value
The case value.
protected
ExpressionInterface|object|scalar|null
$value
= null
$valueType
The case value type.
protected
string|null
$valueType
= null
$when
The `WHEN ... THEN ...` expressions.
protected
array<string|int, WhenThenExpression>
$when
= []
$whenBuffer
Buffer that holds values and types for use with `then()`.
protected
array<string|int, mixed>|null
$whenBuffer
= null
Methods
__clone()
Clones the inner expression objects.
public
__clone() : void
__construct()
Constructor.
public
__construct([ExpressionInterface|object|scalar|null $value = null ][, string|null $type = null ]) : mixed
When a value is set, the syntax generated is
CASE case_value WHEN when_value ... END
(simple case),
where the when_value
's are compared against the
case_value
.
When no value is set, the syntax generated is
CASE WHEN when_conditions ... END
(searched case),
where the conditions hold the comparisons.
Note that null
is a valid case value, and thus should
only be passed if you actually want to create the simple
case expression variant!
Parameters
- $value : ExpressionInterface|object|scalar|null = null
-
The case value.
- $type : string|null = null
-
The case value type. If no type is provided, the type will be tried to be inferred from the value.
clause()
Returns the available data for the given clause.
public
clause(string $clause) : ExpressionInterface|object|array<string|int, WhenThenExpression>|scalar|null
Available clauses
The following clause names are available:
-
value
: The case value for aCASE case_value WHEN ...
expression. -
when
: An array ofWHEN ... THEN ...
expressions. -
else
: TheELSE
result value.
Parameters
- $clause : string
-
The name of the clause to obtain.
Tags
Return values
ExpressionInterface|object|array<string|int, WhenThenExpression>|scalar|nullelse()
Sets the `ELSE` result value.
public
else(ExpressionInterface|object|scalar|null $result[, string|null $type = null ]) : $this
Parameters
- $result : ExpressionInterface|object|scalar|null
-
The result value.
- $type : string|null = null
-
The result type. If no type is provided, the type will be tried to be inferred from the value.
Tags
Return values
$thisgetDefaultTypes()
Gets default types of current type map.
public
getDefaultTypes() : array<int|string, string>
Return values
array<int|string, string>getReturnType()
Returns the abstract type that this expression will return.
public
getReturnType() : string
If no type has been explicitly set via setReturnType()
, this
method will try to obtain the type from the result types of the
then()
and else()
calls. All types must be identical in order
for this to work, otherwise the type will default to string
.
Tags
Return values
stringgetTypeMap()
Returns the existing type map.
public
getTypeMap() : TypeMap
Return values
TypeMapsetDefaultTypes()
Overwrite the default type mappings for fields in the implementing object.
public
setDefaultTypes(array<int|string, string> $types) : $this
This method is useful if you need to set type mappings that are shared across multiple functions/expressions in a query.
To add a default without overwriting existing ones
use getTypeMap()->addDefaults()
Parameters
- $types : array<int|string, string>
-
The array of types to set.
Tags
Return values
$thissetReturnType()
Sets the abstract type that this expression will return.
public
setReturnType(string $type) : $this
If no type is being explicitly set via this method, then the
getReturnType()
method will try to infer the type from the
result types of the then()
and else()
calls.
Parameters
- $type : string
-
The type name to use.
Return values
$thissetTypeMap()
Creates a new TypeMap if $typeMap is an array, otherwise exchanges it for the given one.
public
setTypeMap(TypeMap|array<string|int, mixed> $typeMap) : $this
Parameters
- $typeMap : TypeMap|array<string|int, mixed>
-
Creates a TypeMap if array, otherwise sets the given TypeMap
Return values
$thissql()
Converts the Node into a SQL string fragment.
public
sql(ValueBinder $binder) : string
Parameters
- $binder : ValueBinder
-
Parameter binder
Tags
Return values
stringthen()
Sets the `THEN` result value for the last `WHEN ... THEN ...` statement that was opened using `when()`.
public
then(ExpressionInterface|object|scalar|null $result[, string|null $type = null ]) : $this
Order based syntax
This method can only be invoked in case when()
was previously
used with a value other than a closure or an instance of
\Cake\Database\Expression\WhenThenExpression
:
$case
->when(['Table.column' => true])
->then('Yes')
->when(['Table.column' => false])
->then('No')
->else('Maybe');
The following would all fail with an exception:
$case
->when(['Table.column' => true])
->when(['Table.column' => false])
// ...
$case
->when(['Table.column' => true])
->else('Maybe')
// ...
$case
->then('Yes')
// ...
$case
->when(['Table.column' => true])
->then('Yes')
->then('No')
// ...
Parameters
- $result : ExpressionInterface|object|scalar|null
-
The result value.
- $type : string|null = null
-
The result type. If no type is provided, the type will be tried to be inferred from the value.
Tags
Return values
$thistraverse()
Iterates over each part of the expression recursively for every level of the expressions tree and executes the $callback callable passing as first parameter the instance of the expression currently being iterated.
public
traverse(Closure $callback) : $this
Parameters
- $callback : Closure
-
The callable to apply to all nodes.
Tags
Return values
$thiswhen()
Sets the `WHEN` value for a `WHEN ... THEN ...` expression, or a self-contained expression that holds both the value for `WHEN` and the value for `THEN`.
public
when(ExpressionInterface|Closure|object|array<string|int, mixed>|scalar $when[, array<string, string>|string|null $type = null ]) : $this
Order based syntax
When passing a value other than a self-contained
\Cake\Database\Expression\WhenThenExpression
,
instance, the WHEN ... THEN ...
statement must be closed off with
a call to then()
before invoking when()
again or else()
:
$queryExpression
->case($query->identifier('Table.column'))
->when(true)
->then('Yes')
->when(false)
->then('No')
->else('Maybe');
Self-contained expressions
When passing an instance of \Cake\Database\Expression\WhenThenExpression
,
being it directly, or via a callable, then there is no need to close
using then()
on this object, instead the statement will be closed
on the \Cake\Database\Expression\WhenThenExpression
object using
\Cake\Database\Expression\WhenThenExpression::then()
.
Callables will receive an instance of \Cake\Database\Expression\WhenThenExpression
,
and must return one, being it the same object, or a custom one:
$queryExpression
->case()
->when(function (\Cake\Database\Expression\WhenThenExpression $whenThen) {
return $whenThen
->when(['Table.column' => true])
->then('Yes');
})
->when(function (\Cake\Database\Expression\WhenThenExpression $whenThen) {
return $whenThen
->when(['Table.column' => false])
->then('No');
})
->else('Maybe');
Type handling
The types provided via the $type
argument will be merged with the
type map set for this expression. When using callables for $when
,
the \Cake\Database\Expression\WhenThenExpression
instance received by the callables will inherit that type map, however
the types passed here will not be merged in case of using callables,
instead the types must be passed in
\Cake\Database\Expression\WhenThenExpression::when()
:
$queryExpression
->case()
->when(function (\Cake\Database\Expression\WhenThenExpression $whenThen) {
return $whenThen
->when(['unmapped_column' => true], ['unmapped_column' => 'bool'])
->then('Yes');
})
->when(function (\Cake\Database\Expression\WhenThenExpression $whenThen) {
return $whenThen
->when(['unmapped_column' => false], ['unmapped_column' => 'bool'])
->then('No');
})
->else('Maybe');
User data safety
When passing user data, be aware that allowing a user defined array to be passed, is a potential SQL injection vulnerability, as it allows for raw SQL to slip in!
The following is unsafe usage that must be avoided:
$case
->when($userData)
A safe variant for the above would be to define a single type for the value:
$case
->when($userData, 'integer')
This way an exception would be triggered when an array is passed for the value, thus preventing raw SQL from slipping in, and all other types of values would be forced to be bound as an integer.
Another way to safely pass user data is when using a conditions array, and passing user data only on the value side of the array entries, which will cause them to be bound:
$case
->when([
'Table.column' => $userData,
])
Lastly, data can also be bound manually:
$query
->select([
'val' => $query->newExpr()
->case()
->when($query->newExpr(':userData'))
->then(123)
])
->bind(':userData', $userData, 'integer')
Parameters
- $when : ExpressionInterface|Closure|object|array<string|int, mixed>|scalar
-
The
WHEN
value. When using an array of conditions, it must be compatible with\Cake\Database\Query::where()
. Note that this argument is not completely safe for use with user data, as a user supplied array would allow for raw SQL to slip in! If you plan to use user data, either pass a single type for the$type
argument (which forces the$when
value to be a non-array, and then always binds the data), use a conditions array where the user data is only passed on the value side of the array entries, or custom bindings! - $type : array<string, string>|string|null = null
-
The when value type. Either an associative array when using array style conditions, or else a string. If no type is provided, the type will be tried to be inferred from the value.
Tags
Return values
$this_castToExpression()
Conditionally converts the passed value to an ExpressionInterface object if the type class implements the ExpressionTypeInterface. Otherwise, returns the value unmodified.
protected
_castToExpression(mixed $value[, string|null $type = null ]) : mixed
Parameters
- $value : mixed
-
The value to convert to ExpressionInterface
- $type : string|null = null
-
The type name
_requiresToExpressionCasting()
Returns an array with the types that require values to be casted to expressions, out of the list of type names passed as parameter.
protected
_requiresToExpressionCasting(array<string|int, mixed> $types) : array<string|int, mixed>
Parameters
- $types : array<string|int, mixed>
-
List of type names