Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:34069 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 14998 invoked by uid 1010); 17 Dec 2007 18:17:46 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 14983 invoked from network); 17 Dec 2007 18:17:46 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 17 Dec 2007 18:17:46 -0000 X-Host-Fingerprint: 74.163.131.214 adsl-163-131-214.mia.bellsouth.net Received: from [74.163.131.214] ([74.163.131.214:26348] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id A0/74-20687-84DB6674 for ; Mon, 17 Dec 2007 13:17:46 -0500 To: internals@lists.php.net,Dmitry Stogov Message-ID: <4766BD3C.3080907@gmail.com> Date: Mon, 17 Dec 2007 13:17:32 -0500 User-Agent: Thunderbird 1.5.0.12 (X11/20070530) MIME-Version: 1.0 References: <97.BF.38526.B657F574@pb1.pair.com> <4A.C3.44650.82DA2674@pb1.pair.com> <47664546.3030107@zend.com> In-Reply-To: <47664546.3030107@zend.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Posted-By: 74.163.131.214 Subject: Re: [PHP-DEV] Re: Idea for namespace lookup resolution From: jrhernandez05@gmail.com (Jessie Hernandez) Dmitry, As I mentioned, I did not find any significant performance penalty with this patch. Also, the patch can be improved by not checking the __get_namespace_classes function if we are not currently inside a namespace. Either way, if we ignore namespace imports, then the best solution would be the following: commit Greg's patch which allows "use ::globalName", don't generate an error when a class is imported with the same name as an internal class, and modify the lookup logic so that internal classes are not even considered when inside a namespace. For example: a.php b.php The lookup rules would be: 1. Are we inside a namespace? No -> look for internal class named Exception. Yes -> look for ns::Exception. 2. If inside a namespace, and ns::Exception does not exist, then try autoloading ns::Exception. 3. If ns::Exception does not exist now, then generate an error. The above would be consistent with how global variables are handled currently. In order to use a global variable inside a function, you first need to "import" it using a "global $name" statement. The same would apply here, in order to use a global/internal class, you either need to reference it using ::name syntax or have a "use ::name" statement at the beginning of the file. Since there aren't many internal classes in the first place, there will be few "use ::internalName" statements per file, so this won't burden the user. I'll try to come up with the patch soon, incorporating Greg's "use ::name" change. Regards, Jessie Hernandez Zend Certified Engineer (http://zend.com/zce.php?c=ZEND006359&r=222727282) Dmitry Stogov wrote: > Hi Jessie, > > The namespace may include several files and it may be extended with > additional files in any moment. So having single > __get_namespace_classes() function will require to update it every time > you extend namespace. > > Also such function will significantly slowdown access to internal > classes. (It was the main reason why __autoload() was moved after check > for internal class). > > Thanks. Dmitry. > > Jessie Hernandez wrote: >> Attached is the proof-of-concept patch. If the idea is met well, then >> I'll keep working on it to add caching and, if there's interest, I'll >> add *namespace imports*. >> >> An example of how a class in a namespace that's named the same as an >> internal class can be loaded: >> >> autoload.php >> > function __autoload($className) >> { >> include_once str_replace( '::', DIRECTORY_SEPARATOR, $className ) >> . '.php'; >> } >> >> function __get_namespace_classes($namespaceName) >> { >> return array( 'Exception' ); >> } >> ?> >> >> test.php >> > namespace ns; >> >> include 'autoload.php'; >> $ex = new Exception(); >> var_dump( $ex ); // prints out ns:Exception instead of Exception >> ?> >> >> >> I ran a few tests on it and did not find any significant performance >> hit. If possible, I'd like someone to try it out and see if they have >> the same result. >> >> As always, comments/suggestions on the patch are welcome. >> >> >> Regards, >> >> Jessie Hernandez >> Zend Certified Engineer >> (http://zend.com/zce.php?c=ZEND006359&r=222727282) >> >> >> Jessie Hernandez wrote: >>> I just thought of something that might be a solution to the lookup >>> rules that we currently have in the namespaces implementation. >>> Whether it's good or not, I just wanted to throw it out there. Here >>> goes: >>> >>> Support a user-defined function named __get_namespace_classes, which >>> will be similar to __autoload. The signature of the function would be >>> the following: >>> >>> >>> array __get_namespace_classes(string $namespaceName); >>> >>> Returns an array of names of classes that are under the specified >>> namespace, or FALSE if the classes under the namespace could not be >>> determined. >>> >>> >>> The above function would be used in the lookup rules as follows >>> (using DateTime as an example): >>> >>> 1) Does the class DateTime exist in the current namespace? >>> 2) If not, and the function __get_namespace_classes exists, call >>> __get_namespace_classes. >>> 3) If the string DateTime is returned in the array from >>> __get_namespace_classes, then autoload that class. >>> 4) If the class is not in the resulting array, or if the result was >>> FALSE, then look for an internal class DateTime. >>> >>> >>> With the above function, you can define classes inside your namespace >>> that are named the same as internal classes without having to >>> explicitly "use" them all over the place. You also solve the problem >>> of namespace imports (sorry, use :-) ): >>> >>> >> use PEAR::Net::*; >>> >>> $a = new FTP(); >>> >>> // The above "use" statement results in calling the >>> // __get_namespace_classes function and "using" each class in the >>> // resulting array internally. Meaning the above will be equivalent to >>> // this: >>> // >>> // use PEAR::Net::Curl; >>> // use PEAR::Net::DNS; >>> // use PEAR::Net::FTP; >>> // ...etc... >>> ?> >>> >>> >>> For the above function to work best, the PHP "dir" function, as an >>> example, should be modified to have an additional "use_include_path" >>> argument: >>> >>> object dir(string $directory [, bool $use_include_path]) >>> >>> >>> By passing TRUE as the second argument, the directory will be >>> searched for in the include path. The user can then do something like >>> the following as an implementation of __get_namespace_classes >>> (assuming the user organized it into class per file, as is common): >>> >>> >> function __get_namespace_classes($namespaceName) >>> { >>> $classes = false; >>> $nsDir = str_replace( '::', DIRECTORY_SEPARATOR, $namespaceName ); >>> $d = dir( $nsDir, true ); >>> >>> if( $d ) >>> { >>> $classes = array(); >>> >>> while( ( $file = $d->read() ) !== false ) >>> $classes[] = str_replace( '.php', '', $file ); >>> >>> $d->close(); >>> } >>> >>> return $classes; >>> } >>> ?> >>> >>> >>> Let me know what you think! >>> >>> >>> >>> Regards, >>> >>> Jessie >>