 Let's get going. My name is Adam Harvey and you can find me on Twitter as Elnome. I work for a company called New Relic. We do interesting performance analytics stuff, which is pretty cool. Check it out. That's all I'm going to say about that. I'm going to talk to you about PHP 7 today. I am peripherally a member of the PHP 7 Internals team, which means that you get to blame me for anything that you dislike about the language, even if I didn't vote for it. I'm going to talk about the biggest transition that we've had in PHP for, I guess, really 11 years. Maybe you could argue PHP 5.3, but the transition from PHP 5 to PHP 7. This talk is mostly about migrating existing code to PHP 7. I'm going to touch on a few new features as we go, but mostly what I want to give you today is kind of an appreciation for what's going to change, what might break your code and a rough toolbox for kind of what you can do to fix those problems as you find them or more accurately find those problems so you can fix them. PHP 7, like everything, has a logo. Very nice. I'm supposed to have a space in it. Sorry, Vincent. It's taken us a while to get here. Let's see where we came from. PHP 5 was first released in July 2004, so it's 11 years ago now. It only really snapped into focus as a modern language with PHP 5.3, which came out six years ago in 2009. During this time, of course, PHP 5 has, in theory, the idea is that you're not supposed to break back compatibility. Anybody who's been around for PHP 5.2 to 5.3 knows that we've been better at that with some releases than others, but the idea is basically that PHP 5 hasn't changed too much as time has gone by, stuff's been added, but not too much stuff has been removed. In 2012, we started releasing new minor versions, I guess, feature versions annually, roughly. It's actually about every 15 months, if you do the maths, we're not very good at annual releases. Each of those has included a bunch of new features, but kind of as we've gone by, it's also become apparent that there was an increasing amount of stuff that we wanted to remove, I guess, from the language as well, miss features that made sense in 1997 when nobody knew any better, but don't make sense today. There are things that we could deprecate, but the problem with sticking to PHP 5, of course, is that it's very, very hard to actually remove stuff because that is a backward compatibility break. There were a few key things like magic quotes where we just went ahead and did it anyway because it was the right thing to do, but for the most part, we tried to avoid that. So I stirred the pot early last year and was like, let's talk about whether we want to do a new release. But what really got things going on PHP 7 was in May, Sebastian Bergman sent this very confused email after about 800 commits appeared out of nowhere on a new branch in PHP Source. The source of that was from Dmitri Stogov, Shincheng Hui and Nikita Popov, who sponsored by Zend did work on something which a lot of you have probably heard of called PHP NG, which was basically a next generation engine. So the PHP runtime runs on a virtual machine called the Zend engine. PHP 5 runs on the Zend engine too. PHP NG was a huge refactoring of pretty much everything to do with the runtime for performance reasons. And the performance, of course, as a lot of you will have seen, and we will see in PHP 7 is significantly better. This is only the first step. PHP NG was about 50% quicker in PHP 5 on an average kind of workload. Say a Drupal site, say a WordPress site, say a symphony site, whatever it may be. Obviously, this was really going to be the impetus for a new major version. So of course, the floodgates opened at that point. All of those little irritations, you know, why can't we get rid of this? Why can't we get rid of that? Why can't we deprecate this? Why can't we implement this? Because the pass is broken. The floodgates open. And by the time that the feature freeze happened in February, we ended up with accepting 45 RFCs, pretty much all of which corresponded to new features. As of Tuesday, when I updated this slide, there were almost 10,000 commits and 180 just code contributors. Now, the total contributor counts higher because people have contributed ideas, people have contributed documentation, people have participated in mailing list discussions, but the point is it's been a very, very, very big project. It's not as big as Drupal 8 probably, but it's still pretty big. And that contributor count, by the way, is easily the highest we've ever had for a new major or minor version. Like that's way off the charts. PHP 5, I looked it up at one point. PHP 5, I think, was about 40 people. PHP 7 is now 180. So a fair bit's changed. So as I said, I guess, well, why would you want to upgrade to PHP 7? Well, for one thing, it's a lot faster. I ran a few benchmarks this morning just to kind of get up to date numbers. This is one I just care about, we're just building the PHP documentation, which this is measured in seconds. So it used to take over a minute on this laptop in PHP 5.3, and this laptop is not too bad. Now it takes 20 seconds in PHP 7. It's an awful lot quicker. So as I said, I did this benchmarking myself. It's terrible benchmarking, but I don't trust benchmarks. I didn't fake myself. For a typical blog, that is very strange. My apologies, there's meant to be some graphs. Let me just show you some speak. Let me, you can just look at my speaker notes for a moment. So PHP doc was considerably quicker. A competing product to Drupal is also much, much quicker. It's about three times quicker. I actually had to rerun this just to make sure I hadn't screwed up my environment, but it really is PHP 7 is three times quicker than PHP 5.5 was. For my Drupal benchmarks, it wasn't quite as impressive. I think this is mostly because I just did all this in like a bunch of docker containers and I think the MySQL overhead back and forward was actually a big part of this. So that's my bad, sorry, bad benchmark. Like I said, don't trust them. The other one that's impressive is the memory usage. Now a lot of these performance gains have come because we're hitting cases more often. And the reason for that is this is a standard Drupal 8 beta 15 index.php just hitting it, seeing what the peak memory usage is. PHP 5.5 and 5.6 was within like a K of each other. It's 36 megs or something like that. The resonance size is now 29 in PHP 7. So it's smaller as well. You can host more sites on the same hardware. That's pretty awesome. All right. Of course, it's also better. I'm going to talk, as I said, a little bit about features, not much. But when you see some of the cleanups that have happened to the language, I think you'll hopefully agree that it is better than it used to be. There is, of course, a problem though. I mean, that's the carrot, but here's the stick. PHP is popular. You know, PHP 5, there are 140,000 GitHub projects. And I actually didn't update that number. I did that back in May. So it's probably like another 20,000 now. There are tens of millions of sites, if you believe, builtwith.com or whatever it's actually called. There are 44 million PHP websites out there. About a million of those are Drupal. So good job, Drupal. But the point is there's a huge long tail of, like, probably 20 million of those sites are just, like, somebody hacked together a guestbook in PHP 4 or something like that. Every time we break something, this obviously causes problems for people. Now, the other problem is, the trade-off with the annual release strategy is that the flip side of that was that we decided to support PHP versions for two years, fully after they were released, and then another year for security fixes after that. PHP 5, therefore, is not very long for this world. PHP 5.6 came out over a year ago. So what that means is, PHP 5.6 is end of life then. What that really means is everything before PHP 7 is end of life then. It's pretty close. It's not that far off. Now, obviously at this point, if you're like me, you're gonna flail because, you know, we've got big projects. We can't fix everything in that space of time to be PHP 7 clean. Of course, it's not really that bad. You do have some options for handling the migration. You can stagger it out a bit more if you have to. What can you do instead? Well, you can rely on distribution packages to buy you a few more years. That being said, I mean, theoretically this is great. Ubuntu will still support PHP 5.5 until April 2019. It supports a new enough version of PHP 5.5 that Drupal 8 will run on it. I assume Drupal 8's minimum requirement was probably scoped to match this rather than the other way around. Red Hat, you know, if you're running Red Hat 7 or CentOS 7, PHP 5.4, we support it until June 2024. That's nine years from now. Where were you nine years ago? The catch, of course, of that is the longer you stick your head in the sand, the more you're relying on the distribution maintainers getting backports of security fixes right. Because obviously in my near 11 months, how many days it was, the PHP project won't be supporting PHP 5.6. Backporting security fixes, if the code is pretty much the same, is not that hard. Backporting security fixes, if you just rewrote the entire runtime, is pretty hard. So I think there's a viable strategy like if you need an extra six months, 12 months, 18 months, but I don't think it's a viable strategy if you really want this in nine years. If you really still want to be running PHP 5 in nine years, you may have bigger problems. So another option you have, and this really works if you host your own stuff, just have a flag day. Just change everything over, you know, just do your testing, do your integration, and then say, okay, well, we'll switch to PHP 7 on this day. But probably what you're really going to want to do for a while is do your wield. You're going to want to use both PHP 5 and PHP 7 depending on what you do. Now, if you're admitting a site, that's great, but if you're maintaining, say, a module, you know, a theme, anything that has to run on both, this gets a fair bit harder. Because a brief digression is a language design. Breaking back of compatibility is tricky for that use case because code that supports both can only run in the intersection between those. Now, in PHP 7, we've tried to maximise that space, and I think we learned some lessons from other languages here, and I'm going to pick on Python for a minute. Python 3 came out seven years ago, almost seven years ago. There are still, of its top 360 packages, there are still 15% of them that just straight up don't run on Python 3. Most of the rest run on both, some of them are Python 3 only. Adoption's being rocky, just adoption of Python 3 has been very rocky because of the difficulty of supporting both versions, particularly in the early versions of Python 3. This got a lot better around Python 3.2 or 3.3. In PHP 7, we've tried really hard to minimise those problems. So that's why I think the right thing to do, particularly if you're maintaining module code, or theme code, or extension code, or whatever it is, is to have your code run on both for a reasonable period of time, because, and this completely undercuts the point of my talk, in a lot of cases, you don't really actually have to do very much. It's a relatively straightforward process. So, as I said, that's what you can do, what should you do? As I said, I think you should just run on both. The other thing you need to do if you maintain a module, or you maintain any kind of code that's used by anybody that's not you and the people that you can hit with a squishy ball from your desk, is you need to tell your users what you're gonna support and for how long. You know, you need to say, okay, my awesome module is gonna work on PHP 5 and be supported on PHP 5 until December 31st, 2017, or whatever date you pick and stick to it. Document it, put it in big block letters on the top of like your page on Drupal.org. You need to tell your users what you plan to do. And if you are a user, look for those policies. Figure out what you're gonna do. Figure out how you are going to upgrade. Because you don't really, you don't really wanna support both for like a single project. It's really only if you're sharing code where you wanna support both. If you're relying on somebody who are relying on a project where the author hasn't said what they're gonna do or hasn't got PHP 7 compatibility, if it's an open source project, consider contributing, make a pull request, ask them. You really just need to get the prompt to think about it and be receptive to that. If you wanna run on PHP 7 because you want the awesome performance improvements but you can't, but you're relying on a library that doesn't support PHP 7, yeah, you can fork it and fix it and run it for a period of time, but you don't really wanna diverge from upstream like that. So try and get your stuff back into the upstream. All right, so PHP 7 is awesome. I've now scared you all. What are we gonna do about it? I've got a site, big Drupal site. I wanna run it in PHP 7. How do we go about actually doing this? Well, your number one best possible thing for this is testing. Right, you know, if you don't have tests, right tests. If you do have tests, right, more tests. You basically can't ever have enough tests. These are the biggest single thing that you have to combat problems with cross version compatibility is running your tests in PHP 5 and PHP 7 and seeing what breaks. If you're using PHP unit, then PHP unit integrates with XD bug and you get lovely code and branch coverage stats. The branch coverage stuff is new and super cool and I highly recommend looking into it. I assume there is also a way to get this out of simple tests, but I apologize for standing up here at a Drupal conference and not actually knowing. The point is testing is what you want to do. You wanna make sure that you are testing your code. There is also tooling out there for this as well. Now, Alexia Smith has written a project called PHP 7 MAR, migration assistant report. And what that does is it just basically, you give it a directory full of code and it will go away and recursively scan all the PHP and it will tell you what might break. I ran it on Drupal core, which you can actually see kind of in the background of that and I came back with a bunch of stuff and most of it's not critical to be clear. Like most of this is just advice, but there is also a level there for, oh my God, this is really going to break. Rasmus Luthor has also written a tool called fan, which is a more general static analyzer, which is kind of very embryonic, but it does also, it can actually detect some of these backward compatibility breaks as well. So there is tooling out there. These are links. I will put a link up to my slides at the end so you can jump in there and go to those. You can also just Google them. So there is some tooling out there. It's pretty, both of these are pretty alpha at the moment. They're both like 0.1, but they're both useful already. Like they'll give you an idea of what's going on. And obviously the other thing you can do is try it. You know, assuming you have a development environment or a staging environment or something like that, and if you don't, you probably need to consider that, then install PHP 7 on it, see what breaks. You know, do some informal testing. That's a perfectly viable strategy as long as it's not your only strategy. It's a very good strategy. Just make sure you also use the tooling and do some testing. All right, so what are these breaks? What's PHP 7 broken? Now I'm focusing mostly on the things that are a little more insidious. A lot of PHP 7's breaks have big screaming errors that are very obvious, like it will fatal error and it will tell you what's wrong and you can go away and fix it. But there are a few changes that are not quite so obvious. So let's get into them. I like putting this slide up because it's just scary as shit. It's not actually all variables. It's better and worse than you think. The problem's really that the way, the associativity of some of the way that we handle indirect references has changed. What do I mean by an indirect reference? Basically these are the four cases. Now the thing you will note is that they're all involving variable variables in some way. So that one's a straight up variable variable. That's a variable property name, which then goes to an array, variable property name, variable property name. These have all changed behavior in PHP 7. They've all changed behavior in ways that you may not get errors. You might just get incorrect results. It depends on what your properties actually are, what the variable variables actually are. Are they callable in some of these cases? But first, why are we doing this to you? Why are we inflicting this horrible pain on you? The reason is because it allows us, all the parser cleanups and the implementation of an abstract syntax tree means that we can now support all of these awesome things. You can now do JavaScript style like immediate call closures, or immediate calls to closures. You can now dereference things and just call them. You can have arrays and just call them if they're callable. So there's a lot of really cool stuff there. The problem's just that to implement all of this, a few of the earlier hacks had to go away. So all that's awesome. The good news is, when this was implemented, Nikita Popov worked on this. He had a look at Symphony and Zen Framework 2, I believe. I don't think he looked at Drupal, but he looked at Symphony, which obviously now Drupal depends on, and Zen Framework, and there was literally only one case in both of those frameworks where this actually mattered. The problem, of course, is finding the one case in both of those frameworks where this actually mattered. So how has this changed? So basically, I'm just gonna walk through each of these in turn, PHP5 version, PHP7 version. If you can't remember these as I skip through them in 20 seconds per slide, that's okay, these are all in the migration guide as well, which I will link at the end. But I just wanna sort of give you a flavor of kind of how this has changed. So in PHP5, this fairly horrible expression basically broke down to take the value of foo-bar-bas, and then use that as a variable name. Now, of course, if you basically ever write dollar-dollar to use variable variables, you have basically lost. But in PHP7, now it will basically look at the variable variable first and then treat it as an array. So again, that's what I'm getting at. It depends on what these variables actually are. If what's pointed to by dollar-dollar foo isn't an array, then obviously you will get an error, and that's great. But if it is an array, maybe you won't, and that's why you have to be aware of this. You might just get null or you might get something completely different. The next variant, and there's a couple of these which are basically the same. In PHP5, basically, bar-bas was what you'd use as the property name. In PHP7, foo-bar becomes the property that you're accessing, and then you treat that as an array. This variate, there was another variation on that too on the first slide, I'm not gonna go through it, and then this variation is basically literally just the static version. You can probably imagine how that's gonna change. Goes from bar-bas as the property to foo-bar is the class. All right, what do I do about this? How do I detect this horrible case somewhere deep in code that some contractor wrote 10 years ago? Well, once you've found them, preferably using the tooling that I mentioned earlier, you can actually get this behavior. All of the examples that I just showed are actually valid syntax. So you can specify what behavior you want by using curly braces appropriately. You can specify what, or you can break it down, and this is actually what I'd prefer to do, break it into two instructions and then just do it that way. So I said, what do you look for? You can use tooling, PHP7, mar definitely detects this, because I tested this yesterday just to make sure they did. You can also, if you really want to, I wrote a regex, it works. Maybe you don't do this, but if you really want to, you can just pull this out of the slides and trust me, it works. Oh, it doesn't support non-ASCII variable names. So if you have Unicode variable names, sorry. All right, moving on. PHP7 now has engine exceptions. So in PHP5, there was no scenario, basically, where the Zend engine would ever throw an exception. There were a couple of cases in core extensions where you might get an exception. I think there was one in the DOM extension, for example, but there was nothing in core where you'd ever get an exception thrown. If the Zend engine has an error to tell you, it would tell you via an error. The problem with that, of course, is that errors are hard to deal with. Fatal errors you can't intercept in any way, shape, or form. Recoverable errors you have to go through, like, set error handler and handle them that way, and that's pretty ugly. And of course, if you're using a framework like Drupal, you also have to deal with the frameworks of error handler as well, so you might not even have control over this. So in PHP7, wherever possible, the runtime will now throw an exception instead of generating an error. It's a normal exception, you can catch it, you can do whatever you want with it, you can re-throw it, you can, whatever works for you. Or you can just let it bubble up, whatever the right behavior for you is, but the point is there's now more flexibility. So in PHP5, there were 182 errors, 17 recoverable errors, and one pars error. I think this was PHP 5.6. In PHP7, the number of these has dropped dramatically. The number of fatal errors that you can't actually catch is now down to 54. The number of recoverable errors is now down to three. Pars errors are now gone altogether, but the constant lives on because basically if you don't catch the exception that the pars error generates, then it turns into a pars error. So how does this work? Here's an example, and this is a little bit of a sneak peek of something I'll talk a little bit more about later in terms of type declarations. Here's an example of some code that will generate a type error. In this case, we're giving a string to something that expects an integer. Now, what you'll get is you will get, if you don't have a try catch or a set exception handler, you will get a fatal error, but the key is it's an uncaught type error. So it's an exception. Type error is just the name of the exception class. It's uncaught, and it then has like any other exception, or any other, yeah, any other exception. It has a message. So the nice thing is now, at the point where you actually made the call, you can just catch it and do whatever you need to. You know, report an error back to the user. Maybe it's something that's non-critical, so you just wanna keep going. But the point is you can catch it and deal with it like any other exception. Now to do this, the exception hierarchy in PHP has changed. In PHP 5, everything inherited from exception. It was basically this God exception class that everything else inherits from. In PHP 7, it's been moved down a level. This is something that will seem familiar if you come from Python or Java, but is new PHP. So the exception stuff still exists. None of that's changed. There's still a class called exception. There's still subclasses of that called logic exception, runtime exception. And any exception that you throw at runtime should be an instance of exception or one of the subclasses. But there's also now this parallel hierarchy of errors. And these are intended for internal errors that PHP generates. So when PHP hits a parse error, it will throw a parse error exception. When it hits a type error, it will throw a type error exception. There are currently five. They're all in the migration guide. I expect that there will be a lot more in the next few versions of PHP. I think 7.1 and 7.2 will probably subclass a lot of these out again. But the important thing here as well is that there's now this top level thing called throwable. Now throwable is an interface. You can't actually go new throwable. Any, in PHP 5, any exception had to be an instance of exception. In PHP 7, any exception is an instance of throwable, maybe not necessarily exception. So what that means is that if you had something in PHP 5 that had this pattern, a Pokemon handler where you've got to catch them all, you knew that any exception that got thrown would be caught. Like that block there would basically always run if an exception got thrown. In PHP 7, that's not the case. It's now possible for PHP to throw an exception that won't be handled by this. Now that might be good. I mean, you're not expecting to get exceptions from the language here probably. So if you don't want to handle those, then you don't have to change anything. You just keep it as exception. But if you do want to catch everything now, you have to catch throwable. Now that does work. You can of course also do a catch throwable and catch exception as well to get both. Not sure that's a good idea. So what do you do? Now, Drupal 8 is going to catch your throwable, is going to catch throwable that you don't handle with its own exception handler. So if you're good with Drupal's default exception handling, then job done. Go to the pub. But what I would suggest is if you have code, if you have a code base that you want to run on both where you're doing your own error handling, I would say you set up use the setExceptionHandler function to set up an exception handler that will basically catch, be a last result handler in PHP 5 and basically make it very similar to your error handler. So basically do the same things in setExceptionHandler that you would do in setErrorHandler which is probably just print some sort of message to the user and log something and get out. Exit. The key here is that, so in PHP 5, I actually, I'm sorry, I jumped ahead there. In PHP 5, I'd use setErrorHandler and a Pokemon handler at the top level like if you've got a front controller. In PHP 7, I would use setExceptionHandler in a similar way to setErrorHandler and then as said, just do what you would normally do. Of course, rules are made to be broken. There are times when you'll have to catch errors. At least now, it's gonna be a lot closer. If you try and say include or highlight string some sort of block of PHP code that's invalid, hey, at least you can now deal with it. That's a bonus. And you can deal with it in the same function rather than having to jump to another scope. There is an additional wrinkle too. If you have an exception handler in PHP 5, you may have type-inted it with the exception class. Now, obviously in PHP 7, if it throws something that isn't an exception, it's just a throwable, then you're going to get a very big fatal error message. It's gonna be pretty ugly. So in PHP 7 only, you would have to change that to throwable, but the right thing to do is probably just not to have a type-int on your exception handler. Just whatever it is, it is. Trust that PHP will never give you something that's not an object. I really hope. All right, what am I looking for? You're gonna look for your existing exception handlers just to make sure they do sensible things and you're gonna look for anywhere where you're just catching every exception. That's pretty much all there is to it. It's mostly, this is probably actually a really good opportunity to just check that what you're doing with the exceptions and errors makes sense. Like, you know, give it some thought, make sure that whatever you did a few years ago still makes sense today. It's a good chance to do it. All right, speaking of, so earlier I said that we changed how variables work. Now I'm gonna say we're gonna change how foreach works. Well, how is it broken? Let me count the ways. It's okay, there aren't that many. So, what happens when we modify an array that's being iterated in a by-reference foreach? So, just in case anybody doesn't know what this does, we're iterating this array but we're actually grabbing a reference to the real value for each time we iterate over it. So in this case, what we do is when we see the first item, we are adding a new array item and var dumping. Now in PHP 5, what would happen here was you would only get, although the array would change to one, two, you would only actually get the first element. Now, again, if you're doing this, don't. But if you're doing it by accident, you need to know this has changed. In PHP 7 now, it will do a really good job of trying to keep track of how the array has changed out from under you and actually still iterates in the next thing. This is actually probably much better behavior. I mean, still don't do it. This is probably much better behavior, but it is different. The other change relates to these functions. Now, if you've only started writing PHP in the last 15 years or so, you've probably never had to use these, but this is how we used to do iteration back in PHP 3 before 4H was a thing. So in PHP 5, 4H used to actually set the internal array pointer that gets used for what the current element is. So you can actually do horrible things like this. You could var dump the contents of the current element without actually ever using the dollar V. In PHP 7, the internal array point is never touched. So if you have basically 4H's that then also run any of these functions within the 4H on the same array, it's gonna change. That's probably a good thing because you probably need to rethink this anyway. What do you do? Well, don't use the old PHP 3 functions for one thing. I would say beyond that, if you need to manipulate arrays or manipulate elements within a by-reference 4H, consider using array walk and array map. I mean, with anonymous functions and closures in PHP now, it's a lot simpler to do this. You get a completely fresh scope where you don't have to worry about messing anything up outside. One of the bugs that we get the most in PHP is that we get reported the most is where somebody's used a 4H with a by-reference variable, and then they've reused that variable after the 4H. Now, what happens for those of you who haven't encountered this before is the PHP, that's still, because PHP doesn't have block scope, that's still a reference to the last item of the array. So if you reset that variable to something else, you just changed what was in the array. That's usually bad. It looks like spooky action at a distance. So you can use array walk and array map to actually effectively deal with that problem. You don't have to worry about the scope leaking because you have a true function scope there. I mean, the right thing to do here really is if you have one of those two cases, you just need to refact your code to not do that. And you're looking basically, you're probably gonna have to look, there are no errors for any of this, so you're probably gonna have to look at any 4H where you're doing it by reference. That's probably fair advice anyway. This one's kind of obscure, but again, it can be silent. It's not always gonna be silent, but it can be silent. So in PHP 5, anything that looks kind of like a number in a string is treated as a number when you try and use it as a number. So the 0x10 is treated as a hex decibel number. In PHP 7, it will not be treated as a number, but you also won't get an error. The reason for that is because of another of PHP's misfeatures, which is that when you cast a string to a number, if it starts with a valid number, it will treat that as a number and then once it gets to something it doesn't think as a part of a number, it just throws it away. It doesn't actually, it doesn't warn you, it doesn't try to use it, it just gets rid of it. So in this case, the x is the first non-numeric character in PHP 7. So PHP goes, oh, okay, it's zero. So now it's zero. Not really what you want. So what do you do? Well, if you really need the old behavior, there are a bunch of ways to do it. You can use scanf to say, hey, I've really got a hex string or an octal string, please treat it as such. Also, why do you have an octal string? My point is you can do it. What do you look for? I don't know. Interestingly, however, the Alexia's PHP 7 martl actually picks this up. I haven't, I didn't, I haven't pulled it apart. This only got added recently. I haven't pulled it apart yet to figure out how. So tooling, tooling is good. The behavior of list has changed again. This is really obscure, but I'm just mentioning it, because again, because it doesn't generate any warnings. In PHP 5, you can unpack strings like arrays using the list construct. So you can basically go ABC and you get ABC. Interestingly, this only ever worked if the right-hand side was a variable. You couldn't do this, where that dollar S is on the second line, you couldn't do this if that was a string literal. I have no idea why. In PHP 7, you can't do it anymore. It won't warn you. I really wish it did, but it doesn't. You just get nulls, because it's not an array that's going in. Of course, if you want that behavior, you can do it in a completely PHP 4, 5, and 7-compatible way by using string split. Turn it into an array because list expects arrays. What do you look for? I have even less idea on this one. If you don't use list very much, then just look for all the list instances in your code. If you use list a lot, then good luck. We only just added yield. How could yield have changed? Well, the associativity has changed for the same reasons as the earlier indirect variable stuff has changed. So in PHP 5, yield foo or bar basically implicitly put brackets around that, so you got a boolean in that case. In PHP 7, that now binds to the yield, so it goes yield foo or bar. Accessing dollar bar probably isn't super useful, but it does mean that you could actually now do the classic Perl style yield something or die pattern. Please don't do that. What do you do about it? Just use parentheses, just specify how you want that to actually work. Sorting has changed. This sounds dramatic, but it's not. PHP's never guaranteed that you have a stable sort, so for performance reasons, PHP basically gives you no guarantees about how sorting works. Well, it gives you a guarantee that the lowest thing will be at one end and the highest thing will be at the other end, but it doesn't give you too many guarantees about how that's gonna work or what order things are the same will be in. So in PHP 5, so basically all that's happened here is that the order of some objects when they're the same gets swapped. So this is doing a case in sensitive sort, just watch the bottom line. In PHP 7, the lower case O comes first. In PHP 5, the uppercase one comes first. In practice, I very much doubt that this will break anyone's production code, but I suspect it will break people's tests. So this is one that I think you're more likely to see in tests where you're testing for a particular array output. So you're looking for it in specific test cases and I think you're really just looking for broken tests. Really, if you have a test where you're testing that a function returns an array and you wanna test that array, you need to be testing that elements are in the array. You shouldn't be testing the whole array itself, I think, as a general rule, because this sort of thing can happen. Unless you have a very clear order in which case, I guess it's fine. Everybody probably knows this warning. I suspect everybody's seen it at some point, probably lots of times. Usually at about 5.30 on a Friday afternoon when you're really just trying to spin up one more server for someone. In PHP 7, it's gone. That's not necessarily good news, though, because all it means is PHP just picked UTC for you. Now, if all your servers run in UTC and all your applications expect UTC, that's great, but if you don't, that might be a source of silent breakage. Just always set a date time zone. So if that's all the things that don't scream at you, what are a few of the things that you need to know about that will? You can't use any of these as class names anymore. Even if they're like just the last, you know, even if it's a namespace class, you still can't use these as class names. The reason, of course, is because of the new static or scalar typing feature that's come into PHP 7, which I'll talk a little bit more about in a minute. This seems to have disproportionately affected test suite authors and doesn't seem to have affected too many other people, but I do know that Drupal 8, this did affect symphony, so Drupal 8 then had to pull in a symphony 2.3 patch to actually make this work. So just something to be aware of. I would also avoid, even though they're not officially gone, I would also avoid scalar and void, because I think there's a pretty good chance in PHP 7.1 that they're both gonna appear. Their warning. If you ever use the HTTP raw post data variable, it's gone. It's been deprecated for a while in actual fact, so you've probably been ignoring deprecation warnings in this case, but it's really gone now. So you need to use file, get contents, PHP input. This is actually, generally speaking, a good thing. The old MySQL extension is gone. Now, if you are solely using Drupal's database APIs, that's fine, don't care, doesn't affect you, but if you have to interact with code outside of Drupal, just be aware of that. It's really gone. You also can't use this. I don't really know how to go into more detail on that. Apparently, Global used to work with variable variables. Who knew? There is more stuff that's broken. All of it has very obvious errors, as I said. I'm not gonna go too deeply into, well, I'm not gonna go into it, but it is all in the migration guide. There is a very, very exhaustive list of backward compatibility breaks in the migration guide. Your eyes will glaze over while you read it. I can assure you my eyes glazed over while I was writing it, but you will, at some point, need to know them. So I suggest setting aside a day where you're very awake and getting a coffee and going through the list because there's a bunch of stuff in there that's important. So it's not really the goal of the talk. This wasn't really part of the abstract, but I've got 18 minutes still. So let's look at a few of the new, just three of the new features really quickly. The big one, the headline one, a lot of respect. Once you get over all the graphs where PHP 7 performs way better, and it's really cool, is type declarations. And you saw these on an earlier slide. Basically, you can now type int, and they're not called type int anymore. They're called type declarations. There was a big find and replace there. You can now use scalar types to basically hint, or tell PHP what type you want a variable to be. Don't clap too much. I voted against one of the features that's coming up next. I voted for this, I should note. The cool thing about this is that you are guaranteed within foo that A and B will be an integer and a string. No matter what the user passed in, you are guaranteed, and no matter what, whether they're in strict or weak mode, which I'll cover in a sec, you are guaranteed that in that function, if that function actually executes, A and B will be an integer and a string. Definitely, no ifs, buts, or maybes. So that's awesome. That saves a ton of boilerplate, figuring out what type you've got, whether it's really a numeric string, like calling isNumeric, things like that. That's all gone now. You know it will be an int and a string. How those become integers and strings, however, is configurable. There is a strict mode and there's a weak mode. Strict mode is optional. You have to turn it on with that declare that you can see there. But what that does is if you give an integer to a function that expects an integer, or sorry, if you give a numeric string to a function that expects an integer, you will still get an error. It will not be coerced. Even if PHP could coerce it without any loss, you will get an error. You will get an uncaught type error. You can catch the type error if you really want to. But it will error. The default, though, is weak mode, which you can declare strict type zero if you really want to, but don't bother. And in this case, PHP will coerce. If it can coerce the value that comes in, it will coerce it using the same rules that have always applied to internal functions. You know, if you have given, say, the power function, a numeric string in PHP, it will convert it to a number if it can. So this behaves the same way. It uses the exact same rules. Now, the interesting thing about the strict types is this, that declaration applies to the file. It's a file scoped thing. And it only applies to function calls that you make within the file, not functions you define within the file. So it doesn't matter. When I declared foo, it doesn't matter whether strict types was one or zero in that file. The point is that in the file where I actually call it, if strict types is there, then strict type checking will take place. What that means is if you're using an API, you get to decide whether you want strict type checking on or not. If you are writing an API for someone else to use, you don't get to decide that. But at the same time, it doesn't really matter because you know that you're still getting an integer and a string. It's just up to the person who's calling your code to decide whether they want that to error or not if strict type checking is enabled. This also applies to return types. So you can also type int, type declare. Even I've got to still go through the process of finding and replacing. You can define what type a function will return. This is subject to the same strict typing as before. So if this function returned, in weak mode, if this function returned a numeric string, that would be fine. It would succeed. It would get converted to an integer and the code that called it would get an integer back. In strict mode, if you returned a numeric string, then it would error. And again, you'd get a type error and you'd get to catch it and you could do something with that if you wanted to. Again, the nice thing is that you know that the thing is getting returned as an int. Where I think this is really gonna be useful is in interfaces and in sort of class hierarchies because now you can basically define, okay, I'm defining an interface for a user. The username will always be a string. The email will always be a string. The login function will always return a boolean. And you know that no matter who implements or whoever writes the class implements this, their return types will definitely be those things, otherwise PHP will jump up and down and scream at you. I think that's pretty cool. I think it's gonna greatly improve like the ability to use duck typing, it's gonna improve the ability to do, just have general type safety and data safety in PHP. So I commend it to you. Another thing that's in which is kind of small but really useful is the null coalesce operator. We've all written blocks of code like this, I suspect. Is this variable defined? If it is, use it. If it's not, use something else. In PHP 7, you now can shorthand all of that. There's a double question mark thing which I believe we shamelessly stole from C sharp which we'll do the same thing. Small but nifty. The other new operator that came in in space, the final frontier was the spaceship operator. The spaceship operator, which I'm told is a tie advanced, basically is a comparison operator. This again exists in some other languages and PHP is shamelessly stolen on it. Basically it will compare two values using PHP's internal comparison rules. So whatever variables or expressions you give it, we compared using PHP's internal compare function function. It's called compare function, I wasn't, I didn't start it. The funny thing is, you've never actually been able to access that before. Like there's never been a way in PHP to do it. If you knew they were both strings, then you could use string compare. If you knew they were both numbers, then you could subtract them. But if you didn't know what they were, you didn't have a type safe way of doing this. Now you can just use this. It's really useful for things like this sort callbacks where you're not comparing to objects but you're comparing two properties on those objects or something like that. It's really useful for that. There is a ton more stuff. The new features page in the migration guide is actually longer than the backwarding compatible page. And trust me, the backwarding compatible page is long. So there's an awful lot of really cool stuff. Again, I strongly recommend seeing down, this one you'll probably stay awake more for. So do this after the backwarding compatible page but definitely sit down and read it. There's things like anonymous classes, better assertions, unicode escapes, massive generator improvements if you like doing co-routine stuff. There's a bunch of cool stuff there. Group use statements, so you don't have to type use and a prefix every single time you import 10 things from the same namespace. It's pretty awesome. I've just lost focus too because apparently I have to re-authenticate to the Wi-Fi network. All right. So when can you have all of this wonderfulness? Let's assume I've sold you, let's assume this 50 minutes hasn't gone in vain and I've sold you on how good all of this is. The good news is it's really soon. We're currently in the process of shipping release candidates. We shipped release candidate three last week, which means release candidate four or the final release, but it'll be release candidate four. We'll be next week. The expectation is we'll have a few more. You know, the more changes that you make in a version of PHP or any project really, generally the more release candidates you have. PHP 5.4 had eight of them and PHP 5.4 was smaller than this, so hopefully it doesn't go too much beyond that but you never know. The target date for this when we set out a timeline months and months ago was November. We're tracking pretty well for that. We're releasing a release candidate every two weeks that may go to weekly at a certain point, depending on if we get to the point where it's really just one or two bugs each release candidate might go to weekly. But basically it's the classic open source process. We keep shipping release candidates until nobody reports a critical bug after the last release candidate and then that becomes the release. It's gonna be pretty soon. Like I think it will be this year. It might even be in the next couple of months if things go really well. You can already get this too from a number of places. Homebrew now has packages for this. There are, Andre Suri has Debian packages. Remy has RPMs. They will work on Ubuntu, Debian, Red Hat, CentOS, the usual things. These are again links. You can go find them later if you need to. So there are pre-built packages available for common distributions and they're built in ways that match the normal system packages for those distributions. You shouldn't have to go in and reconfigure how, say, PHP, FPM starts or something like that. It's pretty much the same thing. You can also build it yourself. If you've built PHP before, PHP 7 is exactly the same. The dependencies haven't really changed. It just builds the exact same way. If you haven't built it before, maybe don't do it in production, but it's actually an interesting learning experience. There are instructions on the website. There are many IRC channels where you can get help. It's probably worth doing at least once just to try it. Finally, turnabouts fair play. We're still on the release candidate stage for a reason. We don't necessarily feel that what's there is completely stable right now. I think it's pretty good. I've been running a bunch of production sites on it, but I'm also insane, an Australian, but I repeat myself. So don't necessarily go ahead and do that. But what we really need people to do is test their sites on PHP 7. And this goes double if you're running Drupal 8, in which case you are very brave and thank you. You should totally test your Drupal 8 sites on PHP 7. Drupal 8 has good PHP 7 support. And if you find a bug, please report it. Please, please, please. Because without people running tests, we have a test suite. We all run sites, but the reality is everybody who works on PHP has been running PHP 7 for long enough now that we've run out of bugs to find. Like, you know, we've found the bugs that affect us. We need to know the bugs that affect you because that will help make PHP 7 that much better. So please report bugs. If you can figure out how to fix it or at least write a test case, send PRs. There's a contributing markdown document at the top level of the PHP source. It details how to create a pull request, how to contribute code. I would also love contributions to the contributing document too. If there's something that's not listed in there that you figure out, please send a pull request for that. We'd love to merge it. So that brings us to the end of PHP 7. We've got about six or seven minutes for questions. There is a microphone about halfway down on that side. Please rate my talk on the Drupalcon website. And also, as I said, please read the migration guide because there's lots and lots of good stuff in there. Thank you very much. Hello. Hello. Does the fact that there is weak and strict type checking and you have to choose between them mean that a difficult decision was dodged? Yes. So when I said there was a thing I voted against, that was actually the thing I voted against. I would have preferred just to make a call and stick to it. But basically, I mean, it was, I mean, scalar type hints have been on the agenda since at least PHP 5.2. The idea's been around for a decade at this point. So I think at the end of the day, if that compromises the thing that got them into PHP, then I am willing to overlook the ugliness and just go, hey, we improved the language. But yes, we totally dodged a question there. All right, let's see someone else moving. Hello. So obviously, thank you for the show and all the work with PHP 7. So one thing that obviously Facebook is now working with the HBM, do you know if they will have any plans of adopting these features to HHVM or are you just proceeding with hack? I don't want to put words in Facebook's mouth because I don't work for Facebook. My understanding is that they are in general going to merge features back into HHVM. They intend to make, when not in hack mode, they intend to maintain source compatibility with PHP, including PHP 7. So I don't know their timeline on that, but my understanding is that, yes, this will all appear in HHVM in due course. Okay, thank you. So regarding variable variables, are you saying that the variable single arrow, curly brace, dollar sign, whatever, that's gonna stop working? It will keep working, but it may stop working for you because the associativity has changed on a lot of those. So let me go back. Bear with me. Let me see if I can find this. Okay, went too far. Back. Okay. So I probably skipped through this a little too fast. So basically, all of these still work. Like none of these will generate parse errors, but the meaning of them has changed. So I mean, if we always use curly braces, will it continue to... Yeah, oh sorry, yeah, I misunderstood the question. Yes, so basically all of the examples I showed there with either parentheses or curly braces, those will all work on PHP five and seven. So you can use those to just manually tell PHP exactly what associativity and precedence you want for those expressions. Okay, thanks. There is a path, you can do both. All right, I don't see anybody else moving towards the mic, so I think we'll wrap it up there. Thank you very much, you've been great. I'll just leave the link to the slides up for a minute. I will tweet this as well in a few minutes.