Short circuit evaluation and include

From: Date: Tue, 02 Dec 2008 10:55:20 +0000
Subject: Short circuit evaluation and include
Groups: php.general 
Request: Send a blank email to php-general+get-283986@lists.php.net to get a copy of this message
Hello everyone, I'm posting this as a warning when using include() or include_once() and checking their return values. I'm refactoring someone else's code at the moment and got a short circuit evaluation problem that made some problems .. Here's the code: FILE "some_file.php": <?php function some_function($file) { $obj = false; if ( !isset($file) || !is_string($file) || !is_readable($file) || !include_once($file) || !class_exists('some_class') || !is_a(($obj = new some_class()), 'some_class') || !method_exists($obj, 'some_method') || !$obj->some_method() ) return false; // line 14 return $obj; } $file = 'some_class.php'; some_function($file); ?> FILE "some_class.php": <?php class some_class { function some_method() { return true; } } ?> ERRORS PRODUCED: Warning: some_function(1) [function.some-function]: failed to open stream: No such file or directory in */some_file.php on line 14 Warning: some_function() [function.include]: Failed opening '1' for inclusion (include_path='.;*/php/pear/') in */some_file.php on line 14 Note: I ran this code in PHP 4.4.9 It seemed to me like include_once() was not fully executed or something when "short circuited", because this code worked just fine ... FILE "some_file.php": <?php function some_function($file) { $obj = false; if ( !isset($file) || !is_string($file) || !is_readable($file) || !include_once($file) ) return false; if ( !class_exists('some_class') || !is_a(($obj = new some_class()), 'some_class') || !method_exists($obj, 'some_method') || !$obj->some_method() ) return false; return $obj; } $file = 'some_class.php'; var_dump(some_function($file)); ?> OUTPUT: object(some_class)(0) { } So I was wondering how include() or include_once() are actually being executed. I know they both return int(1) if no return specified in the included file. That's why I had a glance at the manual [1], where I saw this .. Because include() is a special language construct, parentheses are not needed around its argument. Take care when comparing return value. Example #4 Comparing return value of include <?php // won't work, evaluated as include(('vars.php') == 'OK'), i.e. include('') if (include('vars.php') == 'OK') { echo 'OK'; } // works if ((include 'vars.php') == 'OK') { echo 'OK'; } ?> So when I added the paranthesis it worked ... FILE "some_file.php": <?php function some_function($file) { $obj = false; if ( !isset($file) || !is_string($file) || !is_readable($file) || !(include_once($file)) // <--- added paranthesis || !class_exists('some_class') || !is_a(($obj = new some_class()), 'some_class') || !method_exists($obj, 'some_method') || !$obj->some_method() ) return false; return $obj; } $file = 'some_class.php'; var_dump(some_function($file)); ?> Me, after an hour of coding without a line of code. [1] http://in.php.net/manual/en/function.include.php

« previous php.general (#283986) next »