PHP Oddity: Variable Assigned in Expression Cast as Bool
When blog posts here slow down as they have over the last few weeks, it’s a good bet I have my head down building something.
I ran across an issue today that I’d worked around in the past, but had never explicitly investigated. It appears that when assigning a variable within a multiple condition check in PHP, if you don’t explicitly look for a value the first item in the expression is cast as a bool.
I particularly use this technique a lot in CodeIgniter, for example when pulling data from $this->input->post('foo') – a method that will either return semi-sanitized data from $_POST['foo'] or will return false.
I tested this in PHP 5.3 (built-in version on Snow Leopard).
Here is some sample code that demonstrates this issue, and the workaround.
function foo() {
return 'foo';
}
function bar() {
return 'bar';
}
if ($foo = foo()) {
echo '<p>Condition <code>$foo = foo()</code> passed</p>';
}
var_dump($foo);
echo '<hr />';
if ($foo = foo() && $bar = bar()) {
echo '<p>Condition <code>$foo = foo() && $bar = bar()</code> passed</p>';
}
var_dump($foo);
echo '<hr />';
if ($foo = foo() && $bar = bar()) {
echo '<p>Condition <code>$foo = foo() && $bar = bar()</code> passed</p>';
}
echo '<p>$foo:<br />';
var_dump($foo);
echo '<p>$bar:<br />';
var_dump($bar);
echo '<hr />';
if (false !== ($foo = foo()) && $bar = bar()) {
echo '<p>Condition <code>false !== ($foo = foo()) && $bar = bar()</code> passed</p>';
}
echo '<p>$foo:<br />';
var_dump($foo);
echo '<p>$bar:<br />';
var_dump($bar);
Here is the output of this code:
Condition $foo = foo() passed
string(3) “foo”
Condition $foo = foo() && $bar = bar() passed
bool(true)
Condition $foo = foo() && $bar = bar() passed
$foo:
bool(true)
$bar:
string(3) “bar”
Condition false !== ($foo = foo()) && $bar = bar() passed
$foo:
string(3) “foo”
$bar:
string(3) “bar”
Hopefully this will be useful to someone else when they run across this issue.
Know why PHP works this way? Let me know in the comments.
UPDATE: wrapping each expression in parenthesis works around this. See comments for more detailed explanation.













