Table of Contents

Request for Comments: Scalar Type Casting Magic Methods

Introduction

Currently, the Zend Engine exposes several methods to PECL extensions and internal classes to control how internal objects behave when casting to primitives. The two methods used in this RFC are specifically cast_object() and get() . This proposal is to expose those two methods as a series of 5 new magic methods to allow user classes to hook into this functionality more completely.

Use Cases

Scalar Wrapping

One use-case for this functionality is in creating wrapper classes for scalar values. There are several possibilities that this will enable:

Implementation

Syntax

This RFC and patch introduces 4 new magic methods:

Handler Behavior

When the cast_object handler is called, the type parameter is switched against to determine which magic method to call. The four possibilities include toInt(), toFloat(), toArray(), toString() and toBool().

When the get handler is called, the toScalar() method is invoked. This would indicate that the cast is to a scalar, but the type is up to the class to determine. This is called when a primitive type is needed, but not a specific one. So the normal math operators trigger a get call: (+, -, *, /), in addition to compound operators (++, +=, &=, |=, etc).

Example Triggers

<?php

 $obj = $obj + 1; // triggers __toScalar(), followed by the object being overwritten by the return + 1 (based on normal juggling rules)
 (int) $obj; // triggers __toInt()
 substr($obj1, $obj2); // triggers __toString() on $obj1, and __toInt() on $obj2
 (array) $obj; // triggers __toArray()
 array_keys($obj); // triggers __toArray()
 (bool) $obj; // triggers __toBool()

Backwards Compatibility Breaks

The changes to the object handlers are designed in such a way that if the object does not implement the new methods, it will behave as it currently does without the patch.

There are also direct references to the magic methods added to zend_parse_arg_impl to allow for backwards compatible casting while still allowing core functions to accept a casted argument.

References

The normal casting logic does not make a distinction between how casts happen with references. So this patch does not attempt to make a distinction there. However, when an internal function accepts a typed parameter by reference, if the magic cast method is defined on the passed in object, an error is raised as the cast cannot be performed because of the reference.

This means that an object implementing toArray cannot be passed directly to sort(), as that would cause the object to be destroyed. So, to prevent data loss, references are prevented from automated casting.

Todo

Further reading