Namespace methods

php.internals

Kevin Newman

20 years ago
Hello, I have been trying to compile PHP with the namespaces patch, but have been completely unable to find the time after an initial attempt failed (I'm compiling on windows). So I just wanted to know what methods this patch provides, if it does at all. Does it support import for example? If so, is there any documentation on the methods the patch provides? Thanks, Kevin N.

Jessie Hernandez

20 years ago
Kevin, Just to make sure, you can get the latest patch from http://www.zend.com/zend/week/pat/pat44.txt. For documentation, please refer to this post: http://news.php.net/php.internals/17484. Let me know if you have any questions or if you still cannot get the patch to compile (I wrote the patch against a 5.1 CVS version some months ago, maybe it doesn't apply cleanly anymore, haven't tried). Regards, Jessie Hernandez Kevin Newman wrote:

Kevin Newman

20 years ago
Thank you for the info. I have some questions/suggestions (they may be silly - please feel welcome to tell me so, if they are): You have solved the problem (grievance number 5) of file based scoping, by introducing a function that can only be used within __autoload (the autoload_import_class function). Is that function meant to be called from within the class file? If so, I'd like to offer an alternative, that would allow usage even outside of the __autoload function. Namespaces are generally implemented in file based languages (like c, c++, c# etc.), so there isn't an issue with clearing out imported namespaces when a file ends - but since (let me know if this is an incorrect assumption) PHP is an inline based interpreter - it would make sense to have a way to remove namespaces after they have been imported. So the first suggestion is to add an unimport (export?) function that would do just that - remove imported classes (or functions/vars, etc.) from the current (or global?) scope. This functionality combined with the get_imported_namespaces function would allow users to emulate file based namespaces from within the __autoload function, while allowing them to use the standard import statement from within class files. Here is a crude sudo code (that incorrectly assumes import and unimport take a string as an argument) example of an __autoload function that does that: function __autoload($classname) { // class name figuring out code goes here ... // store current namespaces $current_namespaces = get_imported_namespaces(); // remove all current namespaces foreach ($current_namespaces as $namespace_name) { unimport($namespace_name); } // include the class file require_once(...$classname); // remove all namespaces imported from the class file $new_namespaces = get_imported_namespaces(); foreach ($new_namespaces) { unimport($namespace_name); } // reimport the $current_namespaces from the array foreach ($current_namespaces as $namespace_name) { import($namespace_name); } } The addition of two new functions - clear_all_namespaces() and import_namespaces() (or reimport_namespaces, restore_namespaces, etc.) could help clean that up a bit. The example would then look like this: function __autoload($classname) { // class name figuring out code goes here ... // store current namespaces $current_namespaces = get_imported_namespaces(); // remove all current namespaces clear_all_namespaces(); // include the class file require_once(...$classname); // remove all namespaces imported from the class file clear_all_namespaces(); // reimport $current_namespaces from the array restore_namespaces($current_namespaces); } You can see from the example, how this would work inline, just as well as within the __autoload function. Am I completely nuts here? What do you think? Kevin N. PS You could even wrap all those Namespace manipulation methods into a class (initial attempt): <?php interface Namespaces { /** * Alternative to the import statement. * @param $ns_name - a string containing the name of the namespace to import */ public static import($ns_name); /** * Removes an imported namespace. * $param $ns_name - a string containing the name of the namespace to unimport */ public static unimport($ns_name); /** * Clears all imported namespaces. */ public static unimport_all(); /** * Clears a collection of namespaces. * $param $ns_names - an array containing the names of the namespaces to clear */ public static unimport_multiple($ns_names); /** * Imports a collection of namespaces (can be used to restore a previously cleared collection). * $param $ns_names - an array containing the names of the namespaces to clear */ public static import_multiple($ns_names); /** * Get a list of current imported namespaces * @return array of currently imported namespaces */ public static get_imported(); } ?> Jessie Hernandez wrote:

Jessie Hernandez

20 years ago
Hi Kevin, Kevin Newman wrote:
> Thank you for the info. > > I have some questions/suggestions (they may be silly - please feel > welcome to tell me so, if they are): > > You have solved the problem (grievance number 5) of file based scoping, > by introducing a function that can only be used within __autoload (the > autoload_import_class function). Is that function meant to be called > from within the class file? If so, I'd like to offer an alternative, > that would allow usage even outside of the __autoload function. >
The autoload_import_class function has nothing to do with solving the file-based scoping problem. The way this was done internally was to have a HashTable with the file names as key, and the values are each a HashTable containing the import information. The autoload_import_class function was created in order for full namespace imports to be resolved from the __autoload function, regardless of which file the __autoload function is in. For example, if we had two files, test.php and autoload.php, and from test.php you have a statement "import namespace my_ns" and you reference a class "my_class", then as soon as you try to reference my_class, the __autoload function will be called (which is in autoload.php). There needs to be a mechanism in which a namespace import can be resolved from another file. The autoload_import_class does just that. You pass it the class name and namespace name, and inside this function, it adds this information to the import HashTable of the file that triggered the __autoload call (in this case, test.php). After exiting __autoload, the class is resolved and can be used by test.php.
> Namespaces are generally implemented in file based languages (like c, > c++, c# etc.), so there isn't an issue with clearing out imported > namespaces when a file ends - but since (let me know if this is an > incorrect assumption) PHP is an inline based interpreter - it would make > sense to have a way to remove namespaces after they have been imported. > So the first suggestion is to add an unimport (export?) function that > would do just that - remove imported classes (or functions/vars, etc.) > from the current (or global?) scope. >
This is unnecessary, as there is a separate import HashTable for each file, like I explained above. I believe that what you were trying to accomplish with your pseudocode was what is already being done internally, so I don't think it's relevant after having explained the above (correct me if I'm wrong). Regards, Jessie