# Proposal: A way for classes to define a response to any primitive type cast

- Thread: https://externals.io/message/110846
- Original archive: https://news-web.php.net/php.internals/110846
- Started by Josh Bruce on 2020-07-06T14:17:12+00:00
- Messages: 5
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #110846 — Josh Bruce — 2020-07-06T14:17:12+00:00

URL: https://externals.io/message/110846#110846

Apologies, first time, still learning and have no historical context - timing is what it is.

Proposal type: Concept

Implementer: Unknown, fallback to me after slow learning

Presumed simple implementation as the pattern should already be in place:

Cast of (string) -> __toString() - already implemented

Cast of (bool) -> __toBool()

Cast of (int) -> __toInt()

Cast of (object) -> __toObject()

…and so on.

Alternative implementation using an interface:

\CastableTo{type}

Extreme implementation:

Make both of the previous available.

Known unknowns:

- Level of interest in something like this in the PHP community outside of one upvote on a Stackoverflow question I submitted: https://stackoverflow.com/questions/62747837/php-7-tostring-or-other-interface-for-boolean-values <https://stackoverflow.com/questions/62747837/php-7-tostring-or-other-interface-for-boolean-values>
- Whether this conversation or proposal has already occurred.
- The historical conversation leading to the creation of the __toString() method (and stopping there).
- The current conversation around using magic methods in general and specifically when defining a cast response.
- Enough details on PHP internal development to implement myself (this is the first time in 20 years I felt I couldn’t comfortably accomplish what I wanted to, thanks for that).
- What potential collisions could occur if someone (me) wanted to implement all possibilities in a single class.
- Right now __toBool() would be of the most personal benefit - if proposal is converted to an RFC, would it be better (faster/smoother) to do one RFC for all the cast possibilities - or to have an RFC for each cast separately?

Thank you for the consideration, information, and feedback.

Cheers,
Josh

ps. Also, apologies again for walking into a new space on a mission, not my normal approach.

pps. The primary project inspiring the proposal: https://github.com/8fold/php-shoop <https://github.com/8fold/php-shoop

---

## #110851 — Marco Pivetta — 2020-07-06T16:54:10+00:00

URL: https://externals.io/message/110846#110851 · In reply to: #110846

Hey Josh,

Similar proposals were raised recently for `__toArray()`: see
https://externals.io/message/108369#108369

I'd endorse avoiding object-to-<scalar> casts via cast operations: they are
a good source of bugs.
My rationale for the discouragement of magic cast methods is explained with
some code examples at
https://github.com/ShittySoft/symfony-live-berlin-2018-doctrine-tutorial/pull/3#issuecomment-460441229

Greets,

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/




> Apologies, first time, still learning and have no historical context -
> timing is what it is.
>
> Proposal type: Concept
>
> Implementer: Unknown, fallback to me after slow learning
>
> Presumed simple implementation as the pattern should already be in place:
>
> Cast of (string) -> __toString() - already implemented
>
> Cast of (bool) -> __toBool()
>
> Cast of (int) -> __toInt()
>
> Cast of (object) -> __toObject()
>
> …and so on.
>
> Alternative implementation using an interface:
>
> \CastableTo{type}
>
> Extreme implementation:
>
> Make both of the previous available.
>
> Known unknowns:
>
> - Level of interest in something like this in the PHP community outside of
> one upvote on a Stackoverflow question I submitted:
> https://stackoverflow.com/questions/62747837/php-7-tostring-or-other-interface-for-boolean-values
> <
> https://stackoverflow.com/questions/62747837/php-7-tostring-or-other-interface-for-boolean-values
> > […]
> - Whether this conversation or proposal has already occurred.
> - The historical conversation leading to the creation of the __toString()
> method (and stopping there).
> - The current conversation around using magic methods in general and
> specifically when defining a cast response.
> - Enough details on PHP internal development to implement myself (this is
> the first time in 20 years I felt I couldn’t comfortably accomplish what I
> wanted to, thanks for that).
> - What potential collisions could occur if someone (me) wanted to
> implement all possibilities in a single class.
> - Right now __toBool() would be of the most personal benefit - if proposal
> is converted to an RFC, would it be better (faster/smoother) to do one RFC
> for all the cast possibilities - or to have an RFC for each cast separately?
>
> Thank you for the consideration, information, and feedback.
>
> Cheers,
> Josh
>
> ps. Also, apologies again for walking into a new space on a mission, not
> my normal approach.
>
> pps. The primary project inspiring the proposal:
> https://github.com/8fold/php-shoop <https://github.com/8fold/php-shoop

---

## #110866 — Josh Bruce — 2020-07-07T17:13:39+00:00

URL: https://externals.io/message/110846#110866 · In reply to: #110851

> 
> 
> Hey Josh,
> 
> Similar proposals were raised recently for `__toArray()`: see
> https://externals.io/message/108369#108369
> 
> I'd endorse avoiding object-to-<scalar> casts via cast operations: they are
> a good source of bugs.
> My rationale for the discouragement of magic cast methods is explained with
> some code examples at
> https://github.com/ShittySoft/symfony-live-berlin-2018-doctrine-tutorial/pull/3#issuecomment-460441229
> 
> Greets,
> 
> Marco Pivetta
> 
> http://twitter.com/Ocramius
> 
> http://ocramius.github.com/
> 
> 
> 
> 
> > […]

Thank you for the reply Marco.

Decided to put something together: https://github.com/joshbruce/external-project-proposals/blob/master/php-concepts/interact-with-instance-as-php.md <https://github.com/joshbruce/external-project-proposals/blob/master/php-concepts/interact-with-instance-as-php.md>

I really appreciated the links to and conversations on __toArray. I hope I adequately incorporated and differentiated the desired outcome (interact as if PHP primitive) instead of focusing on the implementation (cast).

Also, just to make sure I caught what you were saying: You recommend avoiding making thing “cast-able” - but ardently necessarily opposed to other means.

Cheers,
Josh

---

## #110867 — Rowan Tommins — 2020-07-07T20:24:39+00:00

URL: https://externals.io/message/110846#110867 · In reply to: #110866

> Decided to put something together:https://github.com/joshbruce/external-project-proposals/blob/master/php-concepts/interact-with-instance-as-php.md


Hi Josh,

Reading through this, it seems to cover a few different concepts, which 
are certainly related, but not quite the same.

Firstly, we have interfaces such as Countable and Serializable, which 
don't make the object act like any particular primitive type, they just 
customise its interaction with particular functions. Iterators could 
potentially be included in that category, too, because it's fairly easy 
to imagine the language having multiple primitive types that can be 
iterated (e.g. separate "list" and "dictionary" types).

ArrayAccess feels more explicitly about making an object "act like" an 
array, but more precisely it overloads the [] operator - it doesn't 
allow the object to be used in other contexts where arrays are allowed. 
More general operator overloading was discussed recently, and the 
particular proposal put forward did not pass its RFC vote. [1]

  __toString, on the other hand, only allows the object to be *converted 
to* a string, not act like one. You can't, for instance, influence the 
behaviour of the concatenation operator, and make "Hello" . $object . 
"!" return an object instead of a string, or a string that doesn't begin 
"Hello". An __toArray method was proposed recently, to mixed reaction. [2]

The other closely related topic is what is often discussed as "scalar 
methods" or "scalar objects" - the ability to call methods on non-object 
values, and possibly to define your own methods that can be called in 
this way. This would seem to fit your use case with Shoop quite well: 
rather than Shoop::array($array)->first()->unfold(), you would just call 
$array->first(). It's fairly high on a lot of people's wish lists, but 
there's a lot of details to get right in both design and implementation, 
so I strongly recommend searching for previous discussions and proofs of 
concept before diving in.


[1] https://wiki.php.net/rfc/userspace_operator_overloading
[2] https://externals.io/message/105589

-- 
Rowan Tommins (né Collins)
[IMSoP]

---

## #110876 — someniatko — 2020-07-08T09:00:12+00:00

URL: https://externals.io/message/110846#110876 · In reply to: #110867

> This would seem to fit your use case with Shoop quite well:
> rather than Shoop::array($array)->first()->unfold(), you would just call
> $array->first(). It's fairly high on a lot of people's wish lists, but
> there's a lot of details to get right in both design and implementation,
> so I strongly recommend searching for previous discussions and proofs of
> concept before diving in.

We don't need methods on non-scalar objects, if we have [pipe
operator](https://wiki.php.net/rfc/pipe-operator-v2): sth like `$array
|> array_first(?)`. This would allow much greater flexibility.
