[0:00] [Music] [0:09] So, hi, I'm Derek. I'm European living [0:11] in London. Um, we can talk about why I [0:13] call myself European in a moment. Um, I [0:16] work for the PHP Foundation partly. I [0:18] also work on XDbook and I work on PHP [0:22] datetime support. I am also Groot [0:25] um without a G. I maintain a PHP.NET [0:28] that infrastructure. I like maps, beer, [0:30] and whiskey. It's irrelevant to the [0:32] talk, but I thought I'd throw it out [0:33] there. And if you want to have [0:35] questions, you can find me on Macedon or [0:37] here on the conference. That's all about [0:40] me. [0:41] So, I'm going to show quite a lot of [0:43] code, quite a lot of old code and some [0:45] new code that will not compile quite [0:47] just yet in your versions of PHP. [0:50] One of the bigger things in PHP 84 is [0:53] the continuation of making [0:58] typing better, making it easier for you [1:01] to add bits of language to to your [1:05] applications to not have to do lots of [1:07] annoying stuff. [1:09] Now, before P384, if you want to do any [1:12] kind of uh public reads and private [1:16] sets, you had to mark your property as [1:20] private and you create a public gutter, [1:23] right? That's a very common pattern that [1:24] you see a lot. But it means you have to [1:27] have cutters and sometimes also setters [1:29] to do these things. [1:32] Now in PG84 you don't have to do that [1:34] anymore. You can now type these things [1:36] immediately without having to create a [1:38] get or setter which is kind of handy. [1:40] There's a few concerns here. Um the [1:43] first keyword is for getting. The second [1:45] one is for setting but you also need to [1:47] use the set in between. There's no get [1:50] in between the parenthesis because this [1:52] is a very common setting. You have a [1:55] public get and a private or protected [1:57] set. There's also a shortcut for that so [2:00] that you don't have to use a public [2:01] keyword. So this implies that it is [2:04] public get. You can create any [2:07] combination but the strictness of the [2:09] set needs to be the same or higher than [2:11] the getter. That sort of makes sense if [2:14] you think of it. So you can't have a [2:16] private get and a public set. It won't [2:19] allow that. Again also not very useful. [2:22] So this asmmetric visibility um is [2:24] actually comes back in a few other [2:26] things. There's a few things around [2:27] this. So it only works with type [2:29] properties. So you can't have a all the [2:33] checks that PHP does for properties with [2:35] access and things like that read only [2:38] and stuff like that. are always only [2:40] work on type properties because the [2:43] untyped properties they are shortcuted [2:45] in some other way. As I said the set [2:48] visibility must be equal or less than [2:50] the main get visibility. Um if you use [2:53] weird array kind of things then that [2:55] follows set visibility even though you [2:57] might be sort of reading this kind of [2:59] weird. Uh the same thing if you inherit [3:01] properties they need to have the same [3:04] time I mean type and you it is allowed [3:09] to widen who can read and write to it. [3:11] So you can just like you have a a [3:13] private property in an inherited class [3:16] you can make it a protected property you [3:18] can also do it with a asymmetric [3:20] visibility [3:22] if you use private set it also makes [3:24] your property final. There is some [3:28] strange interactions happening with [3:30] private properties in classes anyway [3:32] because if you have an inherited class [3:35] that redefineses your private property [3:37] with the same name, they actually [3:39] created as two private properties. [3:41] They're sort of name space. It's not [3:43] something you see unless you like far [3:45] dump a an object or something like or [3:47] you serialize it because you get some [3:49] weird things with null characters in [3:50] there. You might have seen that at some [3:52] point. But this gets too complicated [3:55] with the asmatic visibility. So PHP will [3:58] now not allow you to re to have in an [4:01] inherited class a property with the same [4:03] name as in a class that you're [4:04] inheriting. Um read only has been [4:07] redefined from um private set sort of to [4:12] protected set but still has this right [4:14] runs responsibility. So if you use read [4:16] only by default it will mean a protected [4:19] set which made sort of sense. uh unless [4:23] you mark it as private set yourself. [4:25] Normally read only properties you can uh [4:28] write to in any context that you can [4:30] write to as a public property but that [4:31] now changes as well with this change. [4:36] Now PHP 85 not out yet. This has been um [4:40] merged into the codebase but uh it will [4:43] survive. I think it's pretty likely but [4:45] you never know. is that before 85 you [4:49] couldn't have the public and private set [4:52] on constants [4:54] um it's just left out for some reason [4:58] now exact or sorry I should say class [5:00] constants here now exactly why you would [5:03] want to do that I don't know but [5:05] sometimes we add things in new versions [5:08] that we've forgotten about [5:10] all right [5:13] one of the other bigger things in PHP 84 [5:15] is property hooks so that sort of built [5:17] on top of as asynchronous visibility but [5:20] in a slightly different way. It [5:22] basically allows you instead of having [5:24] to define a setter and get a method to [5:26] implement that logic directly when you [5:29] define a property. So you get the code [5:31] together. So basically what the syntax [5:33] says here is that if I'm reading the [5:35] null the full name property, it will [5:38] return the value of this first [5:40] concatenated with a space concatenated [5:42] with the last name. Don't don't ever [5:45] store names like this because names are [5:47] way more complicated than first names [5:48] and last names. But this is an example [5:50] that was in the RFC. [5:52] Same thing if you if you write to the [5:54] full name property. If you attach a new [5:56] value to it, then at first we'll get the [5:59] value. [6:01] This is a variable that is automatically [6:05] introduced into the property hook. I [6:06] haven't defined it here anywhere myself. [6:08] And you also can't do that. it will [6:11] explode it or split it by space and then [6:13] write it to the first and last property [6:16] and then we set is modified as true [6:18] because why not? [6:21] So there's an interesting interaction in [6:23] here because first and last are actual [6:25] properties. They are defined on the [6:27] class. We have done that with a in a [6:30] constructor here defined as properties. [6:32] But a full name property isn't an actual [6:35] property. uh if you would debug this uh [6:39] an object with this class in XDbug, the [6:41] full name property wouldn't show up [6:43] because it is there's no storage [6:45] attached to it. It's only a virtual [6:47] property in a way that you can read and [6:49] write to it. But there's nothing stored [6:52] with this property. [6:54] The moment you use a property name in [6:56] either the getter or the setter, it will [6:57] have to become an actual property with [7:00] actual storage. So that's how PHP does [7:02] that. Now I find this a little bit of a [7:04] contrived example um but I actually [7:08] found some use case in code that I've [7:09] written a long time ago where these [7:11] propertes are actually quite useful. So [7:14] let's go back in time before we had um [7:18] no typing in PHP whatsoever. So this is [7:20] code that is written in 2003 long or [7:23] 2004 maybe long long time ago where we [7:25] already wanted to have some type [7:27] enforcement of type and value um [7:31] enforcement on properties that we're [7:32] setting. And the way how you could then [7:34] do that is by having the underscore set [7:37] and also underscore get magic methods [7:41] that would get triggered anytime you try [7:43] to write to a property that doesn't [7:44] exist. And the implementation that we [7:46] then did so long ago is we had a [7:49] specific property called properties that [7:51] would then store these actual properties [7:54] as an array element. And because this is [7:56] protected or in sometimes private you [7:58] couldn't directly read and write to [7:59] this. So the way how we would do typing [8:02] for um a property setting in this case [8:05] UID referencing it's something uh email [8:08] related we would check when you write to [8:11] this in this get method whether the [8:14] value is a boolean and if it's not a [8:16] boolean we throw a value exception [8:20] PHP of course has its own value [8:22] exceptions now um and if it works we [8:25] just set it as a value now of course [8:28] when we got type properties in PHP tree, [8:30] you can rewrite this to something like [8:32] this, right? You can just set the type [8:34] directly on a property. But there was a [8:37] few other cases as well like for the [8:39] list limit property, we wanted to make [8:41] sure it's an integer, which we can do [8:42] with this type definition, but we also [8:45] wanted to make sure it is larger than [8:46] zero or zero or larger I should say. And [8:50] that is something you couldn't do in PHP [8:51] yet because you could only enforce the [8:53] type. So with PHP 84, you can now [8:56] rewrite this. So we check for the [8:58] whether it's a number and whether the [9:00] value is larger than zero. You can do [9:03] that now in your set property. [9:06] So set gets called with uh the value and [9:09] if the value is smaller than zero then [9:11] we can throw these value errors yourself [9:13] and then of course when the moment you [9:14] throw an exception things will stop. Um [9:18] the type itself we don't have to check [9:20] with is int anymore. Of course you can [9:21] type that directly on the property. [9:25] So set and get property hooks are [9:27] actually kind of useful. Uh they also um [9:30] cause the bug on XD debug because XD [9:33] debug checks where you have lines of [9:35] code that you can run and it was only [9:37] familiar with functions or methods or [9:39] files. But this is now an additional [9:42] type of function or an additional [9:45] location where you can have code. Xbook [9:48] didn't know about it. So if you would [9:49] set a breakpoint in these things, it [9:51] would sometimes refuse to set a [9:53] breakpoint because it didn't know there [9:55] was actual code on there. That's now [9:56] fixed with the release that I made [9: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]