This is an implementation of Stas idea. 1) Look for existent class in current namespace 2) Look for existent internal class 3) Try to autoload class from current namespace
Thanks. Dmitry. > -----Original Message----- > From: Stanislav Malyshev [mailto:[EMAIL PROTECTED] > Sent: Monday, August 27, 2007 9:49 PM > To: Dmitry Stogov > Cc: 'PHP Internals List' > Subject: Re: [PHP-DEV] Namespaces and __autoload() > > > > <?php > > namespace Foo; > > throw new Exception; > > > > In this case PHP first looks for Foo::Exception and only then for > > internal Exception, but the first lookup may call __autoload (or > > corresponding SPL > > functions) and it can emit error or throw exception. > > > > The patch provides an additional boolean argument to > __autoload() that > > say if class is really required. In case if it false, user code > > shouldn't emit errors or throw exceptions. > > There's two problems here: > 1. On each access to internal class, like Exception, SPL classes, > DateTime, reflection classes, etc. - we'd have call to autoload and > subsequent disk access, maybe more than one if we have include path. > Performance of it would be awful. > 2. All libraries having autoloaders would have to rewrite them to > support the new mode. > > I would propose different solution. When we have unresolved > unqualified > name, we do the following: > 1. Check if we already know such class in namespace at > compile-time. If > so, it's resolved. > 2. If not, will be resolved at run-time. > 3. At run-time, check if we know such class in namespace now. If yes, > it's resolved. > 4. If not, check if we know internal class with such name. If > yes, it's > resolved to internal class. > 5. If not, try to autoload this class. If autoloading fails, it's the > undefined class error. > > This rule is a bit more complex, but allows to resolve common cases > without extra filesystem accesses and allows to keep > autoloader without > modification. > > Comments? > -- > Stanislav Malyshev, Zend Software Architect > [EMAIL PROTECTED] http://www.zend.com/ > (408)253-8829 MSN: [EMAIL PROTECTED] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
Index: Zend/zend_constants.c =================================================================== RCS file: /repository/ZendEngine2/zend_constants.c,v retrieving revision 1.99 diff -u -p -d -r1.99 zend_constants.c --- Zend/zend_constants.c 25 Aug 2007 23:28:10 -0000 1.99 +++ Zend/zend_constants.c 27 Aug 2007 17:59:12 -0000 @@ -333,7 +333,7 @@ ZEND_API int zend_u_get_constant_ex(zend if ((UG(unicode) && (colon.u = u_memrchr(name.u, ':', name_len)) && colon.u > name.u && *(colon.u-1) == ':') || (!UG(unicode) && (colon.s = zend_memrchr(name.s, ':', name_len))&& colon.s > name.s && *(colon.s-1) == ':')) { /* compound constant name */ - zend_class_entry **ce = NULL; + zend_class_entry *ce = NULL; int class_name_len = UG(unicode)?colon.u-name.u-1:colon.s-name.s-1; int const_name_len = name_len - class_name_len - 2; zstr constant_name, class_name; @@ -366,7 +366,7 @@ ZEND_API int zend_u_get_constant_ex(zend if (lcname_len == sizeof("self")-1 && ZEND_U_EQUAL(type, lcname, lcname_len, "self", sizeof("self")-1)) { if (scope) { - ce = &scope; + ce = scope; } else { zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); retval = 0; @@ -379,7 +379,7 @@ ZEND_API int zend_u_get_constant_ex(zend } else if (!scope->parent) { zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); } else { - ce = &scope->parent; + ce = scope->parent; } efree(lcname.v); } else { @@ -427,31 +427,11 @@ ZEND_API int zend_u_get_constant_ex(zend efree(lcname.v); /* Check for class */ - if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS && - (flags & ZEND_FETCH_CLASS_RT_NS_CHECK) != 0) { - retval = 0; - if ((UG(unicode) && (colon.u = u_memrchr(class_name.u, ':', class_name_len)) && colon.u > class_name.u && *(colon.u-1) == ':') || - (!UG(unicode) && (colon.s = zend_memrchr(class_name.s, ':', class_name_len))&& colon.s > class_name.s && *(colon.s-1) == ':')) { - - if (UG(unicode)) { - colon.u++; - lcname_len = class_name_len - (colon.u - class_name.u); - } else { - colon.s++; - lcname_len = class_name_len - (colon.s - class_name.s); - } - lcname = zend_u_str_case_fold(type, colon, lcname_len, 0, &lcname_len); - if (zend_u_hash_find(CG(class_table), type, lcname, lcname_len+1, (void**)&ce) == SUCCESS && - (*ce)->type == ZEND_INTERNAL_CLASS) { - retval = 1; - } - efree(lcname.v); - } - } + ce = zend_u_fetch_class(type, class_name, class_name_len, flags TSRMLS_CC); } if (retval && ce) { - if (zend_u_hash_find(&((*ce)->constants_table), type, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) { + if (zend_u_hash_find(&ce->constants_table, type, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) { retval = 0; } } else { @@ -470,7 +450,7 @@ ZEND_API int zend_u_get_constant_ex(zend efree(class_name.v); if (retval) { - zval_update_constant_ex(ret_constant, (void*)1, *ce TSRMLS_CC); + zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC); *result = **ret_constant; zval_copy_ctor(result); } Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.413 diff -u -p -d -r1.413 zend_execute_API.c --- Zend/zend_execute_API.c 24 Aug 2007 13:50:52 -0000 1.413 +++ Zend/zend_execute_API.c 27 Aug 2007 17:59:13 -0000 @@ -485,7 +485,6 @@ ZEND_API int zval_update_constant_ex(zva zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg; zval const_value; zstr colon; - int len; if (IS_CONSTANT_VISITED(p)) { zend_error(E_ERROR, "Cannot declare self-referencing constant '%v'", Z_UNIVAL_P(p)); @@ -1696,7 +1695,7 @@ check_fetch_type: break; } - if (zend_u_lookup_class_ex(type, lcname, class_name_len, use_autoload, do_normalize, &pce TSRMLS_CC)==FAILURE) { + if (zend_u_lookup_class_ex(type, lcname, class_name_len, rt_ns_check ? 0 : use_autoload, do_normalize, &pce TSRMLS_CC)==FAILURE) { if (rt_ns_check) { /* Check if we have internal class with the same name */ zstr php_name; @@ -1728,6 +1727,13 @@ check_fetch_type: } } if (use_autoload) { + if (rt_ns_check && + zend_u_lookup_class_ex(type, lcname, class_name_len, use_autoload, do_normalize, &pce TSRMLS_CC)==SUCCESS) { + if (lcname.v != class_name.v) { + efree(lcname.v); + } + return *pce; + } if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { zend_error(E_ERROR, "Interface '%R' not found", type, class_name); } else {
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php