php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39542 Behaviour of require/include different to < 5.2.0
Submitted: 2006-11-17 06:24 UTC Modified: 2007-05-11 08:03 UTC
Votes:4
Avg. Score:4.8 ± 0.4
Reproduced:4 of 4 (100.0%)
Same Version:3 (75.0%)
Same OS:1 (25.0%)
From: snowy at corporatezoo dot com Assigned: dmitry (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.2.2 OS: Windows XP
Private report: No CVE-ID: None
 [2006-11-17 06:24 UTC] snowy at corporatezoo dot com
Description:
------------
Behaviour of require/include different to < 5.2.0.

I'm not sure if this is by design, couldn't find any reference to it in release notes. Basically, the search order of an include seems to always start with ./ instead of in the order of get_include_path(). This is problematic, esp in the case of using autoload, where a filename eg in ./index.php might be the same as ../classes/Index.php, ./index.php gets autoloaded instead of ../classes/Index.php

Reproduce code:
---------------
//index.php
set_include_path('../classes;.');
function __autoload($class)
{
    if (!require_once($class.'.php')) {
        error_log('Error: Autoload class: '.$class.' not found!');
    }
}

$index = new Index();

//../classes/Index.php
class Index
{
//blah
}

Expected result:
----------------
In 5.1.6, it works ok, loads Index.php




Actual result:
--------------
in 5.2.0,

Fatal error: Class 'Index' not found in c:\docroot\index.php

I suspect it's looking for a class in index.php (Which is the currently executed script).

Is this an architectural change? Or is this a bug?

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-11-17 11:35 UTC] tony2001@php.net
Not reproducible on Linux.
 [2006-11-17 14:05 UTC] snowy at corporatezoo dot com
tony, sorry I just realised that example might be different in linux because of being case sensitive.

could you try renaming the files and class name to "index"... ie, "../classes/index.php" and "class index".

See which one it tries to load up first. thx
 [2006-11-17 14:11 UTC] tony2001@php.net
I didn't use your example, I tested it in another way.
 [2006-11-17 15:25 UTC] tony2001@php.net
What if you change "../classes" to the full path?
 [2006-11-17 23:39 UTC] snowy at corporatezoo dot com
actually I am using full paths, I'm doing a:

define('SITEROOT_DIR','/web/myproject');
define('FRAMEWORK_DIR','/web/framework');
define('SITECLASS_DIR',SITEROOT_DIR.'/_application');
set_include_path(SITECLASS_DIR.';'.FRAMEWORK_DIR.';'.get_include_path());

and /web/myproject/docroot is the docroot

(I've always been using this kind of naming with "/" for windows since 4.0.x in case I need compat)

It's almost as if it found index.php in the current namespace, and decides it doesn't need to go to include_path to look for one? just guessing...
 [2006-11-17 23:45 UTC] snowy at corporatezoo dot com
Oh btw (in case it wasn't obvious), the "remedy" is

1) rename the class file to "fooIndex.php"
2) rename the class to fooIndex
3) in index.php, $index = new fooIndex();

so the issue is when the script "driver" file (ie, the one in docroot) is named the same as the class file (in the class path) even when the 2 files are of different case (index.php vs Index.php).
 [2006-11-28 22:45 UTC] snowy at corporatezoo dot com
Hi any update on this? btw, in case it was confusing, that wasn't a "fix" I posted, it is merely a way to circumvent the behaviour.

Obviously this "fix" would require the renaming of all php class files in old code, which is an extreme pain, but it would be ok, if I could just confirm what the new "behaviour" of includes is meant to be.

If there is not supposed to be a change in the behaviour of includes/requires, then this is probably a bug
 [2007-02-02 16:48 UTC] jsnell at e-normous dot com
Also seeing this in: PHP 5.2.0-8 (cli) (built: Dec 17 2006 20:03:51) using Linux relay 2.4.29 #2 SMP Sat Mar 12 13:17:01 CST 2005 i686 GNU/Linux
 [2007-02-02 22:02 UTC] jsnell at e-normous dot com
Test case:
Create a file called test.php with the following:
<?php
set_include_path(dirname(__FILE__).'/lib/');
echo(get_include_path()."\n");
require_once('test.php');
?>
and create a subdirectory called lib, containing a file called test.php with the following contents:
Included Test from lib/

Results with php 4 (PHP 4.4.4 (cli) (built: Nov  1 2006 18:10:56) -- osx 10.4.x:
/Users/jsnell/delete/php5/testcase/lib/
Included Test from lib/

Results with PHP 5.1.4 (PHP 5.1.4 (cli) (built: Jan 25 2007 11:50:25) ):
php5 test.php
/Users/jsnell/delete/php5/testcase/lib/
Included Test from lib/

Results with PHP CVS (anon checked out on February 2nd):
../sapi/cli/php test.php
/Users/jsnell/delete/php5/testcase/

--
I believe the original submission is wrong, by changing require_once() to require(), the file from lib/ is being loaded.
 [2007-02-02 22:22 UTC] snowy at corporatezoo dot com
oh so maybe the search order is different between require and require_once?

hmmm makes senses since it looks like a namespace caching issue.
 [2007-02-05 14:01 UTC] tony2001@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip


 [2007-02-09 05:11 UTC] snowy at corporatezoo dot com
hi tried the windows snap, also just tried 5.2.1 and same problem.

I'll just confirm with jsnell's observation that it is indeed require_once that is throwing that exception.

require seems to work fine.

ie

function __autoload($class)
{
    require_once($class . '.php');
}

breaks

whilst

function __autoload($class)
{
    require($class . '.php');
} 

works
 [2007-02-13 16:42 UTC] jsnell at e-normous dot com
still fails for me in the latest snapshot:

One other thing to note, it functions differently depending on where you call the script from:
e-normous:/Users/jsnell/delete/php5/testcase/lib$ ../../../php5.2-200702131330/sapi/cli/php ../test.php
/Users/jsnell/delete/php5/testcase/lib/
Included Test from lib/

vs.

e-normous:/Users/jsnell/delete/php5/testcase$ ../../php5.2-200702131330/sapi/cli/php ./test.php
/Users/jsnell/delete/php5/testcase/lib/

and

e-normous:/Users/jsnell/delete/php5/testcase$ ../../php5.2-200702131330/sapi/cli/php test.php
/Users/jsnell/delete/php5/testcase/lib/
 [2007-03-12 07:28 UTC] snowy at coporatezoo dot com
tried this on 5.2.1 on OSX as well and it also fails.

Another thing:

if my file is in /project/docroot/file.php

even if I do a:

require_once('/project/classes/File.php');

it still fails.

Notice that it's (1) case insensitive, (2) the actual full path is given in require_once.

I thought it may have been caching the full path, but looks like it's only looking if '[F|f]ile.php' (the file name) has been loaded.

Ie, even

set_include_path('/project');
require_once('classes/file.php'); // give a path name to avoid namespace clash

doesn't work.

Is this going to be fixed? Or should we go and change all our include_once/require_once if we want to upgrade to > 5.1.6?

thx
 [2007-03-15 07:13 UTC] snowy at coporatezoo dot com
Hi, so I caught this while reading the change log for 5.2.0:

"Optimized require_once() and include_once() by eliminating fopen(3) on second usage. (Dmitry)"

Perhaps this might be the issue, it might be optimized, but I'm not sure if it's entirely correct.
 [2007-04-26 09:34 UTC] tony2001@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip


 [2007-05-05 14:35 UTC] snowy at coporatezoo dot com
Hi, just tried this with php 5.2.2 (win32) and it's still not behaving as < 5.2.0

I still suspect it has to do with the "optimization" introduced for require_once.

I actually believe the behaviour to be incorrect, in that (1) some sort of namespace for the file is held in cache, albeit not case-sensitive, and (2) in the wrong search order (.= current directory seems to always be searched first, no matter what set_include_path stipulates)

I just find it strange that no once else comes across this problem?
 [2007-05-11 08:03 UTC] dmitry@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC