php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #49618 spl_autoload_register destroys __autoload hook
Submitted: 2009-09-22 05:24 UTC Modified: 2017-09-12 13:49 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:2 (100.0%)
From: jost dot boekemeier at googlemail dot com Assigned: cmb (profile)
Status: Closed Package: SPL related
PHP Version: 5.2.11 OS: *
Private report: No CVE-ID: None
 [2009-09-22 05:24 UTC] jost dot boekemeier at googlemail dot com
Description:
------------
The first call to spl_autoload_register destroys an existing __autoload hook.

Please either deprecate __autoload and/or register __autoload with spl_autoload.


Complete problem description is here: 

http://sourceforge.net/mailarchive/forum.php?
thread_name=3afa16cf0909210312v3e102491n18701bcca0f5e030%40mail.gmail.com
&forum_name=php-java-bridge-users



Reproduce code:
---------------
<?php 
function autoload_legacy($x) {echo "legacy "; return false;}
function autoload_spl1($x) {echo "spl1 "; return false;}
function autoload_spl2($x) {echo "spl2 "; return false;}
function autoload_spl3($x) {echo "spl3 "; return false;}
spl_autoload_register("autoload_spl1");
function __autoload($x) {return autoload_legacy($x);}
spl_autoload_register("autoload_spl2");
spl_autoload_register("autoload_spl3");

@new Foo();
?>


Expected result:
----------------
spl1 spl2 spl3 legacy

Actual result:
--------------
spl1 spl2 spl3

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-09-22 09:11 UTC] sjoerd@php.net
Thank you for your report.

I do not think the behavior you describe is a bug. The documentation is clear about this:
"If your code has an existing __autoload function then this function must be explicitly registered on the __autoload stack. This is because spl_autoload_register() will effectively replace the engine cache for the __autoload function by either spl_autoload() or spl_autoload_call()."

Thus, calling spl_autoload_register() replaces __autoload().
 [2009-09-22 09:26 UTC] jost dot boekemeier at googlemail dot com
My code doesn't use __autoload.

My code uses spl_autoloload.

I have received a bug report because my code has destroyed an existing library.


By issuing this bug report I have asked you to stop this, by either:

* deprecating __autoload altogether

* fix spl_autoload to honor an existing __autoload or

* let library authors check for an existing (or upcoming) __autoload so that their 
library doesn't destroy existing code

With the current behaviour I have no other choice but to not use spl_autoload at all, 
since I don't know whether the user will or will not include a library which uses 
__autoload later on.
 [2009-09-22 17:26 UTC] sjoerd@php.net
If two or more of the libraries use __autoload, it won't work, and there is nothing anybody can do about it.

If all of the libraries use spl_autoload_register, it works as it should.

If one of the libraries uses __autoload and others use spl_autoload_register, it is the task of the library that uses spl_autoload_register to register __autoload as well, like this:

if (function_exists("__autoload")) spl_autoload_register("__autoload");
 [2009-09-22 17:39 UTC] jost dot boekemeier at googlemail dot com
> if (function_exists("__autoload")) spl_autoload_register("__ autoload")

Doesn't work. In line 7 __autoload is not yet defined.

Note that every line in the given example comes from a separate include()d php 
library.

This is a link-time problem which only php can resolve: it must save a legacy 
__autoload handler before creating the spl_autoload stack and call the legacy 
autoload after all other registered spl_autoload hooks.
 [2009-09-23 07:23 UTC] sjoerd@php.net
So the problem occurs with:

include('spl_autoload_register.php'); // uses spl_autoload_register
include('autoload.php'); // defines __autoload
 [2009-09-23 08:53 UTC] jost dot boekemeier at googlemail dot com
Right. In particular: 

<?php // pjb library
function autoload_pjb($x) {echo "pjb "; return false;}
spl_autoload_register("autoload_pjb");
if(function_exists("__autoload")) spl_autoload_register("__autoload");
?>
<?php // joomla library
function __autoload($x) {echo "joomla "; return false;}
?>

<?php // application
require("pjb.php");
require("joomla.php");
@new Foo();
?>

Please see the link posted with the bug report for all the details.


However, I think neither the user nor joomla nor I have to invent strange 
workarounds for bugs in the php implementation. Any new introduced PHP feature 
must be compatible with earlier PHP features, unless the earlier features have been 
deprecated and a clear migration path exists.

The old __autoload is neither deprecated nor is spl_autoload_register compatible with 
it. Whoever wrote it and the comment "....This is because spl_autoload_register() will 
effectively replace the engine cache fo the __autoload function by either 
spl_autoload()  or spl_autoload_call(). "  wrote a bug.


> Thus, calling spl_autoload_register() replaces __autoload()

If spl_autoload_register is intended to replace the old __autoload machinery, the old 
__autoload should have been deprecated and a clear migration path should have 
been given to those using it.
 [2009-11-19 11:22 UTC] colder@php.net
There is no way to "fix" this in PHP.

__autoload in itself is not deprecated, but it is not a good idea to use it as part of a library, for obvious reasons. However, if you know your code will only have one autoload function, using __autoload will be just fine.

To me it seems that the library writers that still use __autoload are at fault here.
 [2010-12-20 09:13 UTC] jani@php.net
-Package: Feature/Change Request +Package: SPL related
 [2011-07-07 17:54 UTC] staff at pro-unreal dot de
How about that (php 5.3):

<?php
spl_autload_register(function($class) {
if (function_exists('__autoload') 
__autoload($class);
})
 [2017-09-12 13:49 UTC] cmb@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: cmb
 [2017-09-12 13:49 UTC] cmb@php.net
> Please either deprecate __autoload […]

__autoload() is deprecated as of PHP 7.2.0 and will be removed in
the next major version, see
<https://wiki.php.net/rfc/deprecations_php_7_2#autoload>.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Mon Mar 30 21:01:23 2020 UTC