Ideas on hooking into the object cast handler

php.internals

Robert Silva

21 years ago
I'm working on creating object wrappers for native php types. With ZE2 and the cast_object object handler, I am able to "unbox" the objects to their native php types with simple casts, but as ZE2 currently stands, (to my knowledge at least) there is no way to hook into the (object)native_type cast. Currently, when you cast a native value to an object using (object)$native_val, it calls convert_to_object which simply converts the native type to an array. I was hoping some of you more familiar with the ZE than I had some ideas of how it may be modified to allow an extension to hook into the convert_to_object function. Looked around for some implementation of an extension registering a callback inside the engine but couldn't find any examples. Here is a userland example of what I am trying to accomplish: $intObj = new PInt32(5); // Int object wrapper $phpInt = (int)$intObj; // Calls the cast_object handler for the PInt32 obj This next part isn't currently possible $intObjB = (object)$phpInt; But if I could hook into the convert_to_object function, I could determine what type of class to return based on the op->type being cast. It can be done, just not sure 1) how it would be generic enough (without registering a callback), and 2) whether you guys would be opposed to it, or 3) am I an idiot for trying to do this. Thanks Bob Silva

Curt Zirzow

21 years ago
* Thus wrote Robert Silva:
> I'm working on creating object wrappers for native php types. With ZE2 and > the cast_object object handler, I am able to "unbox" the objects to their > native php types with simple casts, but as ZE2 currently stands, (to my > knowledge at least) there is no way to hook into the (object)native_type > cast. Currently, when you cast a native value to an object using > (object)$native_val, it calls convert_to_object which simply converts the > native type to an array. I was hoping some of you more familiar with the ZE > than I had some ideas of how it may be modified to allow an extension to > hook into the convert_to_object function. Looked around for some > implementation of an extension registering a callback inside the engine but > couldn't find any examples. Here is a userland example of what I am trying > to accomplish: > > $intObj = new PInt32(5); // Int object wrapper > $phpInt = (int)$intObj; // Calls the cast_object handler for the PInt32 obj
I was actually thinking about this the other day, my idea was to force an object declaration to tell everyone that it can be casted, so ZE2 will define all the different type of interfaces: /* ZE2 defined interface represented in php */ interface Castable { function __toString(); function __toInt(); function __toFloat(); function __toArray(); function __toObject($objname); /* questionable */ } Then if a object wishes to be converted to a paticular type it would simply implement the interface: class Foo implements Castable { ... function __toString() { return "I am a string"; } ...all the rest of the interface definitions } The questionable toObject() would provide the possiblities of something like: $newObj = (OtherObject) $FooObject; But, iirc, the above will probably involve a lot of rewriting of the parsing. Curt
-- First, let me assure you that this is not one of those shady pyramid schemes you've been hearing about. No, sir. Our model is the trapezoid!

Andi Gutmans

21 years ago
Hey, I don't think explicit object casting is of much use. How does (float) $obj improve your life much more than $obj->toFloat()? Don't forget that implicit casting doesn't make a lot of sense because "1",1, and 1.0 are all potentially the same in PHP. When you have something like: $num1 + $num2 then PHP looks at both operands in order to decide what it will do. Having an object that can convert into every native type wouldn't fit in with this dynamic typing. How would the engine know which one you want? The only cast I think is useful is the toString() cast as it's also pretty well defined when we need this (concatenation, printing). Andi At 05:16 AM 9/25/2004 +0000, Curt Zirzow wrote:

Robert Silva

21 years ago
I'm essentially trying to emulate the .NET style boxing/unboxing functionality natively in PHP while maintaining strict type checking and not affecting bc or performance (as part of a larger project converting the .NET BFL to a php extension). I already have a large component of it working in userland classes which uses a ZConvert class that calls the IComparable interface of the classes (same as .NET). Using PConvert::ToBoolean($ZBool) everywhere is the nicest solution. In .NET all boxable types descend from a ValueType class. The optimal solution would be to have zend understand a IValueType interface and perform the boxing/unboxing (probably using the cast_object handler or accessing a ce->property value which is how .NET handles it internally) as necessary. This would handle the unboxing for the majority of cases I think, so you could even pass IValueTypes to standard php functions (which parse their params using the convert_to_* functions. final class ZString extends PValueType implements IValueType { ... } final class ZInt32 extends PValueType implements IValueType { ... } ... etc for the native PHP types $zstring = new ZString("PHP "); // $zstring = (object)"PHP "; $zdouble = new ZDouble(5.1); // or possibly even $zint = (object)5.1; $zstring .= $zdouble; $zdouble *= 2; $int = strlen($zstring); // goes through zend_parse_parameters which understands an IValueType object. Where $zstring and $zdouble remain their respective object types. And then going the other way... if it was possible for an extension to provide a callback to the (object) ZEND_CAST then the following would be possible (the closest I think it could get to real boxing) Note the TypeHints forcing a true object interface, then the explicit cast in the function call. final class ZString extends ZValueType implements IValueType { public static function Concat(ZString $strA, ZString $strB) { return new ZString($strA.$strB); } } $zstring = new ZString("PHP "); $zstring = ZString::Concat($zstring, (object)"5.1.0"); The callback would determine the object type being cast and create a new ZValueType of that object type. I think my thoughts got all jumbled describing this...I know the unboxing of the types will work with no changes....its just the boxing that would require changes by registering a callback during object casts. Like I said, this is mainly for the experience right now, but I would like to release the .NET BFL extension as some point in time. (Along with the ASP page/component processing model) How cool would it be to develop PHP web pages visually in Visual Studio? I'll tackle that part of it when I get this part done :) Bob Silva