MonkeyZeus MonkeyZeus - 7 months ago 31
PHP Question

Namespacing with eval() and include() does not work as expected

I am just messing around and I've come across this:




Doesn't work

<?php
namespace first{
include 'data:text/plain, <?php function a_func(){echo "hi";}';
a_func();
}
namespace second{
include 'data:text/plain, <?php function a_func(){echo "bye";}';
a_func();
}



[29-Apr-2016 14:12:42 America/New_York] PHP Fatal error: Cannot redeclare a_func() (previously declared in data:text/plain, <?php function a_func(){echo "hi";}:1) in data:text/plain, <?php function a_func(){echo "bye";} on line 1


Doesn't work

<?php
namespace first{
eval('function a_func(){echo "hi";}');
a_func();
}
namespace second{
eval('function a_func(){echo "bye";}');
a_func();
}



[29-Apr-2016 14:19:21 America/New_York] PHP Fatal error: Cannot redeclare a_func() (previously declared in C:\path\test.php(3) : eval()'d code:1) in C:\path\test.php(7) : eval()'d code on line 1


Works

<?php
namespace first{
function a_func(){echo "hi";}
a_func();
}
namespace second{
function a_func(){echo "bye";}
a_func();
}





Tested in PHP 5.6.20 and 7.0.5




Is this a bug? Feature? Purposefully implemented?




Extra credit: How do I make either the
include()
or
eval()
work?

Jon Jon
Answer

include and eval cause the compiler to process their input as if it is coming from a separate file in both cases.

This means that your namespace declarations in the setup code don't transfer to the code coming in from include/eval, and the functions which are defined there are defined in the global namespace. You can verify this easily with

<?php
namespace outer;

eval('function func(){}');
var_dump(function_exists('\outer\func'));    // false
var_dump(function_exists('\func'));          // true

To get the expected behavior you must include the namespace declarations in the code being pulled in:

<?php
namespace first{
    include 'data:text/plain,<?php namespace first; function a_func(){echo "hi";}';
    a_func();
}
namespace second{
    include 'data:text/plain,<?php namespace second; function a_func(){echo "bye";}';
    a_func();
}

and

<?php
namespace first{
    eval('namespace first; function a_func(){echo "hi";}');
    a_func();
}
namespace second{
    eval('namespace second; function a_func(){echo "bye";}');
    a_func();
}