language/oop5/basic.xml
c1f37a6c270aadbbb3da56a3973ffd62197adf2b
c1f37a6c270aadbbb3da56a3973ffd62197adf2b
...
...
@@ -14,10 +14,12 @@
14
14
</para>
15
15
<para>
16
16
The class name can be any valid label, provided it is not a
17
-
PHP <link linkend="reserved">reserved word</link>. A valid class
18
-
name starts with a letter or underscore, followed by any number of
19
-
letters, numbers, or underscores. As a regular expression, it
20
-
would be expressed thus:
17
+
PHP <link linkend="reserved">reserved word</link>.
18
+
As of PHP 8.4.0, using a single underscore <literal>_</literal> as a
19
+
class name is deprecated.
20
+
A valid class name starts with a letter or underscore,
21
+
followed by any number of letters, numbers, or underscores.
22
+
As a regular expression, it would be expressed thus:
21
23
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>.
22
24
</para>
23
25
<para>
...
...
@@ -125,6 +127,72 @@ Stack trace:
125
127
</screen>
126
128
</example>
127
129
</warning>
130
+
131
+
<sect3 xml:id="language.oop5.basic.class.readonly">
132
+
<title>Readonly classes</title>
133
+
<para>
134
+
As of PHP 8.2.0, a class can be marked with the
135
+
<modifier>readonly</modifier> modifier.
136
+
Marking a class as <modifier>readonly</modifier> will add the
137
+
<link linkend="language.oop5.properties.readonly-properties"><modifier>readonly</modifier> modifier</link>
138
+
to every declared property, and prevent the creation of
139
+
<link linkend="language.oop5.properties.dynamic-properties">dynamic properties</link>.
140
+
Moreover, it is impossible to add support for them by using the
141
+
<classname>AllowDynamicProperties</classname> attribute. Attempting to do so
142
+
will trigger a compile-time error.
143
+
</para>
144
+
<informalexample>
145
+
<programlisting role="php">
146
+
<![CDATA[
147
+
<?php
148
+
#[\AllowDynamicProperties]
149
+
readonly class Foo {
150
+
}
151
+
152
+
// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo
153
+
?>
154
+
]]>
155
+
</programlisting>
156
+
</informalexample>
157
+
158
+
<para>
159
+
As neither untyped nor static properties can be marked with the
160
+
<literal>readonly</literal> modifier, readonly classes cannot declare
161
+
them either:
162
+
</para>
163
+
<informalexample>
164
+
<programlisting role="php">
165
+
<![CDATA[
166
+
<?php
167
+
readonly class Foo
168
+
{
169
+
public $bar;
170
+
}
171
+
172
+
// Fatal error: Readonly property Foo::$bar must have type
173
+
?>
174
+
]]>
175
+
</programlisting>
176
+
<programlisting role="php">
177
+
<![CDATA[
178
+
<?php
179
+
readonly class Foo
180
+
{
181
+
public static int $bar;
182
+
}
183
+
184
+
// Fatal error: Readonly class Foo cannot declare static properties
185
+
?>
186
+
]]>
187
+
</programlisting>
188
+
</informalexample>
189
+
<para>
190
+
A <modifier>readonly</modifier> class can be
191
+
<link linkend="language.oop5.basic.extends">extended</link>
192
+
if, and only if, the child class is also a
193
+
<modifier>readonly</modifier> class.
194
+
</para>
195
+
</sect3>
128
196
</sect2>
129
197
130
198
<sect2 xml:id="language.oop5.basic.new">
...
...
@@ -138,7 +206,7 @@ Stack trace:
138
206
requirement).
139
207
</para>
140
208
<para>
141
-
If a <type>string</type> containing the name of a class is used with
209
+
If a variable containing a <type>string</type> with the name of a class is used with
142
210
<literal>new</literal>, a new instance of that class will be created. If
143
211
the class is in a namespace, its fully qualified name must be used when
144
212
doing this.
...
...
@@ -156,15 +224,67 @@ Stack trace:
156
224
<programlisting role="php">
157
225
<![CDATA[
158
226
<?php
227
+
class SimpleClass {
228
+
}
229
+
159
230
$instance = new SimpleClass();
231
+
var_dump($instance);
160
232
161
233
// This can also be done with a variable:
162
234
$className = 'SimpleClass';
163
235
$instance = new $className(); // new SimpleClass()
236
+
var_dump($instance);
164
237
?>
165
238
]]>
166
239
</programlisting>
167
240
</example>
241
+
<para>
242
+
As of PHP 8.0.0, using <literal>new</literal> with arbitrary expressions
243
+
is supported. This allows more complex instantiation if the expression
244
+
produces a <type>string</type>. The expressions must be wrapped in parentheses.
245
+
</para>
246
+
<example>
247
+
<title>Creating an instance using an arbitrary expression</title>
248
+
<para>
249
+
In the given example we show multiple examples of valid arbitrary expressions that produce a class name.
250
+
This shows a call to a function, string concatenation, and the <constant>::class</constant> constant.
251
+
</para>
252
+
<programlisting role="php">
253
+
<![CDATA[
254
+
<?php
255
+
256
+
class ClassA extends \stdClass {}
257
+
class ClassB extends \stdClass {}
258
+
class ClassC extends ClassB {}
259
+
class ClassD extends ClassA {}
260
+
261
+
function getSomeClass(): string
262
+
{
263
+
return 'ClassA';
264
+
}
265
+
266
+
var_dump(new (getSomeClass()));
267
+
var_dump(new ('Class' . 'B'));
268
+
var_dump(new ('Class' . 'C'));
269
+
var_dump(new (ClassD::class));
270
+
?>
271
+
]]>
272
+
</programlisting>
273
+
&example.outputs.8;
274
+
<screen>
275
+
<![CDATA[
276
+
object(ClassA)#1 (0) {
277
+
}
278
+
object(ClassB)#1 (0) {
279
+
}
280
+
object(ClassC)#1 (0) {
281
+
}
282
+
object(ClassD)#1 (0) {
283
+
}
284
+
285
+
]]>
286
+
</screen>
287
+
</example>
168
288
<para>
169
289
In the class context, it is possible to create a new object by
170
290
<literal>new self</literal> and <literal>new parent</literal>.
...
...
@@ -181,6 +301,9 @@ $instance = new $className(); // new SimpleClass()
181
301
<programlisting role="php">
182
302
<![CDATA[
183
303
<?php
304
+
class SimpleClass {
305
+
public string $var;
306
+
}
184
307
185
308
$instance = new SimpleClass();
186
309
...
...
@@ -217,26 +340,27 @@ object(SimpleClass)#1 (1) {
217
340
<programlisting role="php">
218
341
<![CDATA[
219
342
<?php
343
+
220
344
class Test
221
345
{
222
-
static public function getNew()
346
+
public static function getNew()
223
347
{
224
-
return new static;
348
+
return new static();
225
349
}
226
350
}
227
351
228
-
class Child extends Test
229
-
{}
352
+
class Child extends Test {}
230
353
231
-
$obj1 = new Test();
232
-
$obj2 = new $obj1;
354
+
$obj1 = new Test(); // By the class name
355
+
$obj2 = new $obj1(); // Through the variable containing an object
233
356
var_dump($obj1 !== $obj2);
234
357
235
-
$obj3 = Test::getNew();
358
+
$obj3 = Test::getNew(); // By the class method
236
359
var_dump($obj3 instanceof Test);
237
360
238
-
$obj4 = Child::getNew();
361
+
$obj4 = Child::getNew(); // Through a child class method
239
362
var_dump($obj4 instanceof Child);
363
+
240
364
?>
241
365
]]>
242
366
</programlisting>
...
...
@@ -259,14 +383,18 @@ bool(true)
259
383
<programlisting role="php">
260
384
<![CDATA[
261
385
<?php
262
-
echo (new DateTime())->format('Y');
386
+
echo (new DateTime())->format('Y'), PHP_EOL;
387
+
388
+
// surrounding parentheses are optional as of PHP 8.4.0
389
+
echo new DateTime()->format('Y'), PHP_EOL;
263
390
?>
264
391
]]>
265
392
</programlisting>
266
393
&example.outputs.similar;
267
394
<screen>
268
395
<![CDATA[
269
-
2016
396
+
2025
397
+
2025
270
398
]]>
271
399
</screen>
272
400
</example>
...
...
@@ -364,17 +492,30 @@ echo ($obj->bar)(), PHP_EOL;
364
492
<para>
365
493
The inherited constants, methods, and properties can be overridden by
366
494
redeclaring them with the same name defined in the parent
367
-
class. However, if the parent class has defined a method
368
-
as <link linkend="language.oop5.final">final</link>, that method
369
-
may not be overridden. It is possible to access the overridden
495
+
class. However, if the parent class has defined a method or constant
496
+
as <link linkend="language.oop5.final">final</link>,
497
+
they may not be overridden. It is possible to access the overridden
370
498
methods or static properties by referencing them
371
499
with <link linkend="language.oop5.paamayim-nekudotayim">parent::</link>.
372
500
</para>
501
+
<note>
502
+
<simpara>
503
+
As of PHP 8.1.0, constants may be declared as final.
504
+
</simpara>
505
+
</note>
373
506
<example>
374
507
<title>Simple Class Inheritance</title>
375
508
<programlisting role="php">
376
509
<![CDATA[
377
510
<?php
511
+
class SimpleClass
512
+
{
513
+
function displayVar()
514
+
{
515
+
echo "Parent class\n";
516
+
}
517
+
}
518
+
378
519
class ExtendClass extends SimpleClass
379
520
{
380
521
// Redefine the parent method
...
...
@@ -407,7 +548,8 @@ a default value
407
548
<constant>E_WARNING</constant> level error is generated.
408
549
A signature is compatible if it respects the
409
550
<link linkend="language.oop5.variance">variance</link> rules, makes a
410
-
mandatory parameter optional, and if any new parameters are optional.
551
+
mandatory parameter optional, adds only optional new parameters and
552
+
doesn't restrict but only relaxes the visibility.
411
553
This is known as the Liskov Substitution Principle, or LSP for short.
412
554
The <link linkend="language.oop5.decon.constructor">constructor</link>,
413
555
and <literal>private</literal> methods are exempt from these signature
...
...
@@ -568,9 +710,9 @@ Stack trace:
568
710
569
711
<para>
570
712
The <literal>class</literal> keyword is also used for class
571
-
name resolution. You can get a string containing the fully qualified name
572
-
of the <literal>ClassName</literal> class by using
573
-
<literal>ClassName::class</literal>. This is particularly useful with
713
+
name resolution.
714
+
To obtain the fully qualified name of a class <literal>ClassName</literal>
715
+
use <literal>ClassName::class</literal>. This is particularly useful with
574
716
<link linkend="language.namespaces">namespaced</link> classes.
575
717
</para>
576
718
<para>
...
...
@@ -621,7 +763,7 @@ Does\Not\Exist
621
763
</example>
622
764
</note>
623
765
<para>
624
-
As of PHP 8.0.0, the <literal>::class</literal> constant may also be used on
766
+
As of PHP 8.0.0, <literal>::class</literal> may also be used on
625
767
objects. This resolution happens at runtime, not compile time. Its effect is
626
768
the same as calling <function>get_class</function> on the object.
627
769
</para>
...
...
@@ -633,9 +775,10 @@ Does\Not\Exist
633
775
namespace NS {
634
776
class ClassName {
635
777
}
778
+
779
+
$c = new ClassName();
780
+
print $c::class;
636
781
}
637
-
$c = new ClassName();
638
-
print $c::class;
639
782
?>
640
783
]]>
641
784
</programlisting>
...
...
@@ -664,7 +807,7 @@ NS\ClassName
664
807
<para>
665
808
<example>
666
809
<title>Nullsafe Operator</title>
667
-
<programlisting role="php">
810
+
<programlisting role="php" annotations="non-interactive">
668
811
<![CDATA[
669
812
<?php
670
813
671
814