php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68026 create_function() fails
Submitted: 2014-09-16 09:26 UTC Modified: 2014-09-18 13:54 UTC
From: jmichae3 at yahoo dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.5.16 OS: Windows 7 pro x64 sp1
Private report: No CVE-ID: None
 [2014-09-16 09:26 UTC] jmichae3 at yahoo dot com
Description:
------------
create_function doesn't seem to actually create the function.

Test script:
---------------
$AcctTypes=preg_split('/,/', 'admin,paidbls,paidmusic,user');
for ($i=0; $i < count($AcctTypes); $i++) {
    global ${'is'.$AcctTypes[$i].'file'};
    $funcbody='{    global $AcctTypes;';
    $funcbody.="    if (strpos(\$filepath,\"/".$AcctTypes[$i]."/\") !== FALSE";
    $funcbody.="     && strpos(\$filepath,\"/".$AcctTypes[$i]."/\") !== ''";
    $funcbody.="     && strpos(\$filepath,\"/".$AcctTypes[$i]."/\") <=3) {";
    $funcbody.='        return TRUE;';
    $funcbody.='    } else {';
    $funcbody.='        return FALSE;';
    $funcbody.='    } }';
    //create the function from the function body in $funcbody with name in $funcname
    ${'is'.$AcctTypes[$i].'file'}=create_function('$filepath', $funcbody);
}
for ($i=0; $i < count($AcctTypes); $i++) {
    if (!function_exists('is'.$AcctTypes[$i].'file')) {
        die("\n\nERROR:config file needs function ".'is'.$AcctTypes[$i].'file'."()\n\n");
    }
}


Expected result:
----------------
functions created, no output.

Actual result:
--------------
( my error when function not defined) 
ERROR:config file needs function isadminfile()


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-09-16 17:26 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2014-09-16 17:26 UTC] requinix@php.net
Sorry, but your problem does not imply a bug in PHP itself.  For a
list of more appropriate places to ask for help using PHP, please
visit http://www.php.net/support.php as this bug system is not the
appropriate forum for asking support questions.  Due to the volume
of reports we can not explain in detail here why your report is not
a bug.  The support channels will be able to provide an explanation
for you.

Thank you for your interest in PHP.

You have not defined a function named "isadminfile". The $isadminfile variable contains a function. So in code where you want to use them you'd have to do
  global $isadminfile;
  $return = $isadminfile($filepath);

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
 [2014-09-16 17:27 UTC] requinix@php.net
>The $isadminfile variable contains a function.
Well, technically it contains a function name, not a closure.
 [2014-09-17 08:09 UTC] 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.
 [2014-09-17 08:25 UTC] 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 09:10 UTC] 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 10:35 UTC] 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-18 11:11 UTC] 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-18 13:54 UTC] johannes@php.net
Please go to a support forum. There is no bug here. Variable variables, create_function() and is_callable() work as they should.
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Wed Oct 07 09:00:02 2026 UTC