xref: /web-php/releases/8.1/release.inc (revision 139d12d9)
1<?php
2
3use function releases\php81\common_header;
4use function releases\php81\language_chooser;
5use function releases\php81\message;
6
7if (!isset($lang)) {
8    $lang = 'en';
9}
10
11$_SERVER['BASE_PAGE'] = 'releases/8.1/' . $lang . '.php';
12
13include_once __DIR__ . '/common.php';
14
15common_header(message('common_header', $lang));
16
17?>
18<section class="php8-section php8-section_dark php8-section_header center">
19    <div class="page-tools">
20        <div class="change-language">
21            <?php language_chooser($lang); ?>
22        </div>
23    </div>
24    <div class="php8-section__content">
25        <div class="php8-logo">
26            <img src="/images/php8/logo_php8_1.svg" alt="php8.1" height="126" width="343">
27        </div>
28        <div class="php8-title"><?= message('main_title', $lang) ?></div>
29        <div class="php8-subtitle"><?= message('main_subtitle', $lang) ?></div>
30        <div class="php8-button-wrapper center">
31            <a class="php8-button php8-button_light" href="/downloads"><?= message('upgrade_now', $lang) ?></a>
32        </div>
33    </div>
34</section>
35
36<section class="php8-section center">
37    <div class="php8-compare">
38        <h2 class="php8-h2" id="enumerations">
39            <?= message('enumerations_title', $lang) ?>
40            <a class="php8-rfc" href="https://wiki.php.net/rfc/enumerations">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/language.enumerations.php"><?= message('documentation', $lang) ?></a>
41        </h2>
42        <div class="php8-compare__main">
43            <div class="php8-compare__block example-contents">
44                <div class="php8-compare__label">PHP &lt; 8.1</div>
45                <div class="php8-code phpcode">
46                    <?php highlight_php_trimmed(
47                        <<<'PHP'
48class Status
49{
50    const DRAFT = 'draft';
51    const PUBLISHED = 'published';
52    const ARCHIVED = 'archived';
53}
54function acceptStatus(string $status) {...}
55PHP
56
57                    );?>
58                </div>
59            </div>
60            <div class="php8-compare__arrow"></div>
61            <div class="php8-compare__block example-contents">
62                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
63                <div class="php8-code phpcode">
64                    <?php highlight_php_trimmed(
65                        <<<'PHP'
66enum Status
67{
68    case Draft;
69    case Published;
70    case Archived;
71}
72function acceptStatus(Status $status) {...}
73PHP
74
75                    );?>
76                </div>
77            </div>
78        </div>
79        <div class="php8-compare__content">
80            <?= message('enumerations_content', $lang) ?>
81        </div>
82    </div>
83
84    <div class="php8-compare">
85        <h2 class="php8-h2" id="readonly_properties">
86            <?= message('readonly_properties_title', $lang) ?>
87            <a class="php8-rfc" href="https://wiki.php.net/rfc/readonly_properties_v2">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/language.oop5.properties.php#language.oop5.properties.readonly-properties"><?= message('documentation', $lang) ?></a>
88        </h2>
89        <div class="php8-compare__main">
90            <div class="php8-compare__block example-contents">
91                <div class="php8-compare__label">PHP &lt; 8.1</div>
92                <div class="php8-code phpcode">
93                    <?php highlight_php_trimmed(
94                        <<<'PHP'
95class BlogData
96{
97    private Status $status;
98
99    public function __construct(Status $status)
100    {
101        $this->status = $status;
102    }
103
104    public function getStatus(): Status
105    {
106        return $this->status;
107    }
108}
109PHP
110
111                    );?>
112                </div>
113            </div>
114            <div class="php8-compare__arrow"></div>
115            <div class="php8-compare__block example-contents">
116                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
117                <div class="php8-code phpcode">
118                    <?php highlight_php_trimmed(
119                            <<<'PHP'
120class BlogData
121{
122    public readonly Status $status;
123
124    public function __construct(Status $status)
125    {
126        $this->status = $status;
127    }
128}
129PHP
130                    );?>
131                </div>
132            </div>
133        </div>
134        <div class="php8-compare__content">
135            <?= message('readonly_properties_content', $lang) ?>
136        </div>
137    </div>
138
139    <div class="php8-compare">
140        <h2 class="php8-h2" id="first_class_callable_syntax">
141            <?= message('first_class_callable_syntax_title', $lang) ?>
142            <a class="php8-rfc" href="https://wiki.php.net/rfc/first_class_callable_syntax">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/functions.first_class_callable_syntax.php"><?= message('documentation', $lang) ?></a>
143        </h2>
144        <div class="php8-compare__main">
145            <div class="php8-compare__block example-contents">
146                <div class="php8-compare__label">PHP &lt; 8.1</div>
147                <div class="php8-code phpcode">
148                    <?php highlight_php_trimmed(
149                        <<<'PHP'
150$foo = [$this, 'foo'];
151
152$fn = Closure::fromCallable('strlen');
153PHP
154                    );?>
155                </div>
156            </div>
157            <div class="php8-compare__arrow"></div>
158            <div class="php8-compare__block example-contents">
159                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
160                <div class="php8-code phpcode">
161                    <?php highlight_php_trimmed(
162                        <<<'PHP'
163$foo = $this->foo(...);
164
165$fn = strlen(...);
166PHP
167                    );?>
168                </div>
169            </div>
170        </div>
171        <div class="php8-compare__content">
172            <?= message('first_class_callable_syntax_content', $lang) ?>
173        </div>
174    </div>
175
176    <div class="php8-compare">
177        <h2 class="php8-h2" id="new_in_initializers">
178            <?= message('new_in_initializers_title', $lang) ?>
179            <a class="php8-rfc" href="https://wiki.php.net/rfc/new_in_initializers">RFC</a>
180        </h2>
181        <div class="php8-compare__main">
182            <div class="php8-compare__block example-contents">
183                <div class="php8-compare__label">PHP &lt; 8.1</div>
184                <div class="php8-code phpcode">
185                    <?php highlight_php_trimmed(
186                        <<<'PHP'
187class Service
188{
189    private Logger $logger;
190
191    public function __construct(
192        ?Logger $logger = null,
193    ) {
194        $this->logger = $logger ?? new NullLogger();
195    }
196}
197PHP
198                    );?>
199                </div>
200            </div>
201            <div class="php8-compare__arrow"></div>
202            <div class="php8-compare__block example-contents">
203                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
204                <div class="php8-code phpcode">
205                    <?php highlight_php_trimmed(
206                        <<<'PHP'
207class Service
208{
209    private Logger $logger;
210
211    public function __construct(
212        Logger $logger = new NullLogger(),
213    ) {
214        $this->logger = $logger;
215    }
216}
217PHP
218                    );?>
219                </div>
220            </div>
221        </div>
222
223        <div class="php8-compare__content php8-compare__content--spaced">
224            <?= message('new_in_initializers_content', $lang) ?>
225        </div>
226        <div class="php8-compare__main">
227            <div class="php8-compare__block example-contents">
228                <div class="php8-compare__label">PHP &lt; 8.1</div>
229                <div class="php8-code phpcode">
230                    <?php highlight_php_trimmed(
231                        <<<'PHP'
232class User
233{
234    /**
235     * @Assert\All({
236     *     @Assert\NotNull,
237     *     @Assert\Length(min=5)
238     * })
239     */
240    public string $name = '';
241}
242PHP
243                    );?>
244                </div>
245            </div>
246            <div class="php8-compare__arrow"></div>
247            <div class="php8-compare__block example-contents">
248                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
249                <div class="php8-code phpcode">
250                    <?php highlight_php_trimmed(
251                        <<<'PHP'
252class User
253{
254    #[\Assert\All(
255        new \Assert\NotNull,
256        new \Assert\Length(min: 5))
257    ]
258    public string $name = '';
259}
260PHP
261                    );?>
262                </div>
263            </div>
264        </div>
265    </div>
266
267    <div class="php8-compare">
268        <h2 class="php8-h2" id="pure_intersection_types">
269            <?= message('pure_intersection_types_title', $lang) ?>
270            <a class="php8-rfc" href="https://wiki.php.net/rfc/pure-intersection-types">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/language.types.declarations.php#language.types.declarations.composite.intersection"><?= message('documentation', $lang) ?></a>
271        </h2>
272        <div class="php8-compare__main">
273            <div class="php8-compare__block example-contents">
274                <div class="php8-compare__label">PHP &lt; 8.1</div>
275                <div class="php8-code phpcode">
276                    <?php highlight_php_trimmed(
277                        <<<'PHP'
278function count_and_iterate(Iterator $value) {
279    if (!($value instanceof Countable)) {
280        throw new TypeError('value must be Countable');
281    }
282
283    foreach ($value as $val) {
284        echo $val;
285    }
286
287    count($value);
288}
289PHP
290
291                    );?>
292                </div>
293            </div>
294            <div class="php8-compare__arrow"></div>
295            <div class="php8-compare__block example-contents">
296                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
297                <div class="php8-code phpcode">
298                    <?php highlight_php_trimmed(
299                        <<<'PHP'
300function count_and_iterate(Iterator&Countable $value) {
301    foreach ($value as $val) {
302        echo $val;
303    }
304
305    count($value);
306}
307PHP
308                    );?>
309                </div>
310            </div>
311        </div>
312        <div class="php8-compare__content">
313            <?= message('pure_intersection_types_content', $lang) ?>
314        </div>
315    </div>
316
317    <div class="php8-compare">
318        <h2 class="php8-h2" id="never_return_type">
319            <?= message('never_return_type_title', $lang) ?>
320            <a class="php8-rfc" href="https://wiki.php.net/rfc/noreturn_type">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/language.types.declarations.php#language.types.declarations.never"><?= message('documentation', $lang) ?></a>
321        </h2>
322        <div class="php8-compare__main">
323            <div class="php8-compare__block example-contents">
324                <div class="php8-compare__label">PHP &lt; 8.1</div>
325                <div class="php8-code phpcode">
326                    <?php highlight_php_trimmed(
327                        <<<'PHP'
328function redirect(string $uri) {
329    header('Location: ' . $uri);
330    exit();
331}
332
333function redirectToLoginPage() {
334    redirect('/login');
335    echo 'Hello'; // <- dead code
336}
337PHP
338
339                    );?>
340                </div>
341            </div>
342            <div class="php8-compare__arrow"></div>
343            <div class="php8-compare__block example-contents">
344                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
345                <div class="php8-code phpcode">
346                    <?php highlight_php_trimmed(
347                        <<<'PHP'
348function redirect(string $uri): never {
349    header('Location: ' . $uri);
350    exit();
351}
352
353function redirectToLoginPage(): never {
354    redirect('/login');
355    echo 'Hello'; // <- dead code detected by static analysis
356}
357PHP
358
359                    );?>
360                </div>
361            </div>
362        </div>
363        <div class="php8-compare__content">
364            <?= message('never_return_type_content', $lang) ?>
365        </div>
366    </div>
367
368    <div class="php8-compare">
369        <h2 class="php8-h2" id="final_class_constants">
370            <?= message('final_class_constants_title', $lang) ?>
371            <a class="php8-rfc" href="https://wiki.php.net/rfc/final_class_const">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/language.oop5.final.php#language.oop5.final.example.php81"><?= message('documentation', $lang) ?></a>
372        </h2>
373        <div class="php8-compare__main">
374            <div class="php8-compare__block example-contents">
375                <div class="php8-compare__label">PHP &lt; 8.1</div>
376                <div class="php8-code phpcode">
377                    <?php highlight_php_trimmed(
378                        <<<'PHP'
379class Foo
380{
381    public const XX = "foo";
382}
383
384class Bar extends Foo
385{
386    public const XX = "bar"; // No error
387}
388PHP
389
390                    );?>
391                </div>
392            </div>
393            <div class="php8-compare__arrow"></div>
394            <div class="php8-compare__block example-contents">
395                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
396                <div class="php8-code phpcode">
397                    <?php highlight_php_trimmed(
398                        <<<'PHP'
399class Foo
400{
401    final public const XX = "foo";
402}
403
404class Bar extends Foo
405{
406    public const XX = "bar"; // Fatal error
407}
408PHP
409
410                    );?>
411                </div>
412            </div>
413        </div>
414        <div class="php8-compare__content">
415            <?= message('final_class_constants_content', $lang) ?>
416        </div>
417    </div>
418
419    <div class="php8-compare">
420        <h2 class="php8-h2" id="explicit_octal_numeral_notation">
421            <?= message('octal_numeral_notation_title', $lang) ?>
422            <a class="php8-rfc" href="https://wiki.php.net/rfc/explicit_octal_notation">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/migration81.new-features.php#migration81.new-features.core.octal-literal-prefix"><?= message('documentation', $lang) ?></a>
423        </h2>
424        <div class="php8-compare__main">
425            <div class="php8-compare__block example-contents">
426                <div class="php8-compare__label">PHP &lt; 8.1</div>
427                <div class="php8-code phpcode">
428                    <?php highlight_php_trimmed(
429                        <<<'PHP'
430016 === 16; // false because `016` is octal for `14` and it's confusing
431016 === 14; // true
432PHP
433
434                    );?>
435                </div>
436            </div>
437            <div class="php8-compare__arrow"></div>
438            <div class="php8-compare__block example-contents">
439                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
440                <div class="php8-code phpcode">
441                    <?php highlight_php_trimmed(
442                        <<<'PHP'
4430o16 === 16; // false — not confusing with explicit notation
4440o16 === 14; // true
445PHP
446                    );?>
447                </div>
448            </div>
449        </div>
450        <div class="php8-compare__content">
451            <?= message('octal_numeral_notation_content', $lang) ?>
452        </div>
453    </div>
454
455    <div class="php8-compare">
456        <h2 class="php8-h2" id="fibers">
457            <?= message('fibers_title', $lang) ?>
458            <a class="php8-rfc" href="https://wiki.php.net/rfc/fibers">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/language.fibers.php"><?= message('documentation', $lang) ?></a>
459        </h2>
460        <div class="php8-compare__main">
461            <div class="php8-compare__block example-contents">
462                <div class="php8-compare__label">PHP &lt; 8.1</div>
463                <div class="php8-code phpcode">
464                    <?php highlight_php_trimmed(
465                        <<<'PHP'
466$httpClient->request('https://example.com/')
467        ->then(function (Response $response) {
468            return $response->getBody()->buffer();
469        })
470        ->then(function (string $responseBody) {
471            print json_decode($responseBody)['code'];
472        });
473PHP
474
475                    );?>
476                </div>
477            </div>
478            <div class="php8-compare__arrow"></div>
479            <div class="php8-compare__block example-contents">
480                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
481                <div class="php8-code phpcode">
482                    <?php highlight_php_trimmed(
483                        <<<'PHP'
484$response = $httpClient->request('https://example.com/');
485print json_decode($response->getBody()->buffer())['code'];
486PHP
487                    );?>
488                </div>
489            </div>
490        </div>
491        <div class="php8-compare__content">
492            <?= message('fibers_content', $lang) ?>
493        </div>
494    </div>
495
496    <div class="php8-compare">
497        <h2 class="php8-h2" id="array_unpacking_support_for_string_keyed_arrays">
498            <?= message('array_unpacking_title', $lang) ?>
499            <a class="php8-rfc" href="https://wiki.php.net/rfc/array_unpacking_string_keys">RFC</a> <a class="php8-rfc" href="/manual/<?= $lang ?>/language.types.array.php#language.types.array.unpacking"><?= message('documentation', $lang) ?></a>
500        </h2>
501        <div class="php8-compare__main">
502            <div class="php8-compare__block example-contents">
503                <div class="php8-compare__label">PHP &lt; 8.1</div>
504                <div class="php8-code phpcode">
505                    <?php highlight_php_trimmed(
506                        <<<'PHP'
507$arrayA = ['a' => 1];
508$arrayB = ['b' => 2];
509
510$result = array_merge(['a' => 0], $arrayA, $arrayB);
511
512// ['a' => 1, 'b' => 2]
513PHP
514                    );?>
515                </div>
516            </div>
517            <div class="php8-compare__arrow"></div>
518            <div class="php8-compare__block example-contents">
519                <div class="php8-compare__label php8-compare__label_new">PHP 8.1</div>
520                <div class="php8-code phpcode">
521                    <?php highlight_php_trimmed(
522                        <<<'PHP'
523$arrayA = ['a' => 1];
524$arrayB = ['b' => 2];
525
526$result = ['a' => 0, ...$arrayA, ...$arrayB];
527
528// ['a' => 1, 'b' => 2]
529PHP
530                    );?>
531                </div>
532            </div>
533        </div>
534        <div class="php8-compare__content">
535            <?= message('array_unpacking_content', $lang) ?>
536        </div>
537    </div>
538</section>
539
540<section class="php8-section center php8-section_light php8-columns">
541    <div class="php8-column">
542        <h2 class="php8-h2" id="performance_improvements"><?= message('performance_title', $lang) ?></h2>
543        <div class="php8-compare__content">
544            <div class="center">
545                <?= message('performance_chart', $lang) ?>
546                <div class="php8-chart__table">
547                    <img src="/images/php8/php81_performance.svg" alt="">
548                </div>
549            </div>
550            <h3 class="php8-h3"><?= message('performance_results_title', $lang) ?></h3>
551            <ul>
552                <li><?= message('performance_results_symfony', $lang) ?></li>
553                <li><?= message('performance_results_wordpress', $lang) ?></li>
554            </ul>
555            <h3 class="php8-h3"><?= message('performance_related_functions_title', $lang) ?></h3>
556            <ul>
557                <li><?= message('performance_jit_arm64', $lang) ?></li>
558                <li><?= message('performance_inheritance_cache', $lang) ?></li>
559                <li><?= message('performance_fast_class_name_resolution', $lang) ?></li>
560                <li><?= message('performance_timelib_date_improvements', $lang) ?></li>
561                <li><?= message('performance_spl', $lang) ?></li>
562                <li><?= message('performance_serialize_unserialize', $lang) ?></li>
563                <li><?= message('performance_internal_functions', $lang) ?></li>
564                <li><?= message('performance_jit', $lang) ?></li>
565            </ul>
566        </div>
567    </div>
568
569    <div class="php8-column">
570        <h2 class="php8-h2" id="other_new_things"><?= message('other_new_title', $lang) ?></h2>
571        <div class="php8-compare__content php8-compare__content--block">
572            <ul>
573                <li><?= message('other_new_returntypewillchange', $lang) ?></li>
574                <li><?= message('other_new_fsync_fdatasync', $lang) ?></li>
575                <li><?= message('other_new_array_is_list', $lang) ?></li>
576                <li><?= message('other_new_sodium_xchacha20', $lang) ?></li>
577            </ul>
578        </div>
579        <h2 class="php8-h2 php8-h2_margin-top" id="deprecations_and_bc_breaks"><?= message('bc_title', $lang) ?></h2>
580        <div class="php8-compare__content">
581            <ul>
582                <li><?= message('bc_null_to_not_nullable', $lang) ?></li>
583                <li><?= message('bc_return_types', $lang) ?></li>
584                <li><?= message('bc_serializable_deprecated', $lang) ?></li>
585                <li><?= message('bc_html_entity_encode_decode', $lang) ?></li>
586                <li><?= message('bc_globals_restrictions', $lang) ?></li>
587                <li><?= message('bc_mysqli_exceptions', $lang) ?></li>
588                <li><?= message('bc_float_to_int_conversion', $lang) ?></li>
589                <li><?= message('bc_finfo_objects', $lang) ?></li>
590                <li><?= message('bc_imap_objects', $lang) ?></li>
591                <li><?= message('bc_ftp_objects', $lang) ?></li>
592                <li><?= message('bc_gd_objects', $lang) ?></li>
593                <li><?= message('bc_ldap_objects', $lang) ?></li>
594                <li><?= message('bc_postgresql_objects', $lang) ?></li>
595                <li><?= message('bc_pspell_objects', $lang) ?></li>
596            </ul>
597        </div>
598    </div>
599</section>
600
601<section class="php8-section php8-section_dark php8-section_footer php8-footer">
602    <div class="php8-section__content">
603        <h2 class="php8-h2 center"><?= message('footer_title', $lang) ?></h2>
604        <div class="php8-button-wrapper center">
605            <a class="php8-button php8-button_light" href="/downloads"><?= message('upgrade_now', $lang) ?></a>
606        </div>
607        <div class="php8-footer__content">
608            <?= message('footer_content', $lang) ?>
609        </div>
610    </div>
611</section>
612
613<?php
614
615site_footer();
616