-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Working with custom method attributes and gen_stub.php
#2254
-
Hi @remicollet, I've got (hopefully) a quick question for you.
I was playing around with adding PHP 8.0 attributes to the Redis class in this commit. It looks like gen_stub.php does have support for creating the attribute classes themselves, but not for attaching them to Redis methods.
I looked through the PHP source code and found the attribute API (zend_add_attribute, zend_add_function_attribute, etc.) but wasn't able to find an example where a method attribute was being attached to an internal class.
Do you know whether or not this is currently possible, and if so do you know of any internal PHP classes where this is being done that I could take a look at?
NOTE: The reason I'm doing require "Zend/zend_attributes.stub.php"; is because it's the only way I could get gen_stub.php to not bomb out on the stub file. It's probably wrong 😄
Beta Was this translation helpful? Give feedback.
All reactions
Answering my own question, in case this ever ends up in someone's searches
You can add arbitrary attributes to an extension class' methods like so:
extern zend_class_entry *redis_ce; static void redis_add_method_attribute(zend_class_entry *ce, const char *fn, size_t fnlen, zend_string *attr) { zval *zfn; zfn = zend_hash_str_find(&ce->function_table, fn, fnlen); ZEND_ASSERT(zfn != NULL); zend_add_function_attribute(Z_FUNC_P(zfn), attr, 0); } static void register_redis_attributes(void) { zend_string *attribute_name_Local = zend_string_init_interned("Local", sizeof("Local") - 1, 1); zend_string *attribute_name_RedisCommand = zend_string_init_interned("RedisCommand",
Replies: 1 comment
-
Answering my own question, in case this ever ends up in someone's searches
You can add arbitrary attributes to an extension class' methods like so:
extern zend_class_entry *redis_ce; static void redis_add_method_attribute(zend_class_entry *ce, const char *fn, size_t fnlen, zend_string *attr) { zval *zfn; zfn = zend_hash_str_find(&ce->function_table, fn, fnlen); ZEND_ASSERT(zfn != NULL); zend_add_function_attribute(Z_FUNC_P(zfn), attr, 0); } static void register_redis_attributes(void) { zend_string *attribute_name_Local = zend_string_init_interned("Local", sizeof("Local") - 1, 1); zend_string *attribute_name_RedisCommand = zend_string_init_interned("RedisCommand", sizeof("RedisCommand") - 1, 1); redis_add_method_attribute(redis_ce, "getlasterror", sizeof("getlasterror") - 1, attribute_name_Local); redis_add_method_attribute(redis_ce, "clearlasterror", sizeof("clearlasterror") - 1, attribute_name_Local); redis_add_method_attribute(redis_ce, "get", sizeof("get") - 1, attribute_name_RedisCommand); redis_add_method_attribute(redis_ce, "set", sizeof("set") - 1, attribute_name_RedisCommand); }
These are "ad-hoc" attributes (ones that aren't derived from abstract base classes), but do work with ReflectionClass.
<?php $reflection = new ReflectionClass(Redis::class); $get = $reflection->getMethod('get'); foreach ($get->getAttributes() as $attribute) { echo "GET attribute: $attribute"; }
GET attribute: Attribute [ RedisCommand ]
Beta Was this translation helpful? Give feedback.
All reactions
-
🚀 1