Bug #68026 [Nab]: create_function() fails

From: Date: Thu, 18 Sep 2014 13:54:08 +0000
Subject: Bug #68026 [Nab]: create_function() fails
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-187589@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=68026&edit=1 ID: 68026 Updated by: johannes@php.net Reported by: jmichae3 at yahoo dot com Summary: create_function() fails Status: Not a bug Type: Bug Package: Scripting Engine problem Operating System: Windows 7 pro x64 sp1 PHP Version: 5.5.16 Block user comment: N Private report: N New Comment: Please go to a support forum. There is no bug here. Variable variables, create_function() and is_callable() work as they should. Previous Comments: ------------------------------------------------------------------------ [2014-09-18 11:11:51] jmicha3 at yahoo dot com "Your code to test function creation should be !is_callable(${'is'.$AcctTypes[$i].'file'})" this does not match what is given in the example in the documentation (although it works somehow regardless of the example). http://php.net/manual/en/function.is-callable.php this is exacerbated by another lack of definition or proper link for the linked term "callable" at http://php.net/manual/en/language.types.callable.php which leads to the top of the same page and gives no definition for the "callable" type hint. I have no clue what a type hint is. so I put "type hint" in the search box, and I got "not found". <?php $a=array('admin','user','moderator'); for ($i=0; $i<count($a); $i++) { ${'abc'.$a[$i].'file'}=$a[$i] . $i; if (isset(${'abc'.$a[$i].'file'})) { echo 'abc'.$a[$i].'file'."=".${'abc'.$a[$i].'file'}."\n"; } } echo ${'abcadminfile'}."\n"; ?> D:\prj\test\php\varvar>php varvar.php abcadminfile=admin0 abcuserfile=user1 abcmoderatorfile=moderator2 admin0 D:\prj\test\php\varvar> https://bugs.php.net/bug.php?id=68026 variable variables *do* in fact work, and there is no conflict with existing function names etc. <?php $s='moderator'; $funcbody =' return ((strpos($filepath,"/admin/") !== false'; $funcbody.= ' && strpos($filepath,"/admin/") <=3));'; //is this in the /admin/ or /moderator/ etc directory off root? $isadminfile=create_function('$filepath',$funcbody); ${'is'.$s.'file'}=create_function('$filepath',$funcbody); echo "isset(\$".'isadminfile'.")=".(isset($isadminfile)?"true\n":"false\n"); echo "function_exists(".'isadminfile'.")=".(function_exists('isadminfile')?"true\n":"false\n"); echo "is_callable(\${".'isadminfile'."})=".(is_callable(${'isadminfile'})?"true\n":"false\n"); echo "\n"; echo "isset(\${'is'.\$s.'file'.})=".(isset(${'is'.$s.'file'})?"true\n":"false\n"); echo "function_exists('is'.\$s.'file')=".(function_exists('is'.$s.'file')?"true\n":"false\n"); echo "is_callable(\${'is'.\$s.'file'})=".(is_callable(${'is'.$s.'file'})?"true\n":"false\n"); ?> Wed 09/17/2014 22:40:34.28|D:\prj\test\php\create_function||>PHP CF.PHP isset($isadminfile)=true function_exists(isadminfile)=false is_callable(${isadminfile})=true isset(${'is'.$s.'file'.})=true function_exists('is'.$s.'file')=false is_callable(${'is'.$s.'file'})=true Wed 09/17/2014 22:40:49.20|D:\prj\test\php\create_function||> unfortunately, I have just found a bug in function_exists(). instead of taking a string which is the function name, it takes the lambda function body itself. look at the results above. this does not match the manual's description and example for this argument. http://php.net/manual/en/function.function-exists.php strangely enough, when I try function_exists() on a php built-in function instead of a lambda function, it works. let's try a built-in function: <?php var_dump(function_exists('create_function')); ?> D:\prj\test\php\function_exists>php fe.php bool(true) D:\prj\test\php\function_exists> so the failure bug in function_exists only happens under the condition where a lambda function is used. ------------------------------------------------------------------------ [2014-09-17 10:35:34] johannes@php.net You assume $isAdminfile = create_function(...); to create a function isAdminfile as previously said and written in the docs this not the case. It creates a function called \0lambda_1 and returns that name. A way to fix your code was provided above. Aside from that - even if features exist there might be tools which haven proven to be better. create_function() takes code as a string parameter which makes reading and writing hard and also inefficient. The documentation explicitly mentions closures. Just from the code I don't see the reason for this either, though as this could be a normal function with the type as parameter ... but there might be a valid reason not to do that. It might also be worth for you to look at foreach and explode() to write more efficient code. But as said: This is no support forum. create_function() works like expected and documented. With the suggested fix your code gave the expected result. ------------------------------------------------------------------------ [2014-09-17 09:10:14] jmichae3 at yahoo dot com Your code to test function creation should be !is_callable(${'is'.$AcctTypes[$i].'file'}) But please, do a favor for everyone who has to deal with your code: 1. Stop using globals 2. Don't use variable variables 3. Don't dynamically create important functions is_callable(): your syntax is wrong according to the manual, and anyway it fails when I use it: "Stop using globals": no law against using globals. unless the global keyword is only for making an outside variable visible inside a function, in which case you need to say that in the manual, so that's a documentation bug, because that's not stated. I wanted to declare my vars with global-scope and have it visible all throughout my code. they are really important variables. "Don't dynamically create important functions": in other words, don't rely on the spec or any functions in the manual, throw the manual away. if a given function is documented as being there, php.net is not really giving it to you, it's just virtual? do you realize what you just said and how backwards that sounds? ERROR: lamba function isadminfile() doesn't exist. ERROR: lamba function name isadminfile is not callable. ERROR: lamba function ispaidblsfile() doesn't exist. ERROR: lamba function name ispaidblsfile is not callable. ERROR: lamba function ispaidmusicfile() doesn't exist. ERROR: lamba function name ispaidmusicfile is not callable. ERROR: lamba function isuserfile() doesn't exist. ERROR: lamba function name isuserfile is not callable. so you are basically saying stop writing code period? I am just following spec. everything I am trying are things the manual says I should be able to do, like variable variables etc. I fully expect them to work. if it doesn't work, then fix the bugs please. found 2 PHP bugs already just trying to convert my code to a new way of doing things. ------------------------------------------------------------------------ [2014-09-17 08:25:44] requinix@php.net This is not the place for an in-depth explanation of why your code is wrong. Please re-read what I said, or try an online forum or mailing list. http://php.net/support.php ------------------------------------------------------------------------ [2014-09-17 08:09:50] jmichae3 at yahoo dot com you dismissed the bug out of hand, it's still valid. for ($i=0; $i < count($AcctTypes); $i++) { //global ${'is'.$AcctTypes[$i].'file'}; //in our web site, we detect if the /admin/ directory $funcbody =' return ((strpos($filepath,"/'.$AcctTypes[$i].'/") !== false'; $funcbody.= ' && strpos($filepath,"/'.$AcctTypes[$i].'/") <=3));'; //is this in the /admin/ or /moderator/ etc directory off root? //create the function from the function body in $funcbody with name in $funcname ${'is'.$AcctTypes[$i].'file'}=create_function('$filepath', $funcbody); //aggregate any failures so we can see what's wrong and fix it $anyError=false; if (!isset(${'is'.$AcctTypes[$i].'file'})) { echo "ERROR: lambda function name variable ".'is'.$AcctTypes[$i].'file'." failed isset().\n"; $anyError=true; } if (!function_exists('is'.$AcctTypes[$i].'file')) { echo "ERROR: lamba function ".'is'.$AcctTypes[$i].'file'."() doesn't exist.\n"; $anyError=true; } } if ($anyError) { die("----please fix code.\n"); } output: ERROR: lamba function isadminfile() doesn't exist. ERROR: lamba function ispaidblsfile() doesn't exist. ERROR: lamba function ispaidmusicfile() doesn't exist. ERROR: lamba function isuserfile() doesn't exist. ----please fix code. regardless of whether it contained a functoin name or not, its contents would have been replaced with a function (supposedly) by the call to create_function, would it not? what I needed was to make a variable with a variable name (which I could base on a for loop to make a number of functions) that is also a function name. but this is consistently failing. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=68026 -- Edit this bug report at https://bugs.php.net/bug.php?id=68026&edit=1

« previous php.bugs (#187589) next »