[PHP-DEV] Making ArrayAccess objects more array-like?
Hi all. (Again, I've searched the archives, but haven't found anything on this one) The ArrayAccess interface allows one to essentially overload the index operator [] [1], which is nice, as it makes it possible to implement things like type-checked associative arrays, variants, tuples, etc. However, you can't use it with any of the built-in array functions (such as count(), or the array_*-functions), which means you have to either: 1. Have something like an as_array() member function, returning a reference to the embedded array, and call this every time you need to call one of these functions, or: 2. Implement the functions as member functions on the object. Both of these solutions are rather inelegant, and in particular, 2. leads to unnecessary code bloat, and both gives a different calling convention compared to ordinary arrays, which can surely confuse readers of the code. My question is: Has it been considered changing the standard library functions that take an array as a parameter, to be able to take an object implementing ArrayAccess/IteratorAggregate, also? Would it perhaps be a very large change? That would be understandable, given that it could mean the library having to be able to call into user code (the object being passed). However, this is done elsewhere, too, such as foreach(). I know the inability to return a reference is well known. However, has there come to a consensus about how to solve it (or if)? It tends to trip up code using these arrays a lot... Sometimes, you get no change in the array, as it turns out it operated on a copy of an element, rather than the built-in array. Regards, Terje [1] Since ArrayAccess essentially means overloading the index operator, I'm wondering how this have gone through, since some members of the development team (Andi?) appears to have very strong feelings against operator overloading...? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Making ArrayAccess objects more array-like?
Hello Terje, long ago we decided against supporting it in the array functions. best regards marcus Wednesday, September 13, 2006, 8:39:57 AM, you wrote: Hi all. (Again, I've searched the archives, but haven't found anything on this one) The ArrayAccess interface allows one to essentially overload the index operator [] [1], which is nice, as it makes it possible to implement things like type-checked associative arrays, variants, tuples, etc. However, you can't use it with any of the built-in array functions (such as count(), or the array_*-functions), which means you have to either: 1. Have something like an as_array() member function, returning a reference to the embedded array, and call this every time you need to call one of these functions, or: 2. Implement the functions as member functions on the object. Both of these solutions are rather inelegant, and in particular, 2. leads to unnecessary code bloat, and both gives a different calling convention compared to ordinary arrays, which can surely confuse readers of the code. My question is: Has it been considered changing the standard library functions that take an array as a parameter, to be able to take an object implementing ArrayAccess/IteratorAggregate, also? Would it perhaps be a very large change? That would be understandable, given that it could mean the library having to be able to call into user code (the object being passed). However, this is done elsewhere, too, such as foreach(). I know the inability to return a reference is well known. However, has there come to a consensus about how to solve it (or if)? It tends to trip up code using these arrays a lot... Sometimes, you get no change in the array, as it turns out it operated on a copy of an element, rather than the built-in array. Regards, Terje [1] Since ArrayAccess essentially means overloading the index operator, I'm wondering how this have gone through, since some members of the development team (Andi?) appears to have very strong feelings against operator overloading...? Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] Const member functions
(This may be considered too radical for some, but I ask, anyway... Also, if there's a more appropropriate place to ask such questions, let me know, but as this is the developer's list, it seemed like the right place) In C++, it's possible to declare member functions const meaning they don't change the object they operate on. This can help reason about programs, because if you have something like (PHP syntax): function some_member() { ... $a = $this-f(); $b = $this-g(); $c = $this-h(); ... } and f(), g() and h() are all declared const, you know the object is still in the same state as before the functions were called. I was recently bit by this, when I changed the state in a member function, and later called that member function, thinking it _didn't_ change the state, and wasted some time debugging that. Had it been possible to declare your assumption (this function doesn't change the object), I'd got an error where it did change the object, clearly showing the erroneous assumption. Thoughts? As I'm pretty ignorant about the internals of PHP, I don't know if this is practical to implement, or whether it might fit with the language. It's possible to _simulate_ this effekt to some degree, but at the cost of both syntactic noise and performance: In short, it's a hack. It involves creating an object at the start of the function definition, taking a reference to $this, and comparing the new state with a copy of it, in the destructor (i.e. at the end of the function). However, it's a rather inelegant solution, with a potentially large performance impact. Regards, Terje -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Return type hints
On 12/09/06, Terje Slettebø [EMAIL PROTECTED] wrote: function f(Something $value) /** @return SomethingElse */ { // ... } One of the good things about PHP is the loose typing (1.00 == 1 == 1 sort of thing as I understand it). This has been useful. But one of the first things we are told about using PHP ITRW is to always validate user input and to make sure you only accept what you know to be valid data. More often than not, this ends up casting the data to a specific type (number of payments - int, date of birth - date, email address - string (or user type of email), delete - Boolean). You may even have functions which require/expect a parameter to be of a specific type. We can already use type hinting for arrays and classes for parameters. Type hinting could be extended to all types for user functions. Even the possibility of accepting multiple types for a single parameter could be used to support a mixed type. Recently we had a discussion about parameter overloading on methods. You can probably use __magic to produce the effect of parameter overloading. Whilst casting the return type is easy to do, having the return type as part of the function declaration would be very useful for auto-documentors. As for syntax, I would go with ... type function f(type $value) It would be useful to also have VOID as a return type, but that may be open for discussion. But mixed type returns (normal type -string/int/real/Boolean - for valid results AND Boolean False for failure) would need to be considered. -- - Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498amp;r=213474731 Standing on the shoulders of some very clever giants!
[PHP-DEV] PHP5 extensions: using existing functionnames as method names
Hi, i just was wondering how existing function names could be used as method names in OO-Extensions for PHP5. I've looked through the SPL-source where this is done with functions like current() and next() in the iterators, but I couldn't find a hint how to do this. Can someone give me a little hint what is needed to do that. Many thanks in advance, Daniel -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] PHP5 extensions: using existing functionnames as method names
On Wed, Sep 13, 2006 at 10:09:08AM +0200, [EMAIL PROTECTED] wrote: Hi, i just was wondering how existing function names could be used as method names in OO-Extensions for PHP5. I've looked through the SPL-source where this is done with functions like current() and next() in the iterators, but I couldn't find a hint how to do this. Can someone give me a little hint what is needed to do that. you can use any function name as method name without a clash. you just cannot use language constructs that aren't real functions like empty, echo or require as method names. this question better belongs to php-general, btw. Many thanks in advance, Daniel -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] PHP5 extensions: using existing function names as method names
...Just forgot to CC... you can use any function name as method name without a clash. you just cannot use language constructs that aren't real functions like empty, echo or require as method names. this question better belongs to php-general, btw. Sorry if I didn't made myself clear enough. I'm talking about C-extensions. I've tried to implement the PHP_METHOD(class, xyz). It compiles fine, but in runtime PHP Warning: cannot redeclare xyz... will appaer. Daniel -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Return type hints
From: Richard Quadling [EMAIL PROTECTED] On 12/09/06, Terje Slettebø [EMAIL PROTECTED] wrote: function f(Something $value) /** @return SomethingElse */ { // ... } One of the good things about PHP is the loose typing (1.00 == 1 == 1 sort of thing as I understand it). This has been useful. I'd say that's debatable. :) Yes, it can make it more convenient to handle data coming from outside the script (such as forms), but it can also hide bugs. While it can be argued that conversions between, say, arithmetic types (int and floats) may be useful, allowing conversion from something like NULL to empty string, integer 0, etc. (as PHP does) may be going a little over board, as an uninitialised variable (such as a member variable) may not be easily discovered. It's interesting to note that Java (a newer language than C++) actually has a stronger type system (at least in some respects) than C++: While C/C++ allows things like implicit conversion between int/float/pointer and bool (a legacy from C), Java does not, and if you think about it, it makes sense to disallow that, as boolean values are conceptually different from these. But one of the first things we are told about using PHP ITRW is to always validate user input and to make sure you only accept what you know to be valid data. True, and at least with regard to function calls, with type hinting (as you mention below), that testing is done for you, so you don't have to, leading to less code and syntactic noise (and possibly better performance). We can already use type hinting for arrays and classes for parameters. Type hinting could be extended to all types for user functions. I asked about this about 1 1/2 year ago (as well as the possibility of function overloading - which _would_ be at least theoretically possible, now that we have type hints), on this list, but got a very negative response to that... So... I figured the PHP community wasn't ready for that, or didn't think it fit the language. I still think type hints for fundamental types could be a good idea, for catching errors early, such as passing NULL to a function expecting string (as long as it avoids the usual implicit conversion). Anyway, with Sara Golemon's operator overloading extension, it's possible to make your own Integer, Float, String, etc. types, and use them basically as built-in types, making it possible to use them for type hints. Even the possibility of accepting multiple types for a single parameter could be used to support a mixed type. One way to do that could be to create a user-defined variant type (or mixed type, as you say), that may contain a specified number of types. Yes, I know that in PHP, basically all variables are variants, but with a class, you may restrict it to just a few specific ones. Likewise, it's possible to create type-checked tuple types (a sequence of values, of specified types), and ditto arrays. As it's mentioned in the user-contributed notes on autoloading, you may even abuse the autoloader to implement parametric types (like templates in C++). For example, if you write: function f(Array_string $value) { } The autoloader may synthesise the Array_string type, from a generic typed array class, to produce a custom array type that enforces numerical indexes and string values (the above is really short for Array_int_string, where int gives the key type, and string gives the value type). Again, this may be useful for expressing intentions in code, as well as runtime-enforced conditions. Recently we had a discussion about parameter overloading on methods. You can probably use __magic to produce the effect of parameter overloading. I'm not sure what you mean by parameter overloading. Do you mean function overloading? Yes, you can simulate that, using e.g. a dispatch based on func_get_args(), but it's rather inelegant, compared to real overloading. Also, it's impossible to overload existing functions in the standard library (if it was, you could provide your own count(), array_*-functions, etc. for user-defined array types. Whilst casting the return type is easy to do, having the return type as part of the function declaration would be very useful for auto-documentors. Not only that, but in my opinion the more important thing that you may enforce a return type (forgetting to return a proper value from a function could be caught this way). As for syntax, I would go with ... type function f(type $value) Yes, that's _one_ possibility. Let's see it in all its glory (i.e. with a lot of other qualifiers): public abstract SomeClass function f(SomeOther $value) Hm, maybe. Another alternative might be (closer to C/C++/Java syntax): qualifiers function return type function name(parameters) E.g.: public abstract function Someclass f(SomeOther $value) It would be useful to also have VOID as a return type, but that may be open for discussion. Yes, or perhaps more natural for PHP, null. But mixed type returns (normal
Re: [PHP-DEV] Return type hints
On 13/09/06, Terje Slettebø [EMAIL PROTECTED] wrote: From: Richard Quadling [EMAIL PROTECTED] On 12/09/06, Terje Slettebø [EMAIL PROTECTED] wrote: function f(Something $value) /** @return SomethingElse */ { // ... } But one of the first things we are told about using PHP ITRW is to always validate user input and to make sure you only accept what you know to be valid data. True, and at least with regard to function calls, with type hinting (as you mention below), that testing is done for you, so you don't have to, leading to less code and syntactic noise (and possibly better performance). The issue then becomes what would happen to a value of the wrong type? You either have the option of using PHP's own internal casting mechanism, so f(int $i_int_expected) would internally cast the supplied parameter as an int or you have to produce a WARNING with a parameter of the wrong type message. But then what is passed to the function? This would have to be determined somehow. -- - Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498amp;r=213474731 Standing on the shoulders of some very clever giants!
[PHP-DEV] Re: Tweaking expects parameter # to be... message
Either way is fine with me, as long as I get the class name in the warning -Hannes On 9/11/06, Marcus Boerger [EMAIL PROTECTED] wrote: Hello Andrei, for some reason i like instance of class better than class object. The reason is that we have instances rather than objects - So it's a purist thing. best regards marcus Monday, September 11, 2006, 6:44:08 PM, you wrote: How is instance of different from object? -Andrei On Sep 10, 2006, at 11:44 PM, Marcus Boerger wrote: Hello Hannes, with your changewe'd have: Warning: token_get_all() expects parameter 1 to be binary string, stdClass object given in %s on line %d i would like the followingmore: Warning: token_get_all() expects parameter 1 to be binary string, instance ofstdClass given in %s on line %d best regards marcus Monday, September 11, 2006, 12:46:56 AM, you wrote: Index: ext/libxml/tests/001.phpt === RCS file: /repository/php-src/ext/libxml/tests/001.phpt,v retrieving revision 1.2 diff -u -r1.2 001.phpt --- ext/libxml/tests/001.phpt 27 Jun 2006 22:54:29 - 1.2 +++ ext/libxml/tests/001.phpt 10 Sep 2006 22:44:45 - @@ -22,7 +22,7 @@ bool(false) bool(true) -Warning: libxml_use_internal_errors() expects parameter 1 to be boolean, object given in %s001.php on line 6 +Warning: libxml_use_internal_errors() expects parameter 1 to be boolean, stdClass object given in %s001.php on line 6 NULL array(0) { } Index: ext/openssl/tests/bug38255.phpt === RCS file: /repository/php-src/ext/openssl/tests/bug38255.phpt,v retrieving revision 1.2 diff -u -r1.2 bug38255.phpt --- ext/openssl/tests/bug38255.phpt 29 Jul 2006 22:41:34 - 1.2 +++ ext/openssl/tests/bug38255.phpt 10 Sep 2006 22:44:45 - @@ -38,10 +38,10 @@ Warning: openssl_verify(): supplied key param cannot be coerced into a public key in %s on line %d bool(false) -Warning: openssl_verify() expects parameter 2 to be string, object given in %s on line %d +Warning: openssl_verify() expects parameter 2 to be string, stdClass object given in %s on line %d NULL -Warning: openssl_verify() expects parameter 2 to be string, object given in %s on line %d +Warning: openssl_verify() expects parameter 2 to be string, stdClass object given in %s on line %d NULL Warning: openssl_verify() expects parameter 2 to be string, array given in %s on line %d @@ -50,6 +50,31 @@ Warning: openssl_verify() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: openssl_verify() expects parameter 1 to be string, object given in %s on line %d +Warning: openssl_verify() expects parameter 1 to be string, stdClass object given in %s on line %d NULL Done +--UEXPECTF-- +Warning: openssl_verify(): supplied key param cannot be coerced into a public key in %s on line %d + +Warning: openssl_verify(): supplied key param cannot be coerced into a public key in %s on line %d +bool(false) + +Warning: openssl_verify(): supplied key param cannot be coerced into a public key in %s on line %d +bool(false) + +Warning: openssl_verify() expects parameter 2 to be binary string, stdClass object given in %s on line %d +NULL + +Warning: openssl_verify() expects parameter 2 to be binary string, stdClass object given in %s on line %d +NULL + +Warning: openssl_verify() expects parameter 2 to be binary string, array given in %s on line %d +NULL + +Warning: openssl_verify() expects at least 3 parameters, 0 given in %s on line %d +NULL + +Warning: openssl_verify() expects parameter 1 to be binary string, stdClass object given in %s on line %d +NULL +Done + Index: ext/spl/tests/iterator_044.phpt === RCS file: /repository/php-src/ext/spl/tests/iterator_044.phpt,v retrieving revision 1.1 diff -u -r1.1 iterator_044.phpt --- ext/spl/tests/iterator_044.phpt 21 May 2006 17:27:12 - 1.1 +++ ext/spl/tests/iterator_044.phpt 10 Sep 2006 22:44:45 - @@ -89,10 +89,10 @@ object(stdClass)#%d (0) { } -Warning: CachingIterator::offsetExists() expects parameter 1 to be string (Unicode or binary), object given in %siterator_044.php on line %d +Warning: CachingIterator::offsetExists() expects parameter 1 to be string (Unicode or binary), stdClass object given in %siterator_044.php on line %d NULL -Warning: CachingIterator::offsetGet() expects parameter 1 to be string (Unicode or binary), object given in %siterator_044.php on line %d +Warning: CachingIterator::offsetGet() expects parameter 1 to be string (Unicode or binary), stdClass object given in %siterator_044.php on line %d NULL ===2=== object(MyFoo)#%d (0) { @@ -134,10 +134,10 @@ object(stdClass)#1 (0) { } -Warning: CachingIterator::offsetExists() expects parameter 1 to be string (Unicode or binary),
Re: [PHP-DEV] Return type hints
Richard Quadling [EMAIL PROTECTED] schreef in bericht news:[EMAIL PROTECTED] On 13/09/06, Terje Slettebø [EMAIL PROTECTED] wrote: .. The issue then becomes what would happen to a value of the wrong type? You either have the option of using PHP's own internal casting mechanism, so f(int $i_int_expected) would internally cast the supplied parameter as an int or you have to produce a WARNING with a parameter of the wrong type message. But then what is passed to the function? This would have to be determined somehow. I think it would make sense to turn the value into NULL when the casting fails. And honestly, I would love this kind of type hinting. It has to be smart in the sense that if I say double, and it's a string containing 0.123, it will either be casted to a double (which may be unfortunate, since floats and doubles are inaccurate), or simply let through as a string, because it follows double formatting (that being /-?[0-9]+(\.[0-9]+)?/). But this way type hinting for core types is only optional for people and it's not as strict as in the vast majority of other languages out there. This kind of smart type hinting would be simply perfect. Ron -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] PHP5 extensions: using existing functionnames as method names
On Wed, 13 Sep 2006 11:35:16 +0200 [EMAIL PROTECTED] wrote: ...Just forgot to CC... you can use any function name as method name without a clash. you just cannot use language constructs that aren't real functions like empty, echo or require as method names. this question better belongs to php-general, btw. Sorry if I didn't made myself clear enough. I'm talking about C-extensions. I've tried to implement the PHP_METHOD(class, xyz). It compiles fine, but in runtime PHP Warning: cannot redeclare xyz... will appaer. It is possible to name a method like an existing function, I'm not sure what you are doing exactly but it works here. When your class is called zip and you have a function called zip_open, it will conflict with the function name when you build against php 5.2.0. It is fixed in 5.2 and a work around exists, see ext/zip for an example. -- Pierre -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Making ArrayAccess objects more array-like?
Hi Marcus. long ago we decided against supporting it in the array functions. Ok, thanks. Could I ask what the reasons were (Alternatively get a pointer to the discussion)? Regards, Terje best regards marcus Wednesday, September 13, 2006, 8:39:57 AM, you wrote: Hi all. (Again, I've searched the archives, but haven't found anything on this one) The ArrayAccess interface allows one to essentially overload the index operator [] [1], which is nice, as it makes it possible to implement things like type-checked associative arrays, variants, tuples, etc. However, you can't use it with any of the built-in array functions (such as count(), or the array_*-functions), which means you have to either: 1. Have something like an as_array() member function, returning a reference to the embedded array, and call this every time you need to call one of these functions, or: 2. Implement the functions as member functions on the object. Both of these solutions are rather inelegant, and in particular, 2. leads to unnecessary code bloat, and both gives a different calling convention compared to ordinary arrays, which can surely confuse readers of the code. My question is: Has it been considered changing the standard library functions that take an array as a parameter, to be able to take an object implementing ArrayAccess/IteratorAggregate, also? Would it perhaps be a very large change? That would be understandable, given that it could mean the library having to be able to call into user code (the object being passed). However, this is done elsewhere, too, such as foreach(). I know the inability to return a reference is well known. However, has there come to a consensus about how to solve it (or if)? It tends to trip up code using these arrays a lot... Sometimes, you get no change in the array, as it turns out it operated on a copy of an element, rather than the built-in array. Regards, Terje [1] Since ArrayAccess essentially means overloading the index operator, I'm wondering how this have gone through, since some members of the development team (Andi?) appears to have very strong feelings against operator overloading...? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] PHP5 extensions: using existing function names as method names
It is possible to name a method like an existing function, I'm not sure what you are doing exactly but it works here. I've tried: STRING_METHOD(String, trim) {...} (Yes, I'm trying to build a string class) that means that I also redefinied the Macros. Then I've changed the Macros from PHP_METHOD and PHP_ME to ZEND_NAMED_FUNCTION and ZEND_FENTRY. Still on startup PHP Warning: Function registration failed - duplicate name - trim appears. When your class is called zip and you have a function called zip_open, it will conflict with the function name when you build against php 5.2.0. It is fixed in 5.2 and a work around exists, see ext/zip for an example. I haven't found any real differences (but now I know that there is more than one way to create a class). So I will have to wait for 5.2 to get a trim-method? Daniel -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Return type hints
Terje Slettebø wrote: I'd say that's debatable. :) Yes, it can make it more convenient to handle data coming from outside the script (such as forms), but it can also hide bugs. While it can be argued that conversions between, say, arithmetic types (int and floats) may be useful, allowing conversion from something like NULL to empty string, integer 0, etc. (as PHP does) may be going a little over board, as an uninitialised variable (such as a member variable) may not be easily discovered. IMHO, that is covered by === and the NOTICE error level. -- Brian Moon - http://dealnews.com/ Its good to be cheap =) -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] PHP5 extensions: using existing functionnames as method names
Hello, On 9/13/06, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote: It is possible to name a method like an existing function, I'm not sure what you are doing exactly but it works here. I've tried: STRING_METHOD(String, trim) {...} (Yes, I'm trying to build a string class) that means that I also redefinied the Macros. Then I've changed the Macros from PHP_METHOD and PHP_ME to ZEND_NAMED_FUNCTION and ZEND_FENTRY. Still on startup PHP Warning: Function registration failed - duplicate name - trim appears. When your class is called zip and you have a function called zip_open, it will conflict with the function name when you build against php 5.2.0. It is fixed in 5.2 and a work around exists, see ext/zip for an example. I haven't found any real differences (but now I know that there is more than one way to create a class). So I will have to wait for 5.2 to get a trim-method? No, as I said it works well before 5.2 except for zip_* function name and a uip class. Can you show some code? It will help to figure out what's wrong. --Pierre --Pierre -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] PHP5 extensions: using existing functionnames as method names
On 9/13/06, Pierre [EMAIL PROTECTED] wrote: No, as I said it works well before 5.2 except for zip_* function name and a uip class. I mean for zip_* function names and a zip class :) -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] PHP5 extensions: using existing functio nnames as method names
Can you show some code? It will help to figure out what's wrong. Yes I can :) stringclass.h #ifndef PHP_STRINGCLASS_H #define PHP_STRINGCLASS_H extern zend_module_entry string_module_entry; #define phpext_string_ptr string_module_entry #ifdef PHP_WIN32 #define PHP_STRING_API __declspec(dllexport) #else #define PHP_STRING_API #endif #ifdef ZTS #include TSRM.h #endif PHP_MINIT_FUNCTION(string); PHP_MSHUTDOWN_FUNCTION(string); PHP_RINIT_FUNCTION(string); PHP_RSHUTDOWN_FUNCTION(string); PHP_MINFO_FUNCTION(string); #define STRING_METHOD(function_name) \ ZEND_NAMED_FUNCTION(c_stringclass_##function_name) #define STRING_ME(name, arg_info, flags) \ ZEND_FENTRY(name, c_stringclass_ ##name, arg_info, flags) #ifdef ZTS #define string_G(v) TSRMG(string_globals_id, zend_string_globals *, v) #else #define string_G(v) (string_globals.v) #endif #endif -- And stringclass.c #ifdef HAVE_CONFIG_H #include config.h #endif #include php.h #include php_ini.h #include ext/standard/info.h #include zend_compile.h #include zend_interfaces.h #include zend_exceptions.h #include ext/standard/php_smart_str.h #include ext/standard/php_string.h #include php_stringclass.h static zend_class_entry *string_ce; #ifdef COMPILE_DL_STRING ZEND_GET_MODULE(string) #endif STRING_METHOD(__construct); STRING_METHOD(length); STRING_METHOD(toLower); STRING_METHOD(toUpper); STRING_METHOD(trim); //STRING_METHOD(concat); //STRING_METHOD(__toString); //STRING_METHOD(replace); //and so on static ZEND_BEGIN_ARG_INFO(arginfo_String___construct, 0) ZEND_ARG_INFO(0, str) // parameter name ZEND_END_ARG_INFO(); static zend_function_entry string_functions[] = { STRING_ME(__construct, arginfo_String___construct, ZEND_ACC_PUBLIC) STRING_ME(length, NULL, ZEND_ACC_PUBLIC) STRING_ME(toLower, NULL, ZEND_ACC_PUBLIC) STRING_ME(toUpper, NULL, ZEND_ACC_PUBLIC) STRING_ME(trim, NULL, ZEND_ACC_PUBLIC) //STRING_ME(concat, NULL, ZEND_ACC_PUBLIC) //STRING_ME(__toString, NULL, ZEND_ACC_PUBLIC) //STRING_ME(replace, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; static zend_object_handlers string_handlers; typedef struct _string_object { zend_object std; char *data; int len; } string_object; static void string_object_free_storage(void *object TSRMLS_DC) { string_object *intern = (string_object *)object; zend_hash_destroy(intern-std.properties); FREE_HASHTABLE(intern-std.properties); if(intern-data) { efree(intern-data); } efree(object); } static zend_object_value string_object_new_ex(zend_class_entry *class_type, string_object **obj TSRMLS_DC) { zend_object_value retval; string_object *intern; zval *tmp; intern = emalloc(sizeof(string_object)); memset(intern, 0, sizeof(string_object)); intern-std.ce = class_type; *obj = intern; ALLOC_HASHTABLE(intern-std.properties); zend_hash_init(intern-std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(intern-std.properties, class_type-default_properties, (copy_ctor_func_t) zval_add_ref, (void *) tmp, sizeof(zval *)); retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) string_object_free_storage, NULL TSRMLS_CC); retval.handlers = string_handlers; return retval; } static zend_object_value string_object_new(zend_class_entry *class_type TSRMLS_DC) { string_object *tmp; return string_object_new_ex(class_type, tmp TSRMLS_CC); } static zend_object_value string_object_clone(zval *zobject TSRMLS_DC) { zend_object_value new_obj_val; zend_object *old_object; zend_object *new_object; zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); string_object *intern; old_object = zend_objects_get_address(zobject TSRMLS_CC); new_obj_val = string_object_new_ex(old_object-ce, intern TSRMLS_CC); new_object = intern-std; zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); return new_obj_val; } #if MBO_0 static zend_class_entry *string_get_ce(zval *object TSRMLS_DC) { return string_object; } #endif #if PHP_MAJOR_VERSION = 6 #define EXTSRM TSRMLS_C #else #define EXTSRM #endif STRING_METHOD(__construct) { zval *object = getThis(); string_object *intern; char *str; long strlen; php_set_error_handling(EH_THROW, zend_exception_get_default(EXTSRM) TSRMLS_CC); intern = (string_object*)zend_object_store_get_object(object TSRMLS_CC); if(ZEND_NUM_ARGS() 0) { if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, |s, str, strlen) == FAILURE) {
Re: [PHP-DEV] PHP5 extensions: using existing functionnames as method names
zend_module_entry string_module_entry = { #if ZEND_MODULE_API_NO = 20010901 STANDARD_MODULE_HEADER, #endif string, string_functions, PHP_MINIT(string), PHP_MSHUTDOWN(string), PHP_RINIT(string), /* Replace with NULL if there's nothing to do at request start */ PHP_RSHUTDOWN(string), /* Replace with NULL if there's nothing to do at request end */ PHP_MINFO(string), #if ZEND_MODULE_API_NO = 20010901 0.1, /* Replace with version number for your extension */ #endif STANDARD_MODULE_PROPERTIES }; PHP_MINIT_FUNCTION(string) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, String, string_functions); string_ce = zend_register_internal_class(ce TSRMLS_CC); string_ce-create_object = string_object_new; memcpy(string_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); string_handlers.clone_obj = string_object_clone; return SUCCESS; } Problem #1 (The one you actually wrote about) You're registering your methods twice. Once in zend_module_entry as global functions (the cause of your error), and again in INIT_CLASS_ENTRY() (The right place to be doing it). Solution: Change string_functions to NULL in zend_module_entry. Now for the rest of my complaints (all minor points): stringclass.h Not a major problem, but this file naming will trip up static linking. So long as this is only ever a shared module you don't have any worry of course. But you might as well name it php_stringclass.h #define STRING_METHOD(function_name) \ ZEND_NAMED_FUNCTION(c_stringclass_##function_name) #define STRING_ME(name, arg_info, flags) \ ZEND_FENTRY(name, c_stringclass_ ##name, arg_info, flags) There's nothing special about these macros except for the specific function prefix you assign them. Any particular reason you're using them? #ifdef ZTS #define string_G(v) TSRMG(string_globals_id, zend_string_globals *, v) #else #define string_G(v) (string_globals.v) #endif It's common practice to use all uppercase for TSRM macros. Not really an issue, but worth a mentiCONFORM! YOU MUST CONFORM :) -Sara -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Re: Tweaking expects parameter # to be... message
Show me how many times we use instance versus object in PHP. -Andrei On Sep 11, 2006, at 5:31 PM, Marcus Boerger wrote: Hello Andrei, for some reason i like instance of class better than class object. The reason is that we have instances rather than objects - So it's a purist thing. best regards marcus Monday, September 11, 2006, 6:44:08 PM, you wrote: How is instance of different from object? -Andrei On Sep 10, 2006, at 11:44 PM, Marcus Boerger wrote: Hello Hannes, with your changewe'd have: Warning: token_get_all() expects parameter 1 to be binary string, stdClass object given in %s on line %d i would like the followingmore: Warning: token_get_all() expects parameter 1 to be binary string, instance ofstdClass given in %s on line %d best regards marcus Monday, September 11, 2006, 12:46:56 AM, you wrote: Index: ext/libxml/tests/001.phpt === RCS file: /repository/php-src/ext/libxml/tests/001.phpt,v retrieving revision 1.2 diff -u -r1.2 001.phpt --- ext/libxml/tests/001.phpt 27 Jun 2006 22:54:29 - 1.2 +++ ext/libxml/tests/001.phpt 10 Sep 2006 22:44:45 - @@ -22,7 +22,7 @@ bool(false) bool(true) -Warning: libxml_use_internal_errors() expects parameter 1 to be boolean, object given in %s001.php on line 6 +Warning: libxml_use_internal_errors() expects parameter 1 to be boolean, stdClass object given in %s001.php on line 6 NULL array(0) { } Index: ext/openssl/tests/bug38255.phpt === RCS file: /repository/php-src/ext/openssl/tests/bug38255.phpt,v retrieving revision 1.2 diff -u -r1.2 bug38255.phpt --- ext/openssl/tests/bug38255.phpt 29 Jul 2006 22:41:34 - 1.2 +++ ext/openssl/tests/bug38255.phpt 10 Sep 2006 22:44:45 - @@ -38,10 +38,10 @@ Warning: openssl_verify(): supplied key param cannot be coerced into a public key in %s on line %d bool(false) -Warning: openssl_verify() expects parameter 2 to be string, object given in %s on line %d +Warning: openssl_verify() expects parameter 2 to be string, stdClass object given in %s on line %d NULL -Warning: openssl_verify() expects parameter 2 to be string, object given in %s on line %d +Warning: openssl_verify() expects parameter 2 to be string, stdClass object given in %s on line %d NULL Warning: openssl_verify() expects parameter 2 to be string, array given in %s on line %d @@ -50,6 +50,31 @@ Warning: openssl_verify() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: openssl_verify() expects parameter 1 to be string, object given in %s on line %d +Warning: openssl_verify() expects parameter 1 to be string, stdClass object given in %s on line %d NULL Done +--UEXPECTF-- +Warning: openssl_verify(): supplied key param cannot be coerced into a public key in %s on line %d + +Warning: openssl_verify(): supplied key param cannot be coerced into a public key in %s on line %d +bool(false) + +Warning: openssl_verify(): supplied key param cannot be coerced into a public key in %s on line %d +bool(false) + +Warning: openssl_verify() expects parameter 2 to be binary string, stdClass object given in %s on line %d +NULL + +Warning: openssl_verify() expects parameter 2 to be binary string, stdClass object given in %s on line %d +NULL + +Warning: openssl_verify() expects parameter 2 to be binary string, array given in %s on line %d +NULL + +Warning: openssl_verify() expects at least 3 parameters, 0 given in %s on line %d +NULL + +Warning: openssl_verify() expects parameter 1 to be binary string, stdClass object given in %s on line %d +NULL +Done + Index: ext/spl/tests/iterator_044.phpt === RCS file: /repository/php-src/ext/spl/tests/iterator_044.phpt,v retrieving revision 1.1 diff -u -r1.1 iterator_044.phpt --- ext/spl/tests/iterator_044.phpt 21 May 2006 17:27:12 - 1.1 +++ ext/spl/tests/iterator_044.phpt 10 Sep 2006 22:44:45 - @@ -89,10 +89,10 @@ object(stdClass)#%d (0) { } -Warning: CachingIterator::offsetExists() expects parameter 1 to be string (Unicode or binary), object given in %siterator_044.php on line %d +Warning: CachingIterator::offsetExists() expects parameter 1 to be string (Unicode or binary), stdClass object given in %siterator_044.php on line %d NULL -Warning: CachingIterator::offsetGet() expects parameter 1 to be string (Unicode or binary), object given in %siterator_044.php on line %d +Warning: CachingIterator::offsetGet() expects parameter 1 to be string (Unicode or binary), stdClass object given in %siterator_044.php on line %d NULL ===2=== object(MyFoo)#%d (0) { @@ -134,10 +134,10 @@ object(stdClass)#1 (0) { } -Warning: CachingIterator::offsetExists() expects parameter 1 to be string (Unicode or binary), object given in %siterator_044.php on line %d +Warning: CachingIterator::offsetExists() expects parameter 1 to
Re: [PHP-DEV] PHP5 extensions: using existing function names as method
Solution: Change string_functions to NULL in zend_module_entry. Thanks! You rescued my extension. Now I can finish and test the class. #define STRING_METHOD(function_name) \ ZEND_NAMED_FUNCTION(c_stringclass_##function_name) #define STRING_ME(name, arg_info, flags) \ ZEND_FENTRY(name, c_stringclass_ ##name, arg_info, flags) There's nothing special about these macros except for the specific function prefix you assign them. Any particular reason you're using them? As I wrote, I've looked around existing extensions which redefine function names (SPL and zip) and there I found those Macro-Definitions and thought this could be the solution. #ifdef ZTS #define string_G(v) TSRMG(string_globals_id, zend_string_globals *, v) #else #define string_G(v) (string_globals.v) #endif It's common practice to use all uppercase for TSRM macros. Not really an issue, but worth a mentiCONFORM! YOU MUST CONFORM :) Actually I don't know where this come from and why it's in. I don't have any globals. ext.skel? Copied from somewhere? Don't know. If there is any interest in OO-Representation of primitive types let me know, So I could release them as PECL-extension. Daniel BTW Can anyone explain, why the mailservice I'm using is producing such a crap in the subject and what could be done to prevent this for future posts? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Const member functions
In C++, it's possible to declare member functions const meaning they don't change the object they operate on. This can help reason about programs, because if you have something like (PHP syntax): It would be pretty hard to enforce in PHP - how do you know the object is not changed, without strictly typing all the functions that access it? Also, while in C++ compiler can benefit from knowing the function is const - i.e. from knowing nothing was changed by it regarding this argument - PHP engine hardly can do it. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Return type hints
Terje Slettebø wrote: I'd say that's debatable. :) Yes, it can make it more convenient to handle data coming from outside the script (such as forms), but it can also hide bugs. While it can be argued that conversions between, say, arithmetic types (int and floats) may be useful, allowing conversion from something like NULL to empty string, integer 0, etc. (as PHP does) may be going a little over board, as an uninitialised variable (such as a member variable) may not be easily discovered. IMHO, that is covered by === and the NOTICE error level. Scenario: --- Start --- class Something { public function __construct() { // Oops, forgot to initialise $this-something... } public function f() { return $this-something; } private $something; } error_reporting(E_ALL); $something=new Something; echo $something-f()+10; // Prints 10. --- End --- This will run without any notices, warnings or errors. If we meant to initialise Something::something to a value, then there's no way to detect that in f() (other than manual type-checking), since we can't specify the type for Something::f()'s return type. Had we been able to specify e.g. int as the return type, the call to Something::f() would give us an error message, alerting us to the problem. As the program stands, it has a silent bug... How would you solve this with === or E_ALL? Regards, Terje -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Const member functions
In C++, it's possible to declare member functions const meaning they don't change the object they operate on. This can help reason about programs, because if you have something like (PHP syntax): It would be pretty hard to enforce in PHP - how do you know the object is not changed, without strictly typing all the functions that access it? Like I've mentioned, I don't know how PHP does this internally, so maybe this is hard to detect (or may result in nontrivial overhead). I'm not sure what you mean by strictly typing all the functions that access it: The modification detection would likely have to happen at run-time (not compile-time), due to PHP's dynamically typed nature, so I can't see what typing would have to do with it. Also, while in C++ compiler can benefit from knowing the function is const - i.e. from knowing nothing was changed by it regarding this argument - PHP engine hardly can do it. Much, if not almost all, of the benefit of const is about program correctness and easier reasoning about programs (if you know something is const, including variables, you know you can rely on them not having been changed, even a zillion lines below where they were defined), i.e. advantages for the _developer_, foremost. It _might_ give some possibilities of optimisation, in a statically typed language, but that's more of a side effect. Regards, Terje -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Return type hints
--- Start --- class Something { public function __construct() { // Oops, forgot to initialise $this-something... } public function f() { return $this-something; } private $something; } error_reporting(E_ALL); $something=new Something; echo $something-f()+10; // Prints 10. If you can't trust the return values of your methods, I would use: $var = $something-f(); if($var!==NULL){ echo $var+10; // Prints 10. } However, its crap like this that reminds me why I don't use PHP OOP for all my code. I can find no non-OOP code that behaves this way. Even my favorite PHP trick, using settype() to initialize vars, does not set the var to NULL. -- Brian Moon - http://dealnews.com/ Its good to be cheap =) -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Making ArrayAccess objects more array-like?
Hello Terje, sorry i often only remember the outcome. best regards marcus Wednesday, September 13, 2006, 9:52:57 AM, you wrote: Hi Marcus. long ago we decided against supporting it in the array functions. Ok, thanks. Could I ask what the reasons were (Alternatively get a pointer to the discussion)? Regards, Terje best regards marcus Wednesday, September 13, 2006, 8:39:57 AM, you wrote: Hi all. (Again, I've searched the archives, but haven't found anything on this one) The ArrayAccess interface allows one to essentially overload the index operator [] [1], which is nice, as it makes it possible to implement things like type-checked associative arrays, variants, tuples, etc. However, you can't use it with any of the built-in array functions (such as count(), or the array_*-functions), which means you have to either: 1. Have something like an as_array() member function, returning a reference to the embedded array, and call this every time you need to call one of these functions, or: 2. Implement the functions as member functions on the object. Both of these solutions are rather inelegant, and in particular, 2. leads to unnecessary code bloat, and both gives a different calling convention compared to ordinary arrays, which can surely confuse readers of the code. My question is: Has it been considered changing the standard library functions that take an array as a parameter, to be able to take an object implementing ArrayAccess/IteratorAggregate, also? Would it perhaps be a very large change? That would be understandable, given that it could mean the library having to be able to call into user code (the object being passed). However, this is done elsewhere, too, such as foreach(). I know the inability to return a reference is well known. However, has there come to a consensus about how to solve it (or if)? It tends to trip up code using these arrays a lot... Sometimes, you get no change in the array, as it turns out it operated on a copy of an element, rather than the built-in array. Regards, Terje [1] Since ArrayAccess essentially means overloading the index operator, I'm wondering how this have gone through, since some members of the development team (Andi?) appears to have very strong feelings against operator overloading...? Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] Re: Re: __autoloading and functions
Hi François. I think this sounds like a great idea. :) We do something similar with our class loader, in that it scans a lib-directory and its subfolders, building a map of class name to filename (it doesn't open the files - it only builds the map based on file naming convention, allowing it to infer the class name from the file name, if a file contains a class) and storing it in the session. Yet, something that didn't have to be rebuild at session startup would be even better. Of course, one could serialise this information, but then it becomes important that it updates it when there are relevant file changes (like your CLI program can do). Regards, Terje - Original Message - From: LAUPRETRE François (P) [EMAIL PROTECTED] To: [EMAIL PROTECTED]; internals@lists.php.net Sent: Tuesday, September 12, 2006 1:01 PM Subject: Re: Re: __autoloading and functions Yes, the trivial answer is to name each file after the symbol it contains, but it limits to one symbol per file (and I was talking about autoloading constants ! :-). Once again, if we don't propose a smarter autoload manager, extending the autoload feature to functions is not very interesting because, for most PHP programmers, it won't make their task easier (and it won't allow to autoload extensions, which would be a big step forward). I would be glad if people interested in this subject could have a look at an autoload manager I have written and which could, IMHO, solve most of these problems. It contains two parts : a CLI program to scan source files and extensions and store their symbols in map files, and a runtime resolver which will use these files. A map file can contain symbols for any number of source or extension files allowing, for instance, to put only one map file in the extensions directory to store the symbols of every extensions present on the host. As there is no hook at this time in the PHP engine to autoload functions and constants, their resolutions must be explicitely requested before using the symbol but, if the autoload feature was extended to these symbol types, the autoloader would be completely transparent to the client programs. Of course, it is written in PHP today but it would be quite easy to rewrite it in C and integrate it to the core. If it was integrated to the core and if we added a cache to keep symbol maps in memory, I am sure that the speed up due to JIT loading would balance the autoloading overhead. Please tell me what you think about it. Regards François Terje Slettebø wrote: In either of the above cases, you specify where a function belongs, both where it's defined, and where it's used (either through full qualification, or a shorter one, using import). I'm not arguing for a function to magically become a part of a class/module/whatever, if you thought so Then the question is how do you think this function would be used? That's a very good question... One simple answer would be to have one file per function, and have it work like typical class autoloaders. However, that could be too much overhead (on many levels), having a lot of small files, that conceptually belong together. Maybe function autoloading isn't such an obvious feature, after all (which was one reason for bringing it up - getting the pros and cons of it. By the way, I've now also read in on the archive of this and the other issues having been mentioned in this thread, such as namespaces). Regards, Terje -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Return type hints
From: Brian Moon [EMAIL PROTECTED] --- Start --- class Something { public function __construct() { // Oops, forgot to initialise $this-something... } public function f() { return $this-something; } private $something; } error_reporting(E_ALL); $something=new Something; echo $something-f()+10; // Prints 10. If you can't trust the return values of your methods, I would use: $var = $something-f(); if($var!==NULL){ echo $var+10; // Prints 10. } Right... And you can always use return codes, instead of exceptions or trigger_error(). The problem is that there's nothing that _enforces_ this checking, and since it adds verbosity, it's typically not done. If you don't believe me have a look at some of all of the C code out there, which typically to a large degree don't check return values (and it shows... Programs segfaulting and the like, if something unexpected happens), as it makes the program convoluted and messy, and is easily forgotten. It's for reasons like this that exceptions (and possibly trigger_error()) were invented in the first place. It's similar with the example above: Type-checked return values means you don't have to write all these tedious manual checks, just to ensure program correctness (and had the return type hint been mandatory, there's no way you could forget it or not bother with it, either).. However, its crap like this that reminds me why I don't use PHP OOP for all my code. I can find no non-OOP code that behaves this way. The above was a contrived example, meant to illustrate the point. What's so bad about it? That it doesn't check the return value? Well... having to check the return value, to ensure things didn't go wrong is something I left a looong time ago, when I was programming C, before I started with C++ and Java, which gives better ways of handling this, and have only had to take it up again, in PHP. Even my favorite PHP trick, using settype() to initialize vars, does not set the var to NULL. settype() is still a manual operation - there's no way to automatically guarantee initialisation. In a language like C++, the class members are default-initialised, unless you explicitly initialise them, so there's no way you can forget it or ignore it. The result: More robust programs. Regards, Terje -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php