[wp-trac] [WordPress Trac] #36335: Next generation: core autoloader proposal

WordPress Trac noreply at wordpress.org
Mon Jun 6 07:39:48 UTC 2016


#36335: Next generation: core autoloader proposal
-----------------------------+-----------------------------
 Reporter:  dnaber-de        |       Owner:
     Type:  feature request  |      Status:  new
 Priority:  normal           |   Milestone:  Future Release
Component:  General          |     Version:
 Severity:  normal           |  Resolution:
 Keywords:  2nd-opinion      |     Focuses:
-----------------------------+-----------------------------

Comment (by schlessera):

 Following up on further discussion with @rmccue , I want to detail a
 specific use case here, to illustrate why having a custom autoloader in
 Core would probably cause issues in the future, as this does not seem to
 be clear for everyone.

 PHP has a very strict limitation in that each class can only ever be
 defined once. So, if you try to define a class a second time, you'll get
 an error.

 Using an autoloader will remove that error, as the class definition is
 only loaded the first time the class is encountered and is not known yet.
 This creates another problem though. If you still have two class
 definitions with the same name, you don't know which one will get loaded.
 The autoloader will just load the first `require` statement it encounters,
 and never see the second definition. This is no issue if both of the class
 definitions are the same, but if you have `AClass` v1.0.0 & `AClass`
 v2.0.0, you can't be sure which one will get loaded. If v1.0.0 happens to
 be encountered first, all code relying on v2.0.0 will produce random
 errors, which are hard to debug, because they might not even appear in a
 consistent way.

 Every autoloader implementation will face this issue.

 What is currently considered best practice (mostly used for larger
 projects), is to have Composer deal with generating the autoloaders, and
 let it do so recursively from the site root (a site-wide Composer
 install). Composer will generate 1 single autoloader that will include the
 requested autoloaders at each sub-level, and always try to compare the
 version requirements to make sure that such an issue as described above
 can not happen. In this scenario, the WordPress Core, also being part of
 the site root, is also pulled in via Composer.

 If it encounters a conflict, it will immediately throw an error, which is
 much preferable to bugs that you can hardly replicate. So, generating the
 autoloader through Composer will either work reliably, or immediately
 throw an error pointing you to the exact plugin/theme/library that is
 causing an issue.

 If you now include a custom autoloader within WordPress Core, Composer
 will not be able to include this autoloader in its set of checks. So,
 plugins' libraries' versions will not be verified against WordPress'
 libraries' versions, and the WordPress Core autoloading code will not be
 included in the one generated at the site root.

 You can not even control anymore which autoloader will get precedence,
 because the loading order of the autoloader does not equal the loading
 order of their respective classes. As the classes are only loaded when
 they are actually needed to be referenced, you might get either one,
 depending on what exact path you ran through the codebase. So you'll end
 up with completely unreliable code that might break without any readily
 apparent patterns.

 I am currently one of the people who are heavily using Composer with such
 a site-wide autoloader with large projects. This all works perfectly (and
 much better than any pre-Composer code), as long as the libraries (Core,
 plugins, themes, ...) either include a Composer autoloader, or no
 autoloader at all.

 The reason why this is used is because there's no other way to get
 different sets of autoloaders to work reliably otherwise, because of this
 inherent PHP limitation. There's namespaces to avoid collisions to even
 happen at all, but they only work for a certain category of code. For code
 such as reusable libraries, which might be used in several places at once
 (Core + 5 plugins, each working with the same library), you are certain to
 have the exact same namespace used in several locations, and they cannot
 be resolved properly through the autoloader alone. An external check has
 to be made to ensure that they never want to include conflicting versions,
 there's no way around that.

 So, considering the above, my assertions would be that:

 * '''Reliable autoloading in PHP will eventually need namespaces +
 Composer + dependency management'''
 * '''A custom autoloader is certain to negatively impact reliable
 autoloading in PHP'''

 '''Note:'''
 ''I did not want to talk about dependency management here to not veer
 discussion into the wrong direction. However, my last discussion with
 @rmccue made me aware that it cannot be completely ignored, as autoloading
 for an entire project (not just WP alone) cannot possibly work reliably
 without dependency management. And while I only want to discuss a Core
 autoloader for now (so please don't focus on the dependency management
 part now), I felt I needed to explain my reasons why I think a custom
 autoloader would prove to be problematic in the future. Only considering
 Core in isolation will not reveal these issues.''

--
Ticket URL: <https://core.trac.wordpress.org/ticket/36335#comment:44>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list