rfc:function_autoloading4

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:function_autoloading4 [2024/08/18 08:39] – added mismatched arguments to backwards incompatibilities withinboredomrfc:function_autoloading4 [2024/09/04 19:07] (current) – fix example withinboredom
Line 10: Line 10:
  
 The topic of supporting function autoloading was brought up many times in the past, this RFC introduces a potential implementation which would be consistent with what we have for autoloading classes. The topic of supporting function autoloading was brought up many times in the past, this RFC introduces a potential implementation which would be consistent with what we have for autoloading classes.
 +
 +By using autoloaders, programmers can already get quickly up to speed when it comes to classes, but the language currently lacks a way to do the same for functions. This requires programmers to manually (and carefully) include files that must be included on every request. For 'functional' codebases, they lose the ability to use autoloaders, or they must write their functions as static methods on classes. This isn’t ideal, and this RFC seeks to close the gap between functions and classes.
  
 ===== Proposal ===== ===== Proposal =====
  
-Before getting into the details, there are a few terms worth acknowledging so that the proposal can be easily discussed without getting confused: +This RFC proposes to add two new constants to the SPL extension: ''%%SPL_AUTOLOAD_CLASS%%'', ''%%SPL_AUTOLOAD_FUNCTION%%''These constants may be passed to ''%%spl_autoload_register%%'' as the fourth parameter to register an autoloader for classes or functions, respectively. If not specified, the default value ''%%SPL_AUTOLOAD_CLASS%%'' will be used to retain backward compatibility.
- +
-  - **Defined function**: A function that the engine has knowledge of, such as in a previously included/required file. +
-  - **Undefined function**: A function that the engine does not have knowledge of. +
-  - **Function autoloading**: The process of loading a function that is not defined. +
-  - **Written function**: A function that exists in a file that the engine may or may not have knowledge of. +
-  - **Local scope**: The current namespace +
-  - **Global scope**The global namespace (''%%\%%''+
- +
-The suggested change would be pretty straightforward and backwards-compatible: +
- +
-  - Add two new constants to spl: SPL_AUTOLOAD_CLASS, SPL_AUTOLOAD_FUNCTION. +
-  - Add a fourth optional parameter for spl_autoload_register, with a default value of SPL_AUTOLOAD_CLASS. +
-  - The type for the missing token should also be passed to the $autoload_function callback as a second param. (e.g., SPL_AUTOLOAD_CLASS for classes, SPL_AUTOLOAD_FUNCTION for functions) +
-  - Change the current class autoloading to only call the autoloaders which match with the SPL_AUTOLOAD_CLASS types. +
-  - Add the function autoloading to only call the autoloaders which match with the SPL_AUTOLOAD_FUNCTION types. +
- +
-There won’t be any changes to the current autoloading mechanism when it comes to classes. However, if a function +
- +
-  - is called in a fully qualified form (e.g., a ''%%use%%'' statement or ''%%\%%'' prefix is used), +
-  - is not defined, +
-  - and an autoloader is registered with the SPL_AUTOLOAD_FUNCTION type+
  
-then the autoloader will be called with the function name as the first parameter (with the initial slash removed) and SPL_AUTOLOAD_FUNCTION as the second parameter.+There won’t be any changes to the current autoloading mechanism when it comes to classes.
  
-However, if a function+==== Function Autoloading ====
  
-  - is called in an unqualified form (e.g., ''%%strlen()%%''), +The function autoloader will be called with the fully qualified undefined function nameThis will allow the function autoloader to determine how to load or generate the function.
-  - is not defined locally +
-  - and an autoloader is registered with the SPL_AUTOLOAD_FUNCTION type+
  
-then the autoloader will be called with the current namespace prepended to the function name. If the autoloader chooses to look up the "basename" of the function, it may do so. If the function is still undefined in the local scope, then it will fall back to the global scope—unless the local scope is the global scopeThe function autoloader will not be called again+PHP allows programmers to call an unqualified function name. Traditionally, this means that PHP would first search in the current namespace for the function and then fall back to the global namespace if the function is not found. This behavior will be preservedHowever, the function autoloader will be called **only once** for the current namespace; thus, the function autoloader will not be called again if the function is found in the global namespace.
- +
-This provides an opportunity for an autoloader to check for the existence of a function in the local scope and define it, as well as defer to the global scope if it is not defined.+
  
 Example "''%%PSR-4-style%%''" (except the last part of the namespace is the file it is in) function autoloader: Example "''%%PSR-4-style%%''" (except the last part of the namespace is the file it is in) function autoloader:
Line 53: Line 30:
 <?php <?php
  
-spl_autoload_register(function ($function, $type) { +spl_autoload_register(function ($function) { 
-    if ($type === SPL_AUTOLOAD_FUNCTION) { +    $function_path = dirname(str_replace('\\', DIRECTORY_SEPARATOR, $function)); 
-        $function_path = dirname(str_replace('\\', DIRECTORY_SEPARATOR, $function)); +    $file = __DIR__ . '/functions/' . $function_path . '.php';
-        $file = __DIR__ . '/functions/' . $function_path . '.php';+
  
-        if (file_exists($file)) { +    if (file_exists($file)) { 
-            require_once $file; +        require_once $file;
-        }+
     }     }
 }, false, false, SPL_AUTOLOAD_FUNCTION); }, false, false, SPL_AUTOLOAD_FUNCTION);
 </code> </code>
  
-Performance-wise, this should have minimal impact on existing codebases as there is no default function autoloader.+==== Performance Impact ====
  
-For codebases that want to take advantage of function autoloading, it may be desirable to stick with FQNs for functions and/or employ caches and other techniques where possible.+Function autoloading doesn’t appear to have a significant impact on performance; however, the function autoloader itself (depending upon its implementation) may have a performance impact. 
 + 
 +To help mitigate any potential performance impact of function autoloading many unqualified functionsa function will only be searched for once per namespace.
  
 ==== spl_autoload ==== ==== spl_autoload ====
  
-The ''%%spl_autoload%%'' function will not be updatedFor backwards compatibilitythere will be no changes to class autoloading and there will not be default function autoloader.+The ''%%spl_autoload%%'' function will not be modifiedIt may be used as a function autoloader if the programmer desiresthough it will limit the programmer to a single function per file. 
 + 
 +==== spl_autoload_unregister ==== 
 + 
 +''%%spl_autoload_unregister%%'' will be updated to accept the new constants as the second parameter to unregister an autoloader from either mode. 
 + 
 +==== spl_autoload_functions ==== 
 + 
 +''%%spl_autoload_functions%%'' will be updated to accept one of the new constants as the first parameter. Passing both (i.e., ''%%SPL_AUTOLOAD_CLASS | SPL_AUTOLOAD_FUNCTION%%'') will result in all registered functions.
  
 ==== spl_autoload_call ==== ==== spl_autoload_call ====
  
-The ''%%spl_autoload_call%%'' function will be modified to accept a second parameter of one, (but not bothof the new constants, with the default value set to SPL_AUTOLOAD_CLASS. The name of the first parameter will be changed to ''%%$name%%'' to reflect that it can be a class or function name.+The ''%%spl_autoload_call%%'' function will be modified to accept a second parameter of one or both of the constants, with the default value set to ''%%SPL_AUTOLOAD_CLASS%%''. The name of the first parameter will be changed to ''%%$name%%'' to reflect that it can be a class or function name
 + 
 +In the event that both constants are passed, it will attempt to autoload both types.
  
 <code php> <code php>
-spl_autoload_call('\Some\func', SPL_AUTOLOAD_FUNCTION); // Calls the function autoloader +spl_autoload_call('Some\func', SPL_AUTOLOAD_FUNCTION); // Calls the function autoloader
-spl_autoload_call('\Some\func'); // Calls the class autoloader +
-spl_autoload_call('Some\func', SPL_AUTOLOAD_CLASS); // Calls the class autoloader+
 spl_autoload_call('Some\func'); // Calls the class autoloader spl_autoload_call('Some\func'); // Calls the class autoloader
-spl_autoload_call('func', SPL_AUTOLOAD_FUNCTION | SPL_AUTOLOAD_CLASS); // Error: Cannot autoload multiple types+spl_autoload_call('Some\func', SPL_AUTOLOAD_CLASS); // Calls the class autoloader 
 +spl_autoload_call('func', SPL_AUTOLOAD_FUNCTION | SPL_AUTOLOAD_CLASS); // Calls both autoloaders with the name 'func'
 </code> </code>
- 
-If the user wants to call multiple autoloaders, they can do so manually. 
  
 ==== function_exists ==== ==== function_exists ====
Line 93: Line 77:
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
  
-==== Mismatched arguments ==== +There shouldn’t be any backward incompatible changes.
- +
-If an autoloader was registered that can accept more than one argument, it may fail or perform unexpected behavior when it receives a second argument of ''%%SPL_AUTOLOAD_CLASS%%''.+
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
Line 105: Line 87:
 ==== To Opcache ==== ==== To Opcache ====
  
-To be determined.+  * Potential changes to JIT helpers to call the autoloader instead of reading from the function table directly.
  
 ==== New Constants ==== ==== New Constants ====
Line 113: Line 95:
 ===== Open Issues ===== ===== Open Issues =====
  
-To be determined.+None.
  
 ===== Future Scope ===== ===== Future Scope =====
Line 120: Line 102:
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
 +
 +As per the voting RFC a yes/no vote with a 2/3 majority is needed for this proposal to be accepted.
 +
 +Voting started on 2023-XX-XX and will end on 2023-XX-XX.
 +
 +
  
  
Line 126: Line 114:
    * No    * No
 </doodle> </doodle>
 +
  
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
  
-Not yet.+Review the implementation [[https://github.com/php/php-src/pull/15471|on GitHub #15471]]
  
 ===== Implementation ===== ===== Implementation =====
  
-After the project is implemented, this section should contain the version(s) it was merged into - a link to the git commit(s) - a link to the PHP manual entry for the feature - a link to the language specification section (if any)+  * Implentation: [[https://github.com/php/php-src/pull/15471|PR #15471]] 
 +  * Version: TBD 
 +  * PHP Manual Entry: TODO
  
 ===== References ===== ===== References =====
Line 146: Line 137:
 ===== Rejected Features ===== ===== Rejected Features =====
  
-Keep this updated with features that were discussed on the mail lists.+==== Autoloading constants ==== 
 + 
 +Autoloading of other types such as constants and stream wrappers will come in a later RFC.
  
rfc/function_autoloading4.1723970340.txt.gz · Last modified: 2024/08/18 08:39 by withinboredom