Re: private, protected, readonly, public

From: Date: Tue, 16 May 2006 21:41:37 +0000
Subject: Re: private, protected, readonly, public
References: 1 2 3 4 5 6 7 8 9  Groups: php.internals 
Request: Send a blank email to internals+get-23476@lists.php.net to get a copy of this message
Hello Zeev, Tuesday, May 16, 2006, 11:08:57 PM, you wrote: >> Anyway it adds complexity to what you >>have to learn about PHP. In fact seeing two visibility keywords separated >>by a colon should be easy enough to understand for everybody. > I'll be blunt as it's late here, but that's just ******** (decided to > censor myself). I for one would never guess what it means (well > actually my guess would be something to do with inheritance). Either > I'm an idiot, or you have a serious problem estimating what's obvious > and what's not... And before you say anything, no, I'm not an idiot :) I would never allow myself to even think that. Maybe you're right and it is just obvious to me as i wrote the patch. >>But noone >>would know which side is the read and which is the write side. The keyword >>'readable' on the otherhand would be absolutly clear even for beginners >>after at least thinking for a second. But oh i said thinking :-) > Again, ******** in my humble opinion. Readable from where? Does it > mean it's otherwise not readable? Does it mean that it's not > writable? From where? How does it relate to inheritance? Na 'readable' means readable whatever i said elsewhere, no? Not logical? > There's no way in hell to understand it without reading up on it, > and even then, it's not very easy to remember. > You've seen today someone saying that PPP is often tricky as it > is. So those 'horror stories' I'm telling are very much a > reality. You're suggesting that doesn't complicate it further? Please. Erm i heared somebody asking for 'friend' during php 5.0 development; And it wasn't me, i swear. >>The patch also allows any combinations in later version should we ever want >>to go that road which i do not see any sense in. E.g. private:public and >>protected:public make sense to me and are often a nice optimization and >>also a nice shortcu in development and easing the pain especially for >>beginners or small hacked to gether stuff. > Look, don't get me wrong, but if you pursue this private:public > thingie, I'll have to hurt you next time I see you :) Just no way. ouch! Well, it's just a stupid patch that comes without a new keyword. Mayke it 'private readable'. Btw, you asked for for a new visibility keyword starting with P: Promulgate, Popularize, Proclaim, Pliable. Those are at least remotely related to what they should express. Actually promulgate is in my humble opinion quite close :-) And since you get what you deserver you'll find the updated patch attached. Before you ask making it a single keyword on its own and giving the member private or protected write visibility is of cause very easy, too. >>However, the reason i write this mail is that you said there could be >>problems. Well this is deply integrated in the handlers and they don't >>let you out. In other words if this stuff is not working then the whole >>PHP 5+ object model is broken. Or in other words, if this is broken alot >>of other stuff regarding object handling is already broken. > You're probably right about this one. You can already return a > reference to a private variable today and change it. Andi - did you > mean something else? Best regards, Marcus before anyone gets that wrong again, i am having fun with the patch.

Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.316.2.8.2.2 diff -u -p -d -r1.316.2.8.2.2 zend_compile.h --- Zend/zend_compile.h 11 May 2006 21:07:39 -0000 1.316.2.8.2.2 +++ Zend/zend_compile.h 16 May 2006 21:38:41 -0000 @@ -139,6 +139,10 @@ typedef struct _zend_try_catch_element { /* deprecation flag */ #define ZEND_ACC_DEPRECATED 0x40000 +/* property handling control */ +#define ZEND_ACC_READ_ONLY 0x080000 +#define ZEND_ACC_PUB_READ 0x100000 + char *zend_visibility_string(zend_uint fn_flags); Index: Zend/zend_language_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_language_parser.y,v retrieving revision 1.160.2.4.2.1 diff -u -p -d -r1.160.2.4.2.1 zend_language_parser.y --- Zend/zend_language_parser.y 11 May 2006 21:07:39 -0000 1.160.2.4.2.1 +++ Zend/zend_language_parser.y 16 May 2006 21:38:41 -0000 @@ -115,7 +115,7 @@ %token T_THROW %token T_USE %token T_GLOBAL -%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC +%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC T_PROMULGATE %token T_VAR %token T_UNSET %token T_ISSET @@ -500,8 +500,9 @@ method_body: ; variable_modifiers: - non_empty_member_modifiers { $$ = $1; } - | T_VAR { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; } + non_empty_member_modifiers { $$ = $1; } + | non_empty_member_modifiers T_PROMULGATE { $$ = $1; Z_LVAL($$.u.constant) |= ZEND_ACC_PUB_READ; } + | T_VAR { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; } ; method_modifiers: Index: Zend/zend_language_scanner.l =================================================================== RCS file: /repository/ZendEngine2/zend_language_scanner.l,v retrieving revision 1.131.2.11 diff -u -p -d -r1.131.2.11 zend_language_scanner.l --- Zend/zend_language_scanner.l 13 Apr 2006 13:48:28 -0000 1.131.2.11 +++ Zend/zend_language_scanner.l 16 May 2006 21:38:42 -0000 @@ -1063,6 +1063,10 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_PUBLIC; } +<ST_IN_SCRIPTING>"promulgate" { + return T_PROMULGATE; +} + <ST_IN_SCRIPTING>"unset" { return T_UNSET; } Index: Zend/zend_object_handlers.c =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.135.2.6.2.2 diff -u -p -d -r1.135.2.6.2.2 zend_object_handlers.c --- Zend/zend_object_handlers.c 10 May 2006 21:12:48 -0000 1.135.2.6.2.2 +++ Zend/zend_object_handlers.c 16 May 2006 21:38:42 -0000 @@ -144,20 +144,26 @@ static zval *zend_std_call_issetter(zval return retval; } -static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) +static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce, int read_write TSRMLS_DC) { + if (!read_write && (property_info->flags & ZEND_ACC_READ_ONLY)) { + return 0; + } switch (property_info->flags & ZEND_ACC_PPP_MASK) { case ZEND_ACC_PUBLIC: return 1; case ZEND_ACC_PROTECTED: - return zend_check_protected(ce, EG(scope)); + if ((property_info->flags & ZEND_ACC_PUB_READ) && read_write) { + return 1; + } else { + return zend_check_protected(ce, EG(scope)); + } case ZEND_ACC_PRIVATE: - if (ce==EG(scope) && EG(scope)) { + if ((ce == EG(scope) && ce) || ((property_info->flags & ZEND_ACC_PUB_READ) && read_write)) { return 1; } else { return 0; } - break; } return 0; } @@ -175,7 +181,7 @@ static inline zend_bool is_derived_class return 0; } -ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) +ZEND_API struct _zend_property_info *zend_get_property_info_ex(zend_class_entry *ce, zval *member, int silent, int read_write TSRMLS_DC) { zend_property_info *property_info = NULL; zend_property_info *scope_property_info; @@ -198,7 +204,7 @@ ZEND_API struct _zend_property_info *zen /* if it's a shadow - go to access it's private */ property_info = NULL; } else { - if (zend_verify_property_access(property_info, ce TSRMLS_CC)) { + if (zend_verify_property_access(property_info, ce, read_write TSRMLS_CC)) { if (property_info->flags & ZEND_ACC_CHANGED && !(property_info->flags & ZEND_ACC_PRIVATE)) { /* We still need to make sure that we're not in a context @@ -244,6 +250,11 @@ ZEND_API struct _zend_property_info *zen } +ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) +{ + return zend_get_property_info_ex(ce, member, silent, 0 TSRMLS_CC); +} + ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name TSRMLS_DC) { zend_property_info *property_info; @@ -252,7 +263,7 @@ ZEND_API int zend_check_property_access( zend_unmangle_property_name(prop_info_name, &class_name, &prop_name); ZVAL_STRING(&member, prop_name, 0); - property_info = zend_get_property_info(zobj->ce, &member, 1 TSRMLS_CC); + property_info = zend_get_property_info_ex(zobj->ce, &member, 1, 0 TSRMLS_CC); if (!property_info) { return FAILURE; } @@ -265,7 +276,7 @@ ZEND_API int zend_check_property_access( return FAILURE; } } - return zend_verify_property_access(property_info, zobj->ce TSRMLS_CC) ? SUCCESS : FAILURE; + return zend_verify_property_access(property_info, zobj->ce, 1 TSRMLS_CC) ? SUCCESS : FAILURE; } static int zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member, zend_guard **pguard) @@ -318,7 +329,7 @@ zval *zend_std_read_property(zval *objec #endif /* make zend_get_property_info silent if we have getter - we may want to use it */ - property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__get != NULL) TSRMLS_CC); + property_info = zend_get_property_info_ex(zobj->ce, member, (zobj->ce->__get != NULL), 1 TSRMLS_CC); if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) { zend_guard *guard; @@ -371,7 +382,7 @@ static void zend_std_write_property(zval member = tmp_member; } - property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__set != NULL) TSRMLS_CC); + property_info = zend_get_property_info_ex(zobj->ce, member, (zobj->ce->__set != NULL), 0 TSRMLS_CC); if (property_info && zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) { if (*variable_ptr == value) { @@ -526,7 +537,7 @@ static zval **zend_std_get_property_ptr_ fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); #endif - property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__get != NULL) TSRMLS_CC); + property_info = zend_get_property_info_ex(zobj->ce, member, (zobj->ce->__get != NULL), 0 TSRMLS_CC); if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) { zval *new_zval; @@ -570,7 +581,7 @@ static void zend_std_unset_property(zval member = tmp_member; } - property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__unset != NULL) TSRMLS_CC); + property_info = zend_get_property_info_ex(zobj->ce, member, (zobj->ce->__unset != NULL), 0 TSRMLS_CC); if (!property_info || zend_hash_del(zobj->properties, property_info->name, property_info->name_length+1) == FAILURE) { zend_guard *guard; @@ -849,7 +860,7 @@ ZEND_API zval **zend_std_get_static_prop zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags)); #endif - if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) { + if (!zend_verify_property_access(property_info, ce, 1 TSRMLS_CC)) { if (!silent) { zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name); } @@ -945,7 +956,7 @@ static int zend_std_has_property(zval *o fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); #endif - property_info = zend_get_property_info(zobj->ce, member, 1 TSRMLS_CC); + property_info = zend_get_property_info_ex(zobj->ce, member, 1, 0 TSRMLS_CC); if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) { zend_guard *guard; Index: Zend/zend_object_handlers.h =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.h,v retrieving revision 1.47.2.2.2.1 diff -u -p -d -r1.47.2.2.2.1 zend_object_handlers.h --- Zend/zend_object_handlers.h 9 May 2006 23:53:23 -0000 1.47.2.2.2.1 +++ Zend/zend_object_handlers.h 16 May 2006 21:38:42 -0000 @@ -140,6 +140,7 @@ BEGIN_EXTERN_C() ZEND_API union _zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC); ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent TSRMLS_DC); ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC); +ZEND_API struct _zend_property_info *zend_get_property_info_ex(zend_class_entry *ce, zval *member, int silent, int read_write TSRMLS_DC); ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC); ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC);
« previous php.internals (#23476) next »