TubeSum ← Transcribe a video

What's new in PHP 8.4 (and 8.5) | Derick Rethans | phpday 2025

0h 40m video Transcribed Jun 21, 2026
Intermediate 10 min read For: PHP developers familiar with object-oriented programming and type system, interested in new language features and best practices.
38
Views
1
Likes
0
Comments
0
Dislikes
2.6%
📊 Average

AI Summary

Derek discusses new features in PHP 8.4 and previews upcoming additions in PHP 8.5, focusing on improvements to typing, property hooks, performance, and developer tooling. The talk covers asymmetric visibility, property hooks, new DOM parsing, a rewritten JIT engine, and several new functions for Unicode handling.

[0:41]
Asymmetric Visibility in PHP 8.4

PHP 8.4 allows asymmetric visibility for typed properties, enabling public reads and private/protected sets without explicit getters/setters. The 'set' visibility must be equal or higher strictness than 'get'.

[5:13]
Property Hooks

PHP 8.4 introduces property hooks (get/set) for typed properties, allowing logic to be attached directly to property access. Supports virtual properties (no backing storage) and actual properties with storage.

[10:05]
New on Construct Syntax

PHP 8.4 allows `new ClassName()->method()` without double parentheses, requiring parentheses after the class name to avoid ambiguity.

[11:04]
Pipe Operator (PHP 8.5)

PHP 8.5 may introduce a pipe operator for chaining function calls (e.g., `$value |> fn`), currently in voting, with restrictions on multiple-argument functions requiring closures.

[14:39]
HTML 5 Parsing

PHP 8.4 adds a new `DOM\HTMLDocument` class using an HTML 5 parser, separate from the old HTML 4 parser, allowing opt-in upgrade. Also fixes XML conformance in `DOM\XMLDocument`.

[17:52]
New JIT Engine

PHP 8.4 replaces the 8.0 JIT with a new one based on a custom intermediate representation, easier to maintain and support ARM CPUs. Performance gains are modest but maintainability improved.

[21:53]
Deprecated Attribute

PHP 8.4 adds a `#[Deprecated]` attribute for functions, methods, class constants, etc., triggering a deprecation warning when called. Accepts optional message and 'since' parameters.

[24:15]
No Discard Attribute (PHP 8.5)

PHP 8.5 introduces `#[NoDiscard]` attribute to warn when a function's return value is ignored, useful for immutable methods like `DateTimeImmutable::setDate()`.

[26:34]
PDO Subclasses

PHP 8.4 introduces driver-specific PDO subclasses (e.g., for MySQL, PostgreSQL) via `PDO::connect()` factory method, enabling driver-specific methods and types.

[30:05]
Grapheme Functions

PHP 8.4 adds `grapheme_str_split()` to split strings by grapheme clusters (user-perceived characters), handling emojis and diacritics correctly. PHP 8.5 adds `grapheme_levenshtein()`.

[33:15]
Deprecated Implicit Nullability

PHP 8.4 deprecates implicit nullable types (e.g., `function foo(Type $param = null)` now requires explicit `?Type` or `Type|null`).

[34:57]
Policy Changes

PHP project unified governance rules into a single document. Release cycle changed to 2 years normal support + 2 years security support, ends on Dec 31 of 4th year, fewer release candidates, and allows minor features in beta.

PHP 8.4 brings significant improvements to type system expressiveness, property handling, performance, and tooling, while PHP 8.5 previews further refinements. Developers should plan for the implicit nullability deprecation and explore new Unicode functions for better internationalization support.

Clickbait Check

95% Legit

"Title accurately reflects the content: a comprehensive overview of new features in PHP 8.4 and preview of PHP 8.5."

Mentioned in this Video

Tutorial Checklist

1 0:41 Use asymmetric visibility: declare `public string $name { private set; }` for public get, private set.
2 5:13 Attach logic via property hooks: `public string $fullName { get => $this->first . ' ' . $this->last; set => $this->first = explode(' ', $value)[0]; }`
3 10:05 Call method on new instance: `new ClassName()->method()` (require parentheses after class name).
4 14:39 Upgrade to HTML 5 parsing by using `DOM\HTMLDocument` instead of `DOMDocument`.
5 17:52 Enable JIT command: set `opcache.jit` (default is `disabled` in PHP 8.4; no manual action needed on upgrade).
6 21:53 Use `#[Deprecated('message', since: 'version')]` attribute to mark functions/methods as deprecated.
7 24:15 Apply `#[NoDiscard]` attribute to functions that must have their return value used (PHP 8.5).
8 26:34 Use `PDO::connect()` instead of `new PDO()` to obtain driver-specific PDO subclass.
9 30:05 Split strings by grapheme clusters: `grapheme_str_split($emoji)` for correct Unicode handling.
10 33:15 Fix implicit nullability: add `?` to type or `Type|null` for parameters with default `null`.

Study Flashcards (10)

What is asymmetric visibility in PHP 8.4?

medium Click to reveal answer

Allows typed properties to have different visibility for get and set, e.g., `public get` and `private set`, without explicit getters/setters.

0:41

What is the syntax to call a method on a new object in PHP 8.4?

easy Click to reveal answer

`new ClassName()->method()` (requires parentheses after class name).

10:05

What is the new HTML 5 parsing class in PHP 8.4?

easy Click to reveal answer

`DOM\HTMLDocument` in the `DOM` namespace.

14:39

How does the new JIT engine in PHP 8.4 improve over PHP 8.0's JIT?

hard Click to reveal answer

It is based on a custom intermediate representation, making it easier to maintain and support ARM CPUs.

17:52

What does the `#[Deprecated]` attribute accept?

easy Click to reveal answer

Two optional arguments: a warning message and a 'since' value (free-form text).

21:53

What is the purpose of the `#[NoDiscard]` attribute in PHP 8.5?

medium Click to reveal answer

Warns if the return value of a function is ignored.

24:15

How do you get a driver-specific PDO subclass in PHP 8.4?

medium Click to reveal answer

Using `PDO::connect()` instead of `new PDO()`.

26:34

What function splits strings by grapheme clusters in PHP 8.4?

easy Click to reveal answer

`grapheme_str_split()`.

30:05

What deprecation does PHP 8.4 introduce regarding nullable parameters?

medium Click to reveal answer

Implicit nullable types (e.g., `Type $param = null`) are deprecated; must use `?Type` or `Type|null`.

33:15

What is the new PHP release support cycle as of 2024?

medium Click to reveal answer

2 years normal support + 2 years security support, ending on Dec 31 of the 4th year.

34:57

💡 Key Takeaways

🔧

Property hooks introduced

Allows attaching get/set logic directly to property definitions, reducing boilerplate and improving code cohesion.

5:13
📊

JIT engine rewritten for maintainability

Modernizes PHP's JIT to be easier to maintain and support ARM CPUs, addressing previous platform limitations.

17:52
💡

Grapheme functions for correct Unicode

Enables proper handling of Unicode strings (emojis, composite characters) by splitting by grapheme clusters instead of bytes.

30:28
⚖️

PHP release cycle overhauled

Streamlines release process and aligns support end dates, reducing confusion and allowing minor features in beta.

34:57
💡

Implicit nullability deprecation

Alerts developers to a breaking change coming in PHP 9, requiring explicit nullable type declarations.

33:15

✂️ Creator Tools: Viral Hooks

AI-generated clip ideas for Shorts based on the transcript

PHP 8.4: No More Getter/Setter Boilerplate

51s

Shows a massive time-saver for developers by eliminating tedious getter/setter code, making it highly shareable among coders.

▶ Play Clip

Property Hooks: Cleaner Code in PHP 8.4

60s

Demonstrates a practical, real-world example of property hooks replacing old magic methods, which is both educational and solves a common pain point.

▶ Play Clip

PHP JIT: Is It Worth Keeping?

53s

Raises a controversial debate about the JIT compiler's actual performance benefit, sparking discussion among PHP developers.

▶ Play Clip

New #NoDiscard Attribute in PHP 8.5

51s

Introduces a simple but powerful attribute that prevents silent bugs, making it a must-know tip for clean code practices.

▶ Play Clip

PHP 8.4 Fixes Emoji Splitting Forever

45s

Solves a frustrating, long-standing issue with emoji and multibyte strings in a visually engaging way, perfect for viral tech content.

▶ Play Clip

[00:00] [Music]

[00:09] So, hi, I'm Derek. I'm European living

[00:11] in London. Um, we can talk about why I

[00:13] call myself European in a moment. Um, I

[00:16] work for the PHP Foundation partly. I

[00:18] also work on XDbook and I work on PHP

[00:22] datetime support. I am also Groot

[00:25] um without a G. I maintain a PHP.NET

[00:28] that infrastructure. I like maps, beer,

[00:30] and whiskey. It's irrelevant to the

[00:32] talk, but I thought I'd throw it out

[00:33] there. And if you want to have

[00:35] questions, you can find me on Macedon or

[00:37] here on the conference. That's all about

[00:40] me.

[00:41] So, I'm going to show quite a lot of

[00:43] code, quite a lot of old code and some

[00:45] new code that will not compile quite

[00:47] just yet in your versions of PHP.

[00:50] One of the bigger things in PHP 84 is

[00:53] the continuation of making

[00:58] typing better, making it easier for you

[01:01] to add bits of language to to your

[01:05] applications to not have to do lots of

[01:07] annoying stuff.

[01:09] Now, before P384, if you want to do any

[01:12] kind of uh public reads and private

[01:16] sets, you had to mark your property as

[01:20] private and you create a public gutter,

[01:23] right? That's a very common pattern that

[01:24] you see a lot. But it means you have to

[01:27] have cutters and sometimes also setters

[01:29] to do these things.

[01:32] Now in PG84 you don't have to do that

[01:34] anymore. You can now type these things

[01:36] immediately without having to create a

[01:38] get or setter which is kind of handy.

[01:40] There's a few concerns here. Um the

[01:43] first keyword is for getting. The second

[01:45] one is for setting but you also need to

[01:47] use the set in between. There's no get

[01:50] in between the parenthesis because this

[01:52] is a very common setting. You have a

[01:55] public get and a private or protected

[01:57] set. There's also a shortcut for that so

[02:00] that you don't have to use a public

[02:01] keyword. So this implies that it is

[02:04] public get. You can create any

[02:07] combination but the strictness of the

[02:09] set needs to be the same or higher than

[02:11] the getter. That sort of makes sense if

[02:14] you think of it. So you can't have a

[02:16] private get and a public set. It won't

[02:19] allow that. Again also not very useful.

[02:22] So this asmmetric visibility um is

[02:24] actually comes back in a few other

[02:26] things. There's a few things around

[02:27] this. So it only works with type

[02:29] properties. So you can't have a all the

[02:33] checks that PHP does for properties with

[02:35] access and things like that read only

[02:38] and stuff like that. are always only

[02:40] work on type properties because the

[02:43] untyped properties they are shortcuted

[02:45] in some other way. As I said the set

[02:48] visibility must be equal or less than

[02:50] the main get visibility. Um if you use

[02:53] weird array kind of things then that

[02:55] follows set visibility even though you

[02:57] might be sort of reading this kind of

[02:59] weird. Uh the same thing if you inherit

[03:01] properties they need to have the same

[03:04] time I mean type and you it is allowed

[03:09] to widen who can read and write to it.

[03:11] So you can just like you have a a

[03:13] private property in an inherited class

[03:16] you can make it a protected property you

[03:18] can also do it with a asymmetric

[03:20] visibility

[03:22] if you use private set it also makes

[03:24] your property final. There is some

[03:28] strange interactions happening with

[03:30] private properties in classes anyway

[03:32] because if you have an inherited class

[03:35] that redefineses your private property

[03:37] with the same name, they actually

[03:39] created as two private properties.

[03:41] They're sort of name space. It's not

[03:43] something you see unless you like far

[03:45] dump a an object or something like or

[03:47] you serialize it because you get some

[03:49] weird things with null characters in

[03:50] there. You might have seen that at some

[03:52] point. But this gets too complicated

[03:55] with the asmatic visibility. So PHP will

[03:58] now not allow you to re to have in an

[04:01] inherited class a property with the same

[04:03] name as in a class that you're

[04:04] inheriting. Um read only has been

[04:07] redefined from um private set sort of to

[04:12] protected set but still has this right

[04:14] runs responsibility. So if you use read

[04:16] only by default it will mean a protected

[04:19] set which made sort of sense. uh unless

[04:23] you mark it as private set yourself.

[04:25] Normally read only properties you can uh

[04:28] write to in any context that you can

[04:30] write to as a public property but that

[04:31] now changes as well with this change.

[04:36] Now PHP 85 not out yet. This has been um

[04:40] merged into the codebase but uh it will

[04:43] survive. I think it's pretty likely but

[04:45] you never know. is that before 85 you

[04:49] couldn't have the public and private set

[04:52] on constants

[04:54] um it's just left out for some reason

[04:58] now exact or sorry I should say class

[05:00] constants here now exactly why you would

[05:03] want to do that I don't know but

[05:05] sometimes we add things in new versions

[05:08] that we've forgotten about

[05:10] all right

[05:13] one of the other bigger things in PHP 84

[05:15] is property hooks so that sort of built

[05:17] on top of as asynchronous visibility but

[05:20] in a slightly different way. It

[05:22] basically allows you instead of having

[05:24] to define a setter and get a method to

[05:26] implement that logic directly when you

[05:29] define a property. So you get the code

[05:31] together. So basically what the syntax

[05:33] says here is that if I'm reading the

[05:35] null the full name property, it will

[05:38] return the value of this first

[05:40] concatenated with a space concatenated

[05:42] with the last name. Don't don't ever

[05:45] store names like this because names are

[05:47] way more complicated than first names

[05:48] and last names. But this is an example

[05:50] that was in the RFC.

[05:52] Same thing if you if you write to the

[05:54] full name property. If you attach a new

[05:56] value to it, then at first we'll get the

[05:59] value.

[06:01] This is a variable that is automatically

[06:05] introduced into the property hook. I

[06:06] haven't defined it here anywhere myself.

[06:08] And you also can't do that. it will

[06:11] explode it or split it by space and then

[06:13] write it to the first and last property

[06:16] and then we set is modified as true

[06:18] because why not?

[06:21] So there's an interesting interaction in

[06:23] here because first and last are actual

[06:25] properties. They are defined on the

[06:27] class. We have done that with a in a

[06:30] constructor here defined as properties.

[06:32] But a full name property isn't an actual

[06:35] property. uh if you would debug this uh

[06:39] an object with this class in XDbug, the

[06:41] full name property wouldn't show up

[06:43] because it is there's no storage

[06:45] attached to it. It's only a virtual

[06:47] property in a way that you can read and

[06:49] write to it. But there's nothing stored

[06:52] with this property.

[06:54] The moment you use a property name in

[06:56] either the getter or the setter, it will

[06:57] have to become an actual property with

[07:00] actual storage. So that's how PHP does

[07:02] that. Now I find this a little bit of a

[07:04] contrived example um but I actually

[07:08] found some use case in code that I've

[07:09] written a long time ago where these

[07:11] propertes are actually quite useful. So

[07:14] let's go back in time before we had um

[07:18] no typing in PHP whatsoever. So this is

[07:20] code that is written in 2003 long or

[07:23] 2004 maybe long long time ago where we

[07:25] already wanted to have some type

[07:27] enforcement of type and value um

[07:31] enforcement on properties that we're

[07:32] setting. And the way how you could then

[07:34] do that is by having the underscore set

[07:37] and also underscore get magic methods

[07:41] that would get triggered anytime you try

[07:43] to write to a property that doesn't

[07:44] exist. And the implementation that we

[07:46] then did so long ago is we had a

[07:49] specific property called properties that

[07:51] would then store these actual properties

[07:54] as an array element. And because this is

[07:56] protected or in sometimes private you

[07:58] couldn't directly read and write to

[07:59] this. So the way how we would do typing

[08:02] for um a property setting in this case

[08:05] UID referencing it's something uh email

[08:08] related we would check when you write to

[08:11] this in this get method whether the

[08:14] value is a boolean and if it's not a

[08:16] boolean we throw a value exception

[08:20] PHP of course has its own value

[08:22] exceptions now um and if it works we

[08:25] just set it as a value now of course

[08:28] when we got type properties in PHP tree,

[08:30] you can rewrite this to something like

[08:32] this, right? You can just set the type

[08:34] directly on a property. But there was a

[08:37] few other cases as well like for the

[08:39] list limit property, we wanted to make

[08:41] sure it's an integer, which we can do

[08:42] with this type definition, but we also

[08:45] wanted to make sure it is larger than

[08:46] zero or zero or larger I should say. And

[08:50] that is something you couldn't do in PHP

[08:51] yet because you could only enforce the

[08:53] type. So with PHP 84, you can now

[08:56] rewrite this. So we check for the

[08:58] whether it's a number and whether the

[09:00] value is larger than zero. You can do

[09:03] that now in your set property.

[09:06] So set gets called with uh the value and

[09:09] if the value is smaller than zero then

[09:11] we can throw these value errors yourself

[09:13] and then of course when the moment you

[09:14] throw an exception things will stop. Um

[09:18] the type itself we don't have to check

[09:20] with is int anymore. Of course you can

[09:21] type that directly on the property.

[09:25] So set and get property hooks are

[09:27] actually kind of useful. Uh they also um

[09:30] cause the bug on XD debug because XD

[09:33] debug checks where you have lines of

[09:35] code that you can run and it was only

[09:37] familiar with functions or methods or

[09:39] files. But this is now an additional

[09:42] type of function or an additional

[09:45] location where you can have code. Xbook

[09:48] didn't know about it. So if you would

[09:49] set a breakpoint in these things, it

[09:51] would sometimes refuse to set a

[09:53] breakpoint because it didn't know there

[09:55] was actual code on there. That's now

[09:56] fixed with the release that I made

[09:58] yesterday. So you should not be able to

[10:00] have to run into that now.

[10:03] All right, next one.

[10:05] How often have you written code like

[10:07] this where you create a new object and

[10:09] then you have to have the double

[10:10] parenthesis because you couldn't call uh

[10:14] an a method on this directly. PHP84. You

[10:17] don't have to do that anymore. Yay.

[10:20] However, you do have to specify the

[10:23] parenthesis after your class name.

[10:25] Normally, if you do new class, you don't

[10:28] have to use a parenthesis. But if you

[10:29] want to use this syntax, then you do

[10:31] have to do that. Otherwise, there's an

[10:32] ambiguity in in the PHP language. Now,

[10:36] this works not only for direct methods,

[10:38] it also works for all of the other

[10:39] things that you can do. Um, again, I

[10:42] copied this from the RFC just to show

[10:44] you that it works everywhere. Uh there's

[10:46] some weird things in PHP sometimes like

[10:48] this line.

[10:50] Does anybody write code like that?

[10:54] Yeah, there's always one. Uh so I Yeah,

[10:57] please don't do stuff like that.

[11:00] Unless it's generated code, I suppose.

[11:04] Right now, this is a PHP 85 kind of

[11:08] thing. So earlier we could already have

[11:11] constant expressions. they were

[11:12] introduced in PHP4 where you could have

[11:14] an expression in in in this case in a

[11:16] default value right so I have string

[11:19] input and then array callbacks that has

[11:21] a default value that has the closures in

[11:25] it but this wasn't allowed yet in PHP85

[11:28] this is some so this is something that's

[11:29] going to be newly allowed in PHP85 but

[11:32] there's some restrictions to this like

[11:34] these functions so if it's a method it

[11:36] has to be a static method if it's a

[11:39] function they can also not rely on

[11:42] anything from outside the scope because

[11:43] they have to be static pretty much. That

[11:47] also means that the values

[11:49] cannot rely on either using things like

[11:52] use because that would have to copy

[11:54] something in from the scope where you uh

[11:56] running it or can you use short closures

[11:59] because that automatically takes at the

[12:02] outside scope into what you call it. So

[12:04] you can only do that with uh things like

[12:06] S3 lower. I mean this is an example here

[12:08] where I basically have a string like

[12:11] hello world and then I do a few steps to

[12:15] um first lowerase it then replace all

[12:18] the non letters with a dash

[12:21] remove the dashes on the outside and

[12:23] then replace all the double dashes with

[12:26] a single dash those are the four steps

[12:28] that I'm doing here right this code

[12:31] isn't particularly very readable would

[12:32] you agree

[12:34] however PHP 85 five, we might get the

[12:38] pipe operator which would allow you to

[12:40] do things like this which is a lot lot

[12:42] shorter. I mean it's not the example

[12:45] isn't quite 100% the same but is a lot

[12:47] lot shorter. When I just checked this uh

[12:50] it's currently in voting it was 264 and

[12:53] five against something like that. So

[12:55] there's a good chance that we'll make

[12:56] that into the language.

[12:59] Um again there's a few restrictions

[13:01] here. The way what how this works is

[13:03] like the value on the left hand side

[13:05] gets put as the first argument into the

[13:08] function on the or the code on the right

[13:11] the expression on the right hand side.

[13:13] So s to lower how many arguments does

[13:16] accept except one argument.

[13:19] things like prerec replace accepts

[13:21] multiple arguments and because it

[13:23] accepts multiple arguments you cannot do

[13:26] that directly because it wouldn't know

[13:28] where to place the variable or the

[13:30] input. So in these cases you'd have to

[13:33] wrap it in a short closure that I'm

[13:34] doing here just to be able to make sure

[13:37] that the x that the short closer gets

[13:39] gets put into the the right location in

[13:42] the u in the call itself. This also

[13:45] works for static methods or any other

[13:47] closure that you have. It isn't uh you

[13:49] don't have to spell it out like I'm

[13:50] doing here. I think this is kind of

[13:53] useful. Uh I think it's a good new

[13:55] addition and I'm pretty sure it will

[13:57] make it into the language as you go. I

[14:00] ordered the slide when I was listening

[14:01] to Roman's presentation.

[14:03] Right. But there's a few other things in

[14:06] here as well like um

[14:08] I put them the wrong way around. That's

[14:10] why I got confused. So in this case here

[14:13] I'm using the static functions and stuff

[14:14] like that. But here I'm also allowing um

[14:19] the dot dot dot operator which turns

[14:21] this into closure directly. That is

[14:23] something that you couldn't do in PHP 84

[14:25] either but that is something that is new

[14:26] for 85 as well

[14:31] and of course with restrictions that

[14:34] they must be freestyling functions or

[14:36] static methods.

[14:39] PHP84 introduced parsing HTML HTML 5 to

[14:43] be precise. Have any have you ever used

[14:46] the DOM extension in PHP to parse HTML?

[14:50] Pretty sure

[14:52] it's actually fairly problematic because

[14:54] how many websites are still using HTML

[14:56] 4? It's mostly HTML 5 now, right? And

[15:00] PHP's parser didn't have an HTML 5

[15:03] parser. And if you write conforming HTML

[15:06] 4 or 5, then this is usually not a

[15:08] problem. But the way how HTML 4 and HTML

[15:11] 5 resolve inconsistencies in what you've

[15:13] written. How does it handle when you

[15:15] don't have a closing tag? These are

[15:17] different. The rules for handling these

[15:20] are different which can cause some

[15:23] issues. If you want to parse HTML to

[15:26] make sure that it's conforming, then you

[15:28] might get the wrong answer and that

[15:29] could introduce security issues in some

[15:31] form I suppose as well. Now, so we

[15:34] looked at an 84 to see whether we can

[15:37] replace the parser that is part of the

[15:39] DOM extension of lip XML the library

[15:41] underneath to see whether we can make

[15:44] that HTML 5. But the library that PHP

[15:47] uses doesn't support that. So no, we

[15:50] can't do that. Also we are thinking

[15:52] switching the parser from HTML 4 to HTML

[15:54] 5 without letting you know is also not a

[15:58] great idea as an understatement. So the

[16:01] plan came uh out of that that we find a

[16:04] new library that can parse HTML um and

[16:07] then create a a wrapper around that that

[16:11] you have to opt into.

[16:14] So we created a new namespace the DOM

[16:17] namespace and we put in there the

[16:19] abstract class document which is

[16:21] basically what the original DOM document

[16:23] class was and then there is a XML

[16:26] document in the namespace and an HML

[16:28] document in that namespace that's um the

[16:32] HTML specific one then will use an HTML

[16:34] 5 parser whereas if you would use the

[16:37] normal DOM or DOM HML document I

[16:39] actually don't even remember what it's

[16:40] called now would still use the old HTML

[16:43] 4 parser.

[16:44] Which means if by changing a line in

[16:46] your code by going from DOM document to

[16:48] DOM/ document or actually DOM/HMTML

[16:52] document uh that's the only thing you

[16:54] need to change to upgrade from a HML 4

[16:57] parser to an HML 5 parser

[16:59] to be consistent in the same name space

[17:02] we also created the XML document class

[17:05] and originally that didn't do anything

[17:07] except for basically going to the class

[17:10] that already existed but we found out

[17:13] that Actually the XML pars in PHP also

[17:15] wasn't quite conforming to standards. It

[17:18] was missing uh the way how it handles

[17:20] properties and there was some function

[17:21] calls missing and some behavior was

[17:23] missing. But this also something we

[17:25] could now fix because by creating this

[17:28] extra class in this name space. It means

[17:31] that

[17:34] we can fix all these things in there and

[17:35] then you as a user can opt in into using

[17:37] this fixed behavior. So that also uh

[17:40] makes it possible to introduce new

[17:42] functionality without breaking existing

[17:44] functionality which is something that we

[17:46] always try to do not always succeed but

[17:49] always try to do

[17:52] right PHP 80 head just in time compiler

[17:56] it make everything

[17:59] very slightly faster

[18:02] um

[18:04] it's it I would call the one and 80 a

[18:07] experiments And I'm not quite sure how

[18:09] successful the experiment was. The way

[18:12] what it does, what a JIT engine or JIT

[18:14] compiler does. It takes your PHP code

[18:18] that gets changed into an abstract

[18:20] syntax tree. We call them a because

[18:22] that's a lot easier to pronounce. Uh

[18:25] this a can convert it into an internal

[18:28] structure. We call it bite code or op

[18:29] codes. And that the JIT engine if it

[18:32] sees that specific functions or parts of

[18:34] code has been used a lot will compile

[18:36] that directly to something that runs

[18:38] directly on your CPU. And of course that

[18:40] runs a lot faster or so you hope. Turns

[18:44] out PHP is actually a really quick

[18:46] language to begin with and because this

[18:49] JIT compiler can only do that for bits

[18:52] of code that are just PHP code. The

[18:54] moment you call a PHP function or an

[18:56] internal function or function of V

[18:58] itself, it needs to come out of this jet

[19:00] mode and then when you run PHP code

[19:02] again, it needs to come back in again.

[19:04] So that overhead always, well, not

[19:06] always, but mostly negated

[19:09] any time where um where the JIT engine

[19:13] could provide you with some useful

[19:15] performance boosts. The only real place

[19:17] where it actually helped a lot is if you

[19:19] had a bit of code that did algorithms

[19:21] that didn't really call any other

[19:23] functions, which is not something that

[19:25] happens a lot.

[19:27] So the JIT engine gave a little bit of a

[19:29] speed boost, but you probably wouldn't

[19:32] really notice it to be honest. Now

[19:34] there's also an issue that it was

[19:35] specifically written for Intel CPUs and

[19:38] now most of the new Macs are armed

[19:41] machines and you see that more in cloud

[19:43] environments as well. And in order to

[19:46] all the support for that they basically

[19:47] had to rewrite the whole thing again

[19:49] which is not great because anytime you

[19:51] want to support a new CPU type you'd

[19:53] have to redo all the work. So in PHP84,

[19:56] Dmitri worked on a new JIT engine based

[20:00] on a different framework that he also

[20:03] wrote

[20:04] uh intermediate representation which is

[20:06] basically an a for

[20:09] uh converting the bite code to CPU code

[20:12] and by implementing a different backend

[20:15] for this code, it was much easier to

[20:17] target different

[20:19] CPUs later on. A lot easier to do.

[20:24] Now, this replaces the JIT and PHP 80.

[20:27] You're not going to notice it because it

[20:29] works exactly the same, although you

[20:31] might get slightly different bugs. Bugs

[20:33] happen. It's also a bit faster, but it

[20:36] also has at least the opportunity to get

[20:39] rid of or improve on some of the u

[20:42] issues that the original 8.0 jet engine

[20:45] had where it is easier to to add

[20:49] optimizations for for for calling

[20:51] functions and stuff like that. Now that

[20:53] work has never happened. So the

[20:55] performance boost of the new JIT engine

[20:58] as you call it wasn't much more either

[21:00] but it was at least a lot easier to

[21:02] maintain for us. We also changed how you

[21:05] enable it. Instead of setting the memory

[21:07] usage from zero to a number you now need

[21:09] to the default for opcast.jit is disable

[21:13] instead of enable with no memory was a

[21:16] bit old. Um it's still part of the

[21:19] opcache extension. So if you're using

[21:22] this, you upgrade from PHPA3 to HTV4,

[21:24] you don't really have to do anything. It

[21:26] will just work out of the box.

[21:28] Now, as Roman indicated in the talk,

[21:30] because the JIT engine, not very many

[21:32] people know how it works, and it doesn't

[21:35] really provide a lot of performance. We

[21:38] actually not sure whether it's worth

[21:40] keeping um because it does introduce a

[21:44] whole different code in the engine that

[21:46] also needs maintaining

[21:48] um and can have its own box sometimes.

[21:51] All right, back to some lighter things.

[21:53] We now get the deprecated attribute

[21:58] uh which is an attribute you can set on

[21:59] functions on methods on class constants

[22:02] or everything. And when you use that,

[22:04] PHP will warn you when this function

[22:06] gets called or the code gets loaded that

[22:10] this function or whatever other element

[22:12] is deprecated.

[22:14] The attribute takes two arguments. They

[22:16] are both sort of free form. The first

[22:18] one is basically your error message or

[22:20] your warning message. And the second

[22:22] one, the since argument is basically a

[22:25] way of you

[22:27] describing since when this deprecation

[22:29] happens. But the value that I've used

[22:31] here the 2.4 is free form text. So you

[22:34] can do whatever you want. So in this

[22:36] case when you then wrote this run the

[22:38] test three meth fun function you get

[22:41] this error message. As I said you can

[22:43] also do this on other things. You can do

[22:44] this on class constants. You can do it

[22:46] on methods um and a bunch of other

[22:49] elements and so on. I think this is kind

[22:52] of a neat way than having to use a doc

[22:55] block with deprecated in it that then

[22:57] your static analysis exon this is now

[23:00] supported in the engine which is kind of

[23:02] nice I think to have but it's a small

[23:05] feature.

[23:07] Oh yeah, you can also do it on emnum

[23:08] cases. I forgot about that. I said that.

[23:12] Now PHP 85 extends this um attribute

[23:16] system that you can also set attributes

[23:18] on constants. I'm not talking about

[23:20] class constants here uh but normal

[23:23] constants. Again, who still uses global

[23:26] constants? Not very many. But for some

[23:28] reason, we had forgotten to add

[23:30] attribute support for that in PHP when

[23:32] we introduced them. H5 now allows you to

[23:35] do this kind of thing.

[23:37] useful? Yes. Groundbreaking? No.

[23:40] You can't do it in these cases. It only

[23:42] works if you use the con keyword. Not if

[23:44] you have multiple constants in the same

[23:48] statement or it also doesn't work if you

[23:50] call define because in this case you set

[23:52] the attribute on the fine but you're not

[23:54] declaring the fine. So that makes no

[23:55] sense. It doesn't do it.

[23:58] Scandalous. Yes. I'm sure

[24:02] we also add this new uh element to

[24:04] attribute so that you can now also

[24:06] target a constant but

[24:09] PHP85 introduces however another

[24:12] attribute. Uh this

[24:15] has been merged into the codebase which

[24:17] is the no discard attribute.

[24:20] Basically, this tells the engine that if

[24:24] a function that has its attribute set

[24:27] returns something and then the function

[24:30] that calls it doesn't look at a return

[24:33] value and in that case you'll get a

[24:37] warning. So basically it tells you that

[24:40] if you call a function with this it must

[24:43] return something.

[24:45] So as an example um it was mostly

[24:49] introduced for userlander but there's a

[24:50] few situations in PHP where you also

[24:54] call a function and you need to do

[24:56] something with a result otherwise

[24:57] nothing happens right if you have the

[24:59] original date class if you call set date

[25:02] on it then it modifies the object so

[25:05] that's fine but if you use date time

[25:06] immutable it returns the new object so

[25:09] if you don't do anything with the result

[25:11] here you basically throw that

[25:12] modification away because we internally

[25:15] now this no discard attribute you now

[25:18] will get a warning for this. Yeah. And

[25:20] of course you can do this in your own

[25:21] codebase as well for the things where it

[25:23] is important that the result something

[25:25] either it's important that you do

[25:27] something with it or it's important that

[25:29] um if you have code like this to make

[25:32] sure that um you're not inadvertently

[25:36] doing something or not do something that

[25:38] you're supposed to do kind of things. I

[25:40] think it's a little small feature to add

[25:42] to the language.

[25:45] Right.

[25:46] You can dis you can discard the discard

[25:49] attribute by using a void cast. Um if

[25:52] you really want to ignore this.

[25:56] Why you would want to do this? I don't

[25:58] know. Uh hopefully at some point our

[26:00] compiler gets clever enough to just

[26:02] remove this whole call to set data

[26:04] because it has no side effects.

[26:07] Uh so you can't use this card uh when

[26:10] the function is tied with a void or

[26:12] never return types because it makes no

[26:13] sense. Uh for magic methods including

[26:16] the constructor that require voids

[26:18] there's also the wake up and sleep and

[26:20] stuff like that or have no return type

[26:23] at all. You can also not use it there.

[26:24] You get an an error and you can also not

[26:27] use no discard on property hooks because

[26:29] that makes no sense,

[26:32] right? Discard.

[26:34] PHP84 introduces PDO subclasses

[26:38] and subclasses are basically a way of

[26:41] making sure that well if you do PDIO or

[26:44] new PDIO the object that you get back is

[26:46] a PDO object because you should do new

[26:48] object or so new class name so you have

[26:51] to return an object of that name

[26:53] otherwise it makes no sense

[26:56] but there are so many different PDO

[26:58] drivers like the my squ the the

[27:01] postquest squ the whatever other

[27:04] Firebird, OBBC ones, escalite, they all

[27:07] have slightly different behavior. They

[27:09] have different methods that work on

[27:10] them. They sometimes have different

[27:12] constants or or methods that don't

[27:15] exist right?

[27:17] And accessing these from a generic

[27:20] object makes not a lot of sense because

[27:22] calling get warning code when you're

[27:24] using post the driver would then have to

[27:26] check that and then throw an exception

[27:28] itself where actually this method really

[27:31] shouldn't exist on the PDO object in

[27:34] that case but that also you can't do

[27:36] because an object is an object right so

[27:38] 84 introduces subasses for each of the

[27:41] different PDIO drivers and on these

[27:43] drivers or on these subasses we then

[27:46] have to find the methods that would only

[27:48] work for the driver. Now, we still can't

[27:51] return those when you do new PDO because

[27:53] that has to return a PDO object. But

[27:56] there's now a new static method or

[27:58] factory method, however you want to call

[28:00] those, called PDO connect. You give that

[28:02] your your DSN, your your connection

[28:04] string as you did before. And that then

[28:07] will automatically return a subclass of

[28:09] PDIO that um implements this um that is

[28:14] of the correct subtype

[28:17] um which is kind of nice to have and if

[28:20] it returns the wrong one then you can do

[28:22] something with it if you wish to do

[28:23] that.

[28:25] Let's say Arizona obviously this should

[28:27] never happen but you never know.

[28:31] PDO subasses are kind of useless. So,

[28:33] now we're going to look at some language

[28:35] thing. So, we have an emoji, right? It's

[28:38] the shrug shrugging man emoji, I think.

[28:42] Uh, what do you think the output of this

[28:44] is? So, I'm going to split this emoji

[28:48] into the different characters. What's

[28:50] going to come out of this? Someone

[28:52] should shout out. Yeah. Moji baka. Yeah.

[28:55] Would you want to explain what moji baka

[28:57] is?

[29:01] Like this. Yeah, that's it. Yeah, that's

[29:04] it. Because PHP's internally only knows

[29:07] about bytes. So, the only way how it can

[29:10] split up an emoji is in these 12 bytes,

[29:14] which is not what you want, and you get

[29:16] weird question marks.

[29:18] So, of course, everybody knows here that

[29:20] PHP has better functions for this called

[29:23] multibite strings, right? What is going

[29:25] to be the output of this? Anyone want to

[29:27] shout out?

[29:29] is not quite moji baki

[29:32] but it is not what you would expect. You

[29:35] would expect to get one character out of

[29:36] it but no you get four out of it.

[29:39] So you get a generic emoji for person

[29:42] shrugging. Then there is one for the

[29:45] color of the skin which renders as

[29:48] nothing whether it's masculine or

[29:50] feminine. And then there is a weird

[29:52] combining combining one that I actually

[29:54] don't remember what it does. But this is

[29:56] still not what you want, right? If you

[29:58] want to iterate over characters, this is

[30:00] not what you want to get out of it. You

[30:02] want to get out of it is a single

[30:03] character. So PHP84 introduces a new

[30:05] function called you can guess called

[30:08] graffine string split. So the graphine

[30:11] subset of functions in the language,

[30:12] they are part of the intel extension

[30:14] which does all your fancy uni code

[30:17] things correctly. So please use these

[30:20] instead of MB string. Anyone wants to

[30:23] guess what comes out of this one?

[30:26] Just a single character emoji. Right. So

[30:28] this is PHP84. PHP85. Oh yeah, it also

[30:31] works for other weird characters. So my

[30:34] my browser actually doesn't render this

[30:36] hello correctly because this accent and

[30:38] this accent are actually on the A. So I

[30:41] guess that's a bug in Firefox or the

[30:42] library that it uses. So if you run

[30:44] this, you get the right things out of

[30:47] it. So it knows that the A is a

[30:49] character and also the A with all the

[30:51] accents on top is also considered a

[30:53] single character and then the French

[30:55] flag is a single character.

[30:57] I'm not sure why I picked the French

[30:59] flag and not the Italian one, but

[31:02] now there's also a way how to check

[31:06] differences between different versions

[31:08] of strings. So in this case, my name is

[31:10] Derek. It is not Derek with two Rs or

[31:12] Derek the Dutch way of the name or any

[31:15] of the 17 variations that I've seen in

[31:17] my life. So the Levenstein function is a

[31:21] way of getting out of there a value that

[31:24] represents the difference

[31:28] in definition by some algorithm between

[31:30] the between those two strings. So if you

[31:33] do that with just the names it will

[31:36] basically for each deletion of of

[31:38] character or rep replication of or

[31:41] insertion it will add one to the

[31:43] distance. If you want to see a little

[31:45] bit better how that works you can

[31:46] actually give weights to the deletion

[31:49] replacement and insertion and by nicely

[31:51] using base 10 here you actually can then

[31:55] figure out what differences are. So in

[31:57] this case, if I use this with Derek and

[31:59] Derek, you see that there are no letters

[32:02] inserted. We can see that there's been

[32:04] one replacement, which is the C for the

[32:07] R, and there's been two letters removed,

[32:10] which is the D and the R.

[32:13] Kind of useful to have, but what happens

[32:15] if you have two flags there, two emojis,

[32:18] right? If you call Leenstein on this,

[32:21] what what would you expect the answer to

[32:23] this would be? What would you hope it

[32:26] would say?

[32:29] Just ignoring the person sitting in

[32:30] front there. But no, what would you

[32:33] expect? I mean, what changes is one

[32:35] character that changes, right? But

[32:37] that's not what the answer is. The

[32:38] answer is two out of this because if you

[32:42] look at the bytes, there are two bytes

[32:44] that are different. And these bytes

[32:46] represent the letters that spell out the

[32:49] U and the A. So, and the P and the A in

[32:51] this case or P and the S in this case.

[32:53] So if you look at this the the

[32:55] replacements are these two bytes that

[32:58] switch. We don't want that. You can

[33:00] guess what comes next. PHP85 introduces

[33:03] a graphine Levenstein function. I

[33:04] misspelled it. There's an extra H in

[33:06] there. Um and of course then the answer

[33:09] is one because that's what you want to

[33:10] get out of this.

[33:13] I like languages.

[33:15] All right. Some other stuff that you

[33:17] probably won't like. Um PHP 8.4 before

[33:21] we deprecated the implicit nullability.

[33:24] So if you would set a default value as

[33:26] null then the type for options would be

[33:30] RST options in this case or null in

[33:34] PHP84 that will now throw a deprecation

[33:36] warning. It will tell you sorry that's a

[33:40] bit too small implicitly marking

[33:41] parameter options as nullable as

[33:43] deprecated. So how do you fix this? Yes,

[33:47] you ask the question mark in front of

[33:49] the type or you replace it with or null.

[33:55] Now this uh in my old PHP 53 code this

[33:59] caused some problem because this is the

[34:00] style that we had adopted everywhere.

[34:03] Also it is from what I remember

[34:05] Symphonies adopted that as their coding

[34:07] standard for describing nullable types.

[34:11] So they had to change their coding

[34:12] standard for that. Sorry, it happens.

[34:16] Now, however, so far this is a

[34:17] deprecation. It doesn't mean that the

[34:19] functionality doesn't work. Deplications

[34:21] in PHP basically means like in our next

[34:24] major version, we're going to change

[34:26] this functionality or remove it. So,

[34:28] this basically heads up for you that at

[34:30] some point when PHP 9 gets released,

[34:32] which is not going to be this year

[34:35] because we settled on PHP 85 by now.

[34:38] Could it be next year? Yeah. Uh or not?

[34:42] I don't know. I can't say but it's

[34:44] basically a way of you for knowing that

[34:46] look at this bit of code and you

[34:48] probably should change it

[34:50] and it's not hard to change this because

[34:52] you just need to ask a question mark

[34:55] right

[34:57] I've spoken about code now but we also

[34:59] need to talk a little bit about policies

[35:02] PHP's

[35:04] functionality gets introduced by

[35:06] something we call RFC's requests for

[35:09] comments or requests for code whatever

[35:12] you fancy see at a certain time of the

[35:13] day.

[35:15] But that is also the way how we uh do

[35:18] governance of the project, how we do

[35:19] releases, how we decide what can be in

[35:23] RFC, what our support time frames are

[35:26] and stuff like that. But all the rules

[35:29] for all of these things were are only in

[35:32] these RFC's.

[35:34] So if you wanted to look up on how

[35:35] exactly we do release management or how

[35:38] releases are made or what can be in a

[35:40] release or not that was separated in

[35:42] four or five different documents which

[35:44] is a pain in the bum if you need to

[35:46] figure out what is actually the current

[35:49] rule set. So we worked on a a little

[35:51] project that would conflate all these

[35:53] RFC's and put them in one one document

[35:56] as a first step and then after that we

[35:58] sort of rewritten all of these documents

[36:01] to make them useful and readable and now

[36:04] anytime we want to change any of the

[36:05] policies the RFC that changes the policy

[36:10] is a pull request to the policy. So it

[36:12] all becomes into one document. It's a

[36:14] lot easier to read than finding

[36:16] information in many different things.

[36:18] Now one of the policies that we changed

[36:20] about release management is oh you can

[36:23] find them here is the release cycle in

[36:25] PHP. So PHP for a long long time we'd

[36:29] have two years of normal support bug fix

[36:32] support and then one year of uh security

[36:35] fixes right we always had three alpha

[36:38] releases three beta releases and six

[36:40] release candidates. So each of these

[36:43] takes two weeks.

[36:45] That makes 24 weeks of time when you

[36:48] can't actually add new functionality to

[36:50] PHP, which is more than a third of the

[36:52] year, which is not great.

[36:58] I don't think it's great.

[37:01] We also had some weird languages about

[37:03] no minor features in beta releases and

[37:06] stuff like that. or we could introduce

[37:08] minor features in bug fix releases which

[37:11] is things that no none of you actually

[37:13] liking and also we would end support for

[37:16] version exactly 3 years after it was

[37:19] initially released. So if PHP 80 was

[37:22] released on November 17th, 20,

[37:28] there's a slide, my next slide says so,

[37:30] then the support would end November

[37:32] 17th 2023.

[37:34] Um, which is kind of annoying because

[37:36] it's always a different date. So what we

[37:39] did immediately in effect, so this

[37:42] covers everything, every PHP release

[37:44] that was already out there. We do two

[37:46] years of support and two years of

[37:47] security support with some caveats. We

[37:50] do two fewer release candidates.

[37:53] Nobody tested the release candidates

[37:54] anyway. So we can save a month of work

[37:57] here sort of. So we don't we now allow

[38:00] new minor features in beta releases, but

[38:03] no longer in bug fix releases and

[38:05] release candidates. And the support ends

[38:07] at the end of the fourth year. So that

[38:10] means December 31st. In a graph, it

[38:13] looks like this. So we introduced this

[38:15] somewhere in 2024. But at that point,

[38:18] um, PHP 81 was still in normal support

[38:22] in security support. So we extended that

[38:23] with a year. PHP 800 had already come

[38:26] out of support. So that did not get did

[38:28] not get extended. Uh, also today is not

[38:31] May 4th, but today is May 15th. I wrote

[38:34] a slide on May 4th. the slide the

[38:35] screenshot. So I think this actually

[38:37] kind of useful. Now at some point in the

[38:40] future we might have to make changes to

[38:42] this again uh due to regulation.

[38:45] Regulation is starting to impact open

[38:47] source project more and more. And

[38:50] there's in the EU there's a cyber

[38:51] resilience act that Roman sort of

[38:53] mentioned up front as well. Uh P3

[38:56] Foundation is

[38:58] helping to write guidelines around that

[39:00] and hopeing to influence politicians.

[39:02] It's not easy to do. uh but that might

[39:05] stipulate that we might have to do five

[39:07] years of security support in some way or

[39:10] in some form. We don't exactly know what

[39:12] those guidelines are going to be but

[39:14] that is something that can influence um

[39:18] um yeah politicians can influence open

[39:21] source now and there will be more of

[39:23] that as all right slides are going to be

[39:27] up there or probably are already up

[39:29] there. If you have questions feel free

[39:31] to email me. I'm terrible answering

[39:33] email, but I will eventually answer them

[39:36] at some point in the next year. I'm not

[39:38] that bad. But slides there. If you have

[39:41] questions come

[39:43] feel free to find me during the

[39:44] conference. I'm happy to answer more

[39:45] questions on PHP or XDbug or anything

[39:48] else. And I hope you found this

[39:50] interesting. And I would say enjoy the

[39:51] rest of your two days. Yeah. Thank you.

[39:54] Thank you.

[39:59] [Music]

⚡ Saved you 0h 40m reading this? Transcribe any YouTube video for free — no signup needed.