Skip to content

Commit f9dabde

Browse files
CrellGirgias
andauthored
Hooks documentation (#4094)
* Add basic Hooks syntax. * Document the __PROPERTY__ magic constant. * Virtual properties. * Document inheritance. * Note incompatibility with readonly. * Interface properties. * Abstract properties. * Discuss property variance. * Add serialization section. --------- Co-authored-by: Gina Peter Banyard <[email protected]>
1 parent 550b9c3 commit f9dabde

File tree

6 files changed

+730
-9
lines changed

6 files changed

+730
-9
lines changed

language/constants.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,12 @@ echo ANIMALS[1]; // outputs "cat"
321321
The class method name.
322322
</entry>
323323
</row>
324+
<row xml:id="constant.property">
325+
<entry><constant>__PROPERTY__</constant></entry>
326+
<entry>
327+
Only valid inside a <link linkend="language.oop5.property-hooks">property hook</link>. It is equal to the name of the property.
328+
</entry>
329+
</row>
324330
<row xml:id="constant.namespace">
325331
<entry><constant>__NAMESPACE__</constant></entry>
326332
<entry>

language/oop5.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
&language.oop5.basic;
2828
&language.oop5.properties;
29+
&language.oop5.property-hooks;
2930
&language.oop5.constants;
3031
&language.oop5.autoload;
3132
&language.oop5.decon;

language/oop5/abstract.xml

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
<title>Class Abstraction</title>
55

66
<para>
7-
PHP has abstract classes and methods.
7+
PHP has abstract classes, methods, and properties.
88
Classes defined as abstract cannot be instantiated, and any class that
9-
contains at least one abstract method must also be abstract.
10-
Methods defined as abstract simply declare the method's signature;
11-
they cannot define the implementation.
9+
contains at least one abstract method or property must also be abstract.
10+
Methods defined as abstract simply declare the method's signature and whether it is public or protected;
11+
they cannot define the implementation. Properties defined as abstract
12+
may declare a requirement for <literal>get</literal> or <literal>set</literal>
13+
behavior, and may provide an implementation for one, but not both, operations.
1214
</para>
1315

1416
<para>
@@ -19,8 +21,18 @@
1921
<link linkend="language.oop.lsp">signature compatibility</link> rules.
2022
</para>
2123

24+
<para>
25+
As of PHP 8.4, an abstract class may declare an abstract property, either public or protected.
26+
A protected abstract property may be satisfied by a property that is readable/writeable from either
27+
protected or public scope.
28+
</para>
29+
<para>
30+
An abstract property may be satisfied either by a standard property or by a property
31+
with defined <link linkend="language.oop5.property-hooks">hooks</link>, corresponding to the required operation.
32+
</para>
33+
2234
<example>
23-
<title>Abstract class example</title>
35+
<title>Abstract method example</title>
2436
<programlisting role="php">
2537
<![CDATA[
2638
<?php
@@ -80,7 +92,7 @@ FOO_ConcreteClass2
8092
</example>
8193

8294
<example>
83-
<title>Abstract class example</title>
95+
<title>Abstract method example</title>
8496
<programlisting role="php">
8597
<![CDATA[
8698
<?php
@@ -121,6 +133,66 @@ Mrs. Pacwoman
121133
]]>
122134
</screen>
123135
</example>
136+
<example>
137+
<title>Abstract property example</title>
138+
<programlisting role="php">
139+
<![CDATA[
140+
<?php
141+
abstract class A
142+
{
143+
// Extending classes must have a publicly-gettable property.
144+
abstract public string $readable { get; }
145+
146+
// Extending classes must have a protected- or public-writeable property.
147+
abstract protected string $writeable { set; }
148+
149+
// Extending classes must have a protected or public symmetric property.
150+
abstract protected string $both { get; set; }
151+
}
152+
153+
class C extends A
154+
{
155+
// This satisfies the requirement and also makes it settable, which is valid.
156+
public string $readable;
157+
158+
// This would NOT satisfy the requirement, as it is not publicly readable.
159+
protected string $readable;
160+
161+
// This satisfies the requirement exactly, so is sufficient.
162+
// It may only be written to, and only from protected scope.
163+
protected string $writeable {
164+
set => $value;
165+
}
166+
167+
// This expands the visibility from protected to public, which is fine.
168+
public string $both;
169+
}
170+
?>
171+
]]>
172+
</programlisting>
173+
</example>
174+
<para>
175+
An abstract property on an abstract class may provide implementations for any hook,
176+
but must have either <literal>get</literal> or <literal>set</literal> declared but not defined (as in the example above).
177+
</para>
178+
<example>
179+
<title>Abstract property example</title>
180+
<programlisting role="php">
181+
<![CDATA[
182+
<?php
183+
abstract class A
184+
{
185+
// This provides a default (but overridable) set implementation,
186+
// and requires child classes to provide a get implementation.
187+
abstract public string $foo {
188+
get;
189+
set { $this->foo = $value };
190+
}
191+
}
192+
?>
193+
]]>
194+
</programlisting>
195+
</example>
124196
</sect1>
125197
<!-- Keep this comment at the end of the file
126198
Local variables:

language/oop5/interfaces.xml

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<sect1 xml:id="language.oop5.interfaces" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
44
<title>Object Interfaces</title>
55
<para>
6-
Object interfaces allow you to create code which specifies which methods a
7-
class must implement, without having to define how these methods are
6+
Object interfaces allow you to create code which specifies which methods and properties a
7+
class must implement, without having to define how these methods or properties are
88
implemented. Interfaces share a namespace with classes and traits, so they may
99
not use the same name.
1010
</para>
@@ -89,6 +89,83 @@
8989
Prior to PHP 8.1.0, they cannot be overridden by a class/interface that inherits them.
9090
</para>
9191
</sect2>
92+
<sect2 xml:id="language.oop5.interfaces.properties">
93+
<title>Properties</title>
94+
<para>
95+
As of PHP 8.4.0, interfaces may also declare properties. If they do, the declaration must specify if the
96+
property is to be readable, writeable, or both. The interface declaration applies only to public read
97+
and write access.
98+
</para>
99+
<para>
100+
An class may satisfy an interface property in multiple ways. It may define a public property. It may
101+
define a public <link linkend="language.oop5.property-hooks.virtual">virtual property</link> that implements
102+
only the corresponding hook. Or a read property may be satisfied by a <literal>readonly</literal> property.
103+
However, an interface property that is settable may not be <literal>readonly</literal>.
104+
</para>
105+
<example>
106+
<title>Interface properties example</title>
107+
<programlisting role="php">
108+
<![CDATA[
109+
<?php
110+
interface I
111+
{
112+
// An implementing class MUST have a publicly-readable property,
113+
// but whether or not it's publicly settable is unrestricted.
114+
public string $readable { get; }
115+
116+
// An implementing class MUST have a publicly-writeable property,
117+
// but whether or not it's publicly readable is unrestricted.
118+
public string $writeable { set; }
119+
120+
// An implementing class MUST have a property that is both publicly
121+
// readable and publicly writeable.
122+
public string $both { get; set; }
123+
}
124+
125+
// This class implements all three properties as traditional, un-hooked
126+
// properties. That's entirely valid.
127+
class C1 implements I
128+
{
129+
public string $readable;
130+
131+
public string $writeable;
132+
133+
public string $both;
134+
}
135+
136+
// This class implements all three properties using just the hooks
137+
// that are requested. This is also entirely valid.
138+
class C2 implements I
139+
{
140+
private string $written = '';
141+
private string $all = '';
142+
143+
// Uses only a get hook to create a virtual property.
144+
// This satisfies the "public get" requirement.
145+
// It is not writeable, but that is not required by the interface.
146+
public string $readable { get => strtoupper($this->writeable); }
147+
148+
// The interface only requires the property be settable,
149+
// but also including get operations is entirely valid.
150+
// This example creates a virtual property, which is fine.
151+
public string $writeable {
152+
get => $this->written;
153+
set => $value;
154+
}
155+
156+
// This property requires both read and write be possible,
157+
// so we need to either implement both, or allow it to have
158+
// the default behavior.
159+
public string $both {
160+
get => $this->all;
161+
set => strtoupper($value);
162+
}
163+
}
164+
?>
165+
]]>
166+
</programlisting>
167+
</example>
168+
</sect2>
92169
<sect2 xml:id="language.oop5.interfaces.examples">
93170
&reftitle.examples;
94171
<example xml:id="language.oop5.interfaces.examples.ex1">

0 commit comments

Comments
 (0)