Skip to content

Commit c925e1a

Browse files
Adds a note about hooks + constructor property promotion (#4264)
Per a conversation with @Crell, added a note to detail behavior of hooks when the set hook allows more types than the property, and is used with constructor property promotion. Co-authored-by: Gina Peter Banyard <[email protected]>
1 parent 4bf27ed commit c925e1a

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

language/oop5/property-hooks.xml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,72 @@ class Example
199199
On a backed property, omitting a <literal>get</literal> or<literal>set</literal>
200200
hook means the default read or write behavior will be used.
201201
</simpara>
202+
<note>
203+
<simpara>
204+
Hooks can be defined when using
205+
<link linkend="language.oop5.decon.constructor.promotion">constructor property promotion</link>.
206+
However, when doing so, values provided
207+
to the constructor must match the type associated with the property,
208+
regardless of what the <literal>set</literal> hook might allow.
209+
</simpara>
210+
<simpara>
211+
Consider the following:
212+
</simpara>
213+
<programlisting role="php">
214+
<![CDATA[
215+
class Example
216+
{
217+
public function __construct(
218+
public private(set) DateTimeInterface $created {
219+
set (string|DateTimeInterface $value) {
220+
if (is_string($value)) {
221+
$value = new DateTimeImmutable($value);
222+
}
223+
$this->created = $value;
224+
}
225+
},
226+
) {
227+
}
228+
}
229+
]]>
230+
</programlisting>
231+
<simpara>
232+
Internally, the engine decomposes this to the following:
233+
</simpara>
234+
<programlisting role="php">
235+
<![CDATA[
236+
class Example
237+
{
238+
public private(set) DateTimeInterface $created {
239+
set (string|DateTimeInterface $value) {
240+
if (is_string($value)) {
241+
$value = new DateTimeImmutable($value);
242+
}
243+
$this->created = $value;
244+
}
245+
}
246+
247+
public function __construct(
248+
DateTimeInterface $created,
249+
) {
250+
$this->created = $created;
251+
}
252+
}
253+
]]>
254+
</programlisting>
255+
<simpara>
256+
Any attempts to set the property outside the constructor will
257+
allow either <type>string</type> or <interfacename>DateTimeInterface</interfacename>
258+
values, but the constructor will only allow <interfacename>DateTimeInterface</interfacename>.
259+
This is because the defined type for the property (<interfacename>DateTimeInterface</interfacename>)
260+
is used as the parameter type within the constructor signature, regardless of what
261+
the <literal>set</literal> hook allows.
262+
</simpara>
263+
<simpara>
264+
If this kind of behavior is needed from the constructor, constructor
265+
property promotion cannot be used.
266+
</simpara>
267+
</note>
202268
</sect2>
203269
<sect2 xml:id="language.oop5.property-hooks.virtual">
204270
<title>Virtual properties</title>

0 commit comments

Comments
 (0)