Unconventional PHP (Talk)

Liam Hammett talk about unconventional PHP
(Image credit: Liam Hammett)

You might think you know PHP, but if you dig below the surface you might find it can do more than you knew. Beyond the documented features, there lies a world of tricks, hacks and other techniques that can allow PHP to go a step further.

In this talk we’ll look outside the box at some things PHP provides like references, autoloading and magic methods and explore how using them in an unconventional way can benefit our own code.

Video Transcript :

Hi if you don't know me i'm liam hammett i

do a lot of stuff with php particularly around the laravel ecosystem and today i'm going to be talking to you

about unconventional php um we'll be going over some of the ways that you can use php in a way that you

probably haven't thought of before if you're a beginner with php it might be a little bit hard to follow along

with some of the things but i'll try to explain everything as clearly as i can if you've got any questions then

please ask them in the chat as we go along and i'll try and clear them up at the end if you've worked with php for any amount

of time you'll probably know that it has a lot of ways that let you interact with php source code itself so pitchfield

gives you ways that you can sort of reflect on classes and values and you can pass tokens of source code you can evaluate

new source code on the fly you can serialize objects and you can do so much more

and i expect a lot of you watching this to sort of have this gut wrenching reaction to some of the things we're going to go

over and think they're horrific you won't be seeing most of these techniques that we're going to go over

in the php documentation or in any of those well-known books about design patterns or following solid

principles but that doesn't mean that these tricks can't be useful and i'm not going to go and tell you to

immediately go and use all of these in production code either but i would kind of want to have this talk to make people aware that there are

options to write php code in sort of new interesting ways

we're going to be going over a couple of things where we can bring functionality that's already used in production frameworks like laravel

we'll be seeing how to make the most out of some of the other technologies that we've already got and how we can add to them

and we're going to have a little look at how we can enable certain functionalities that other languages support but php doesn't yet

but before we look at what future features we can find i kind of want to stop and reflect on the past to quickly talk

about what initially prompted me to give this talk so that we can see how techniques like

the ones we're going to go over today have been useful in the past and therefore why they're still worth

discussing so a few months ago i was trying to find some documentation

on php.net and i came across this page about type hinting and the page was pretty empty so the

user contributed comments so jump to the top of the page and i started reading the first one

and it was explaining how to be able to type in your function arguments with primitive types like denoting that this

argument must be a string or that one must be an integer and that might not sound very interesting but

what jumped out about this to me was that this comment was from 12 years ago it was from 2008 and at the time php 5.2

was the latest version and if you've not used php for that long you might not be aware but

you couldn't actually type in perimeter values like this until seven years later when php7 came

out in 2015 and so this kind of blew my mind because

someone managed to build this highly wanted feature that will run in any php environment

seven years before the language itself supported it and even better than that it turned out that it was the exact same

api that we got in php7 so upgrading a project using this technique

was completely effortless so i want to quickly see what the problem is and show you and see how they solved it

so here we've got a simple function that checks if a string is a palindrome so if it says the same reading backwards as it

does forwards as you can see this kid's being executed against php 5.2

and we've type into the value as a string which like we said wasn't actually possible in php 5.2 so

when we try to call the function we get an error and there is a bit confusing it says

argument 1 pass 2 is palindrome must be an instance of string string given

that's because string wasn't actually a reserved type so it was expecting us to get a class with the name string but we gave it a

literal string so let's now have a look at how this post from 2008 on php.net actually

managed to make this work and here's a slight variant of the code that they wrote to get this working that

i just wanted to quickly look at the main thing that it does is that it sets an error handler

so whenever php encounters an error it will run this function to do some custom logic

so there's a lot of stuff here but we're just going to go over the important bits

one of the first things that it does is it checks the error message that came up from the error and make sure it

matches a certain pattern so we're matching it against the pattern that we just saw so

argument a must be uh argument a pass to b must be an instance of c and so this way

we know that we're dealing with the right error once it's done that it goes on to use this debug backtrace function

which is a special utility that php provides and what it will do is return a list of

all the functions that were called to get to this point in time and along with any extra little details like what values were passed into those

functions so now we have that debug backtrace and it passes it into another thing

that we'll go over and basically iterate over every function that was called until we find the one that triggered the

error and when we do that we actually also pull out the value of the argument which we can

then use to assert against so once we've got that we've got we know

what type we're wanting to hint against we know what the value is and we know that we're dealing with the right error

so we really have to do is check that so here we've got a little mapping that gets called

so in our palindrome example we type into the value of the string which maps to

the is string function which is something that php already provides

so if we've passed it through a string and we're checking the string function it will sort of return

true and returning true from an error handler sort of tells php okay pretend like this error didn't

happen and just continue running the code like you were before

and if none of those conditions were met maybe uh it wasn't actually string that we

would that we were passing through or maybe when dealing with a different error then it will return false and that

tells php stop and continue executing the code like you were before that's kind of it now the only change we

need to make to the initial code that we had was to make sure that we include this error handler and it suddenly works

and with only like a few lines of code that now we understand we could use this

nice syntax to check if a value is a string all the way back in php 5.2

now that might not seem particularly relevant today hopefully everyone watching is running recent versions of php already

but the idea of that is to show you that php isn't just a closed box of documented things that you're allowed to

do if you think a bit more abstractly you could make it do a lot more and here we managed to introduce a clean

native feeling syntax into php seven years before php got it itself

so so step back and think what will php like what will php be like seven years from

now in 2027 what features from then would you like to have but you don't have to wait

nearly a decade for it and that's basically the premise of this talk today

so the first one i want to talk about is typed variables and this is something that nikita one of

the primary maintainers of php talked about when php74 was first released

and that's because it's only now possible with the new features it introduced but when you heard about php 74 coming

out you probably didn't hear about typed variables and that's because it's not really a first party feature

it's something that we can kind of make work so let's say we have a variable i but we

can't be sure what type it is it might start off as an integer but it can be reassigned to something else later on so in a nutshell typed

variables is a way to prevent that and make sure that the variable doesn't change its type later on in the program and we

might start protecting something like this by wrapping it in a function and this way we can ensure that the

initial value is always an integer but it still doesn't check for it being reassigned later

so unless we call this function every single time we change the variable it won't get type checked so see how we

can make this function actually do what we want it to we've rewrote a little bit here

so that it basically does the same thing we're creating a class with a type

property called prop we're assigning the integer to that property and then we're returning the property

and on its own this has no different effect in the previous code and that's because we're just returning the value

of the property at the time but the interesting thing is if we tried to change the value of that property

php would throw a type error because it can only be an integer and it can't be a string

so we need to do a little bit more to get that working and the first thing is to add uh is to add these ampersands to

uh both the assignment and the function and that will tell php that instead of returning the real value of the property

we just want to return a reference to it we want to return a reference to the property on that class

and that's important because it means that now when we reassign it it's treating it as if it should be

reassigning the property on the class 2 and it will validate the type as we do that and

that wouldn't happen with regular argument and return type pins and functions unless you pass it through to the

function every time so there's only one last little caveat that we have to worry about here which

is peach piece garbage collection and this is what php does to try and free up memory by getting rid of

things that we no longer need in this function when we return php

thinks that we no longer need the object at this point and we only need the property value

so it'll completely get rid of the object meaning that we're not dealing with the types properly anymore

and somehow we need to keep the object alive so that it is a real object and property even after

we've returned from the function and one kind of simple way to do this is just by adding it to

a superglobal variable and that means that the object will always be referenced in memory

even after the function's returned to value and this means that php doesn't destruct

the object so we're attending a real reference to that property which still has the type against it and magically now that works

now when we reassign the variable to a string later on php will try assigning it to the type property

and it will throw that type error and just to show this works we can still reassign the variable to something else

later on as many times as we want but as soon as it becomes a different type it'll throw an error that you can handle

and this approach may seem a little hacky but it now lets us protect variable types in our code in a way that we just

previously couldn't in php and this can have huge benefits for long procedural code

i'm just going to have the super water

so the next trick we're going to go over is called function piping which is

something else that can help with a lot of procedural code problems what do i mean by piping you might be

familiar with the term if you've used a language like bash where it's a commonly used feature but

simply put means taking one value and piping it into another function so to start off let's see what problem

this solves we've probably all seen code like this at one point in our careers

it's a single line that does a mishmash of things and it's really hard to read here it doesn't even fit on the screen

so let's split it out to make it easier to see what's going on so essentially this code is just getting

the event id from the given url but it's so hard to read and understand that

what i hate about this the most is that it just doesn't read very naturally you gotta start off in the middle to

figure out what the initial value is and then use that in the context to read a bit further out to see what that does

and then again and again so you get the whole context of what the final value is

so we could rewrite that code into something like this which gives us the advantage that now we can see what the initial value is

and we can read it from top to bottom until we get the final value but i think this still isn't very nice

it's better but it's not clear and you probably don't have to spend time coming up with a name for every

step along the way after all naming is one of the hardest things in programming

so incomes the pipe operator rfc which was proposed by sarah goldman a

few years ago the idea of this rfc was to introduce a

new syntax to help make code like this easier to read and so this is what the new syntax would

help make our same code look like and i think this is a lot cleaner personally and you can read it from top to bottom

without having to worry about the intermediary steps it introduced this new dollar dollar

symbol and that represents the last value from the function so that you can sort of decide which

which position in the function arguments you want to pass it to but unfortunately this rfc didn't pass

so this code doesn't work for now however with a bit of effort we can

actually get this very similar syntax working ourselves today in php it's so

similar i don't know if you even were able to spot what the difference is so just like before we want to

pipe a value through some functions and get the result so how do we make

that work well we started off with the pipe function where we passed in the initial value

so we'll have a pipe function and this is going to return another object

the object isn't very special to start off it takes in the value and saves it as a property that we can reuse later on

but the real magic happens inside this magic call function and this is a special function that php

provides that makes things behave in a bit of a special way essentially whenever a

method on this object is called and that method doesn't exist on this class this underscore underscore call function is

going to be executed instead and that lets us do our own custom logic instead of php just throwing an error to

say this method doesn't exist so firstly it checks if any of the arguments passed at the function

match that special dollar dollar syntax and if so then we replace that dollar dollar with the real value that we got

then it moves on to this cool user func expression and this basically passes through the

method name that we got and executes a real php function with

them so for example when we try to call arrow pass url

then that would come through here and php would execute the real core pass url function with the

arguments that we gave it and then the final thing the cool match the magic call method does

is it returns the new value um but again in another pipe and that means that we can chain as many

of these cool methods off of it as we want but when we do want to stop that chain we have this get method where we can

just return to real value and stop stop the piping

so cool now we know exactly how this code works and it's only really a few lines long behind the scenes the pipe function returns an

object so that we can call methods off of it when we call methods it just so happens that we're using real php function names

but they're going through our custom cool function and when we want to stop the chain and get the real value we can

just use the get function now there are obviously some downsides to an approach like this one of which

is that because it's treating them as class methods instead of functions you could lose ide support it wouldn't

know how to tell you what the arguments for these methods are because the methods don't really exist

however this might be an approach that can help you clear up lots of ugly long procedural code that you have around

like this example

the next trick that i want to go over is static constructors and these are a concept that a lot of

different object oriented languages have but unfortunately php doesn't really have first party support for them

so if you're not familiar with the concept a static constructor is just a function you can add to a class and that can be

used to initialize any static properties or to perform any actions that only need to be done once for that class

let's start off and just have a little look at what problems static constructors could help solve

here we've got a simple class that can get us a list of countries by reading them from a json file it's

pretty straightforward but it has one problem every time we want to get the list of countries it's going to read and decode that json

which can be a pretty slow operation especially if we do it a lot so instead

we might use a technique called memorization so that we only read the file once now with this updated code it'll only

read the file once and it will save the results to the property and that means that we can call this function as many times as we want and it

will have the same result without opening that file again and again and this approach forces us to go

through a getter instead of accessing the property directly because we don't know if the property actually has values

this is a pretty common pattern in php but sometimes we might actually want to interact with the property

so let's take a look at what this might look like if we do it with static constructors but just before we do that let's

understand exactly what a static constructor is and what rules it needs to follow so a

static constructor is a static function that belongs to a class and it should take no parameters because you

should never really be calling it manually in your application it should only be called once we don't

have to call it several times over it should be executed before any

instances of the class are created before any static properties are referenced and before any other static

methods are called so really it's just a simple function

with nothing special about it all we need to do is make sure that it gets called once before any of the things in the class

gets used so let's set one up here we've got a

function called underscore underscore construct static and this is just to follow the naming convention of php's regular magic

methods but there's nothing really magic about this one yet it just loads the same file into the property just like we did before

so how do we make sure this function actually gets cooled before we try and access any values or do anything with it

it must be hard to build something that meets all those rules right well what we really have to do is call

it in the same file that the class has defined and that's kind of it this means as soon as we try to reference the countries class

somewhere this file will get autoloaded which means it'll first define the class

and then it'll execute this function immediately before you can do anything with it and this is such

a simple and straightforward pattern but it can give you a whole new way to hook into classes and do some kind of logic

of your own and it's not just limited to initializing properties either you can

do whatever you want in this function so let's take this example of a

controller in a laravel application the gist of a controller is that you hit a specific url in your application

and it'll figure out what controller needs to be used for that url and then it might return something like

an html page or an api response but we don't really care about what the controller does in this case

but how do we know what url should map to this controller

typically in laravel and in most other frameworks you will have your roots defined somewhere in a file

or an array that sort of maps the url to the controller that it should use and this can be kind of nice because it

gives you one file that you can use to figure out where any request hitting your application starts off

but we could also use static constructors for this so by defining the route in a static

constructor instead now this root definition is part of the class it sort of belongs to it's all in

one file and grouped together so you don't have to figure out how different parts of the application

come together and where those bits belong and this is just one example of how we

might use it but there are plenty more possibilities that different applications might be able to make use of

but remembering to call this construct static function at the end can be can be a bit of a hassle though so what

if we could make it so we don't need to put that in every file income custom auto loaders and this is

hands down one of my favorite ways to make php do interesting things if you're not familiar with what an auto

loader i'm going to quickly recap if you try to use a class in php it

might not be aware of what that class is because it's not loaded those files in yet so it'll throw an error so php provides

this handy spl auto load register function and that lets you hook into this event so that

when php doesn't know what a class is you can do some custom logic to try and load that class in

here we've got the simplest possible auto loader where if we try to load a user class it'll try

and load the user.php file which should define what that class is

autoloading can get quite complicated though if you're loading things from lots of different directories and using namespaces

maybe including third party packages the auto loading code would be an awful lot more complicated than this

so the php tool built uh php community built a tool to do this for us

and odds are if you've only been writing php within the last seven or eight years you've only ever used composers to do

this stuff for you and you might not have even been aware that you could write your own custom auto loaders

and composer in its autoloader is great so when i talk about custom autoloaders i don't mean that we should replace it

with something else instead what i mean is that you can have more than one or two loader active at a time so you can do extra stuff on top of

what composer does or even before composer's done its own work

and autoloaders are typically meant to load files automatically it's kind of in the name but they don't really have to

do that they can do whatever you want so let's write one that will automatically call our construct static

function for us so here we're requiring composer's own

autoloader then we define our own custom one that will run after composers done

since composer already loaded the file at this point we can just check that the class already exists and has been

autoloaded but we want to make sure that we pass through the autoload false flag so that we don't accidentally get into a

recursive loop and try to autoload a class that we already know doesn't exist

and then if that happens we can just check if the loaded class has a construct static method on it

and if it does we can just call it now we don't need to include that line at the end of all our classes

you just use a static constructor and i want to add a bit of a disclaimer

that it's not actually quite this simple to add an autoloader into the chain to run

after composer there's actually a little bit more logic you've got to do to hook into when composer has autoloaded a file but

it's absolutely possible and i can share a link to a plugin that does that already if someone wants after the talk but the

theory is basically exactly the same as this example shows

so keeping on theme with static constructors i want to quickly look at how we can use them to

enrich our applications with a new feature of php8 and that is attributes particularly

class attributes so let's go back to this example of a controller and

remember that it needs a root defined somewhere that maps the url back to the controller

instead of using a static constructor like we did before let's take another approach to it and

see how this might be looking if we use an attribute

so here we've got exactly the same control as before but where's one notable difference

now we're defining a custom attribute on the class and that defines what the url should be

if you're not familiar with attributes they're essentially meant to be a replacement for most doc block comments

but because they're not just comments they're actually a first party feature in phpa and that means that they can get a lot

more powerful they can actually map to a real class and that class can contain logic

so let's look at what that class might look like it's a pretty straightforward class to

start off all it's doing is accepting the message the method and the route that we gave it and saving those

as properties for us to use later the thing that stands out here is that there's actually an attribute called

attribute defined on the class which turns this root class into an attribute so let's see how we

can make use of this new one that we've defined again we've got an autoloader function

and this will trigger whenever we reference the class so in this case we care about when the controller is being referenced somewhere

so using the reflection class object we can actually inspect what the controller is and get

some information about it such as what attributes has got and from then on we can it iterate over

all of the attributes that it's got and find when we have the root attribute that we defined

and when we have that we can just call this attribute new instance method and this will create a new instance of that

root class for us and interestingly this will actually have it with the parameters that we gave it when we added

the attribute to the top of our controller so now that we're loading the custom

attribute and it has the parameters we want to use let's make it do something we're going

to add a new register method to the root class and this will do all the work that we want really

this new function is going to accept the controller's class name and then we're going to use it to register a root exactly like we did before in the static

constructor now in our auto loader all we have to do is call that register method and give it the controller's name that we're loading

and we're done so with just a few lines of code in an autoloader and making a

custom attribute we've kind of introduced a whole new way that you can set up routing for your application that might appeal to you

your root in the controller can be kept in the same file and again this isn't the only thing that

attributes could be used for you could do whatever logic makes sense for your application or class

you might use this approach to apply a middleware to a controller and an orm like doctrine or eloquent

might use it to define what database columns belong to a model and i'm sure we'll be seeing many more

interesting uses of them as adoption of phpa rises as it gets released in a few months

custom auto loaders can do quite a lot more though and i think hands down my favorite one is

real time classes and this is a super interesting way to use an autoloader to

make some magic happen and essentially what i mean by a real-time class is that you can just create a new

class file kind of on the fly in real time even before composers try to load it in

and maybe even more interestingly than this laravel has this as a first party feature called

real-time facades and it's got quite a lot of use and adoption over the laravel community

um so to rebuild real-time facades let's quickly look at what a regular facade is and how it can be useful um so we're

going to start off with a pretty basic class to send an email it lets us set who the email is going to what the

subject line should be and what the body of the email is and then when we're done we've got a method to

send it so when we use this class we firstly need to make a new instance

of it and then we can call the methods off of that in whatever order we want

so the thing that facades will do is they'll get rid of that step where we need to make a new instance of the class and it does this by making all

of the methods on the class available as if they were also static methods

so we can take this and basically get rid of this first line

the facade class itself might look like this it's a completely separate class and

it just defines a cool static method and just like the magic call method before

this is kind of special and whenever we try to call a static function that doesn't exist on the side class

it'll call this instead and pass through the parameters that we have and so this cool selling method is just

doing exactly the same as we did before it's making a new email object and then calling the same method of that

instance so it's pretty simple really and when we

try to use it we get this new interface where we don't have to create an instance of the email class we can just call any of

those methods as if they were static to begin with and then change things off of that and

laravel's own facades does a bit of extra magic behind the scenes so it does stuff to automatically do

dependency injection and to make the facade classes mockable so that they're easy to test

but the simplified version is good enough for our use case we don't really want to have to create a

new facade class every single time you want to use this functionality though so how can an auto loader help

so again the spl autoloader register function actually has a couple of extra parameters that we can give it and notably it gives

us the option to prepend our autoload function to the start of the autoloading stack

so if we set that to true normally that means that our own autoload function would get called before composers done its stuff

so we can override the default behavior to find the class and by the way this prepend colon

syntax is actually valid in php 8 with named arguments

um so what if we want to use this to write a facade class on the fly in real

um time going to add a bit of logic to our autoload function and we're going to have a convention here so that if we try to

load any class whose namespace starts with facades we're going to assume it's a real-time

facade and run our custom logic we're also going to make a new facade directory to put these

files in at this given path and we're going to make sure to hash the class name to jaw1 just to deal with any special

characters that might be in it so now that we know what path we're

going to put the file in the first thing we can do is check if it already exists if it does we can just load it and

return true to stop trying to autoload but if it doesn't exist we still need to

make it so the first thing we'll do is make sure that the facades directory exists and then we'll touch um we'll touch the

file path just to create an empty file and now we need to populate that file with something

so to prepare for that we actually need to figure out what the real class name should be by stripping the facade bit from the

start of the class name and that's because we need to actually use it in the file that we're going to write

and after that to write the actual php class to the file we just need to literally put the code there we can have

the raw code as a completely plain string and we have the real class name into

that so that the final file has has the right class name and can create an instance of the correct class

and then we just send it through the file put contents function into the empty file that we just made

and the last step that we need to do to get that working is require the newly created file to

load the class and then return true to stop php moving on to compose zone autoloader

and that's kind of it now we've managed to make this autoloader that will generate brand new files on the fly when we

demand them and now that we're done this is how our final clip might look like

so long as we have uh autoloader running then we can prefix our email

classes namespace with facades even if that facade email namespace doesn't exist yet

and we can call any of the functions off it statically even if they're not static methods on the real email class

and here we can see what our folder structure might look like after our auto load is run where the

facades directory contains a file aimed with a show one hash that we gave it

and now this will work with any class whatever uh whatsoever anywhere in your

code base so long as we import it from that facade's namespace and so you're probably wondering isn't

this going to slow down a code base a lot if it's got to create new files all the time and the answer to that is that it only

really has to make the file once and then it's saved and it can also load like normal

and it'll only do it for each facade class that you try to use in your own code base it won't do it all the time

for every single class that you have in your code and as soon as this

file's be been created it can also be loaded into op cache and has

full performance benefits just like any other normal class does and they don't really have to clutter

your get repository either because they can be made completely on the fly you can get ignore that

facade's directory and it will just generate them when it needs to that first time

and now again this is just a small convenience in this example but you can use this technique to create

any classes you might want on the fly or even add more functionality to the facades here

but now let's take custom autoloaders and real-time classes to the extreme and let's talk about pre-processing

you're probably familiar with front-end pre-processing with tools like sas and less that

compile a similar syntax down into plain css and there's also bible which lets you

take your javascript and automatically rewrite it so that javascript works in any browser

but what you might not know is that we can do that exact same thing with php on the back end

so there's this tool from christopher pitt and it's called pre and i think the tagline speaks for

itself it gives you syntax you like that runs where you need and essentially

this is a composer package that you can just install into a project and it makes use of a custom autoloader

and it'll pre-process your source code as it gets loaded so that you can write php with

pre-custom syntax on top and this package will rewrite it into a file as plain php so that it can

get run by the php interpreter and it's kind of exactly like how real-time classes work before

but this is to a much more extreme level and bree's already supported a lot of

the things in the past that we've eventually managed to get into the php core like allowing trailing commerce and a

list of function arguments and being able to use short closures but it can still do so many things and

unlock so many new ways to write code that we just can't do in php today and i've

got a quick couple of examples i want to quickly go over so one thing that it can let you do is

set dynamic values in your properties directly so if you want the default value of a property to be the result of

a function call or maybe an instance of a new object you can't normally do that in php but

pre can do it for you and unless you do the same thing with

function arguments as well there's also a pre plugin that allows

you to write html literally inside your php code just like we can do with

react and javascript and jsx

we can make operations asynchronous with the async await keywords just like we used to in javascript

instead of plain arrays you can create collections that are array like lists but have a lot of extra

useful functionality built in you can even defer bits of code to be

executed at the end of a block so for example we can open a file and

immediately defer that file to be closed and that doesn't mean it will immediately close the file but it'll do

it at the end of the block which lets you keep the closing logic close to the open stuff instead of having 50 lines of other unrelated code

in between and like i said before i don't think we're actually allowed to have a php

southwest event without mentioning this for dave because he absolutely loves generics

where you can add a type into a class and that type can actually be different depending on how you instantiate the

class and as you can see these are a lot of features that i'm sure we'd all love to

have in php today and tools like pre actually make it possible to use but even this is still just

sort of scratching the surface we can still do all of these things in php but just

a lot more verbosely than pre allows us to do so for something more powerful that we

can't do in user land we can turn to extensions

and a lot of people think that extinctions only introduce new classes they see things like the

redis extension and the dom document extension and all they really give you is a new

class that you can interact with but extensions can actually do a lot more to php

they can introduce new syntax new core functionality and they can just unlock things you've

probably never even thought of the first one i feel obliged to mention

is called swool and this is an extension that can basically replace php fpm in your web

server stack and doing that gives php native async await functionality you can also

run code in code routines you can manage your php processes with it you can

host web server sockets websocket servers with php and even just using it significantly

improves the performance of a php application out of the box even if you don't use any of its other features

so if you're if you're serious about writing php apps that are more than just a typical web app i think

you should definitely check that out uh the next extension i wanted to mention is one by

nikita popov and this offers a different way to interact with scalar values like strings and integers

and unless you treat them like objects so this extension gives you a new

function where you can register a primitive type handler and you can do this by giving it the

type that you want such as a string and pointing it at a class where you want that class to be the object that

gets dealt with that string so now if we have an instance of a string

we can call these methods directly off of it as if they were an object to begin with

and i think this is a super interesting idea personally because you can essentially use this to define

your own way to interact with php completely maybe you don't like naming inconsistencies in some of php's core

functions i know i don't and maybe you can't remember if needles or haystacks come first

so you can actually use this to define your own version here without having to affect how php's

functions currently work and without breaking any backwards compatibility

the last extension i want to mention is another php core contributor sarah gilman and

it's called operator overloading but what is it uh php has a wide range of operators that

you can use to compare two values to one another or to add them together or to concatenate strings

or so on but typically we only really think about using these with the primitive types like integers and

strings but operator overloading is a feature in a lot of other

object-oriented languages that actually lets you run custom logic when you use an operator on

one of your own classes which can actually make it feel a lot more natural to use and you might

not be aware but php already does this internally in a few of its own classes

for example if you want to compare two date time objects together php will realize that if you're using

the greater than or less than operators you probably want to know if one date came before or after the other

and this makes it really easy to write and read this code so the operator overloading extension

brings this kind of functionality to our own classes in php

so we'll take this example quickly where it might come in handy we have a class that represents how much

money something is but it can support multiple different currencies so if we try to add two money objects

together it would just throw an error normally in php but with this extension enabled it'll actually

call this magic add method and that lets us do what we want to figure out how to add the values

together so for the example of money we might want to convert the value from one

currency into another and that lets us add the two values together

but the thing about operator overloading is it's not just limited to numeric values either you could do whatever

logic you want here so long as it makes sense you might use the additional operator to combine two collections into one

or maybe you want to replicate bash's double angle bracket syntax so that you can pipe a string into a

file object and there are a couple of extensions

that we can use today but what other opportunities can we look forward to in the future php8 is just around the corner it's

being released in november 2020 and there's already betas available to use

and it brings a lot of nice new features but it also brings a couple that we can use in these unconventional ways

the first one to mention is weak maps and weak references and these let us reference objects

without interfering with garbage collection and this brings forward a great way that we can

share objects around multiple parts of the code base but without keeping them in memory and sacrificing performance if

they're not needed and this just isn't something that we could reliably do before so we had to resort to other patterns

another one that we've already explored is attributes um we've explored one use case but

there's plenty more out there attributes are present in java in javascript in python

and so many other languages and they've already got a lot of different uses across all of those and now we can bring them to php and

like i said before dark blocks did some of the works attributes could but now attributes can do so much more

because they can have a real code attached to them and they can even go in more places than dot blocks could

and that's kind of all i have for you today hopefully it's made you think a bit about how powerful php can

be as a language and how you might be able to get some future like syntax and

tools that can help you improve your own applications and i want to clarify that i'm completely

aware that everything we've covered here is a little bit weird and if you're looking

at it for the first time or you've got a team member looking at you implementing this for the first time

it might not be obvious what they're doing so these techniques may not be suitable for every scenario and even if you don't use

these techniques directly hopefully in the process you've learned a bit about autoloaders magic methods references and

some other things that php provides that you can work into your own applications maybe in a more conventional way

um yeah that's it feel free to follow me on twitter or check out my site where i occasionally talk about doing wacky

stuff with php there's a link to the slides at the bottom there but i'll make sure to tweet our link to them later too

if you've got any feedback for either myself or naomi please leave it on joined in and thanks to php southwest for having

me wow thank you very much for that that's

that was really interesting that was a i've got so many questions um but if

anyone else has got questions uh please can you add them to the the q a um

i had one question i think i was just probably missing something in your root example um when would the roots get auto loaded

that is the one thing that i didn't actually mention um if i can find it again do you have to

work out what all the yeah i couldn't really work that out so uh which one was it i guess in either of

the examples with the attributes or the static autoloader yeah somehow load that class in first

and loading a class is actually kind of an inexpensive thing you can do in php so you can iterate over a directory and

just load everything in it i see so you've had a convention your controllers in one place you just

iterate through all of them more yeah okay

cool thank you um right question from dan uh why do you

think a precur why do you think a pre-compiled step is so standard in javascript well but so

rare in php is there anything we can do to make pre-compiling more common

i think it was needed in javascript for a long time because um you don't know what environment your

code is going to run in if it's going to run in an old version of javascript from 20 years ago in like ie4 that someone's

using somewhere because someone probably is but in php we've got control of the server so we always

know what it's going to run in so if we want a new new if we want to use new syntax in php we just

upgrade php but we can't really do that with the user's browser

so that's why i think it's common in javascript but not so well known in server-side languages cool thank you

dan if you want to come back on anything then just add an extra message in there david lum asks uh what

tool uh did you use the line highlights highlighting in the presentation it was really good

um i've got these on slides.com which offers it but there's an open source uh

thing called reveal js which basically lets you make slideshows like this and

that's one of the features of the codeblocks oh wow brilliant um i was a bit afraid of doing um

live coding for all this stuff so i figured this is a pretty good alternative to point at what code i'm talking about

yeah no i like it i like it uh there was that can you can you tweet that out please uh what the tool you use or put it in

the uh yeah sure the channel yeah thanks um

i mean no one else has got any questions oh no there's one more um uh dan asks is there anything we can do

to make pre-compiling more common um i think it's a tough one because

pre-compiling is a it's a really awkward thing because if you if you've got files that don't

have normal php syntax like that then suddenly tools like

some or php cs fixer will see it and they'll go that's an invalid php file i can't do anything with that

so it's kind of this trade-off where if you have non-standard php files with pre-processing you

can't necessarily use all the tooling that php currently has available

so um there's actually a project by um christopher pitt who made pre

and nuna maduro and they're trying to sort of make pre a new thing with like

lots of standard pre-processing rules and i think they they've built a vs code

extension or something to be able to sort of get um syntax highlighting working in it

properly and i think they're working on the integrations for all those other things with their standard syntax

so i it's a bit of a tough one because you've got to also work with all the

tooling that's in the ecosystem to be able to support pre-processed code

yeah yeah say because and they got something like pre

was released ages ago wasn't it and then they're working on something which yeah they mentioned the name but then

put it live yeah sorry php php plus or something uh that was it yes yeah

but but that's still unreleased at the moment uh yeah i think it's still on release

but they are sort of working on it behind the scenes yeah yeah so hopefully we'll see it sometime maybe this year

brilliant um so i've got one other question about the real-time

classes could you use that to kind of get aop type functionality so

specifically what i'd be interested in would be like a uh any attack transaction or whatever

whatever the uh attribute and the format will be but so you could do

attack so in like in java where you can do transaction boundaries so you can just say when you enter this method start a

transaction boundary and when you leave that method you know that you know finish the transaction so it's just you would have

to do something actually so when when the class is loaded you'd have to look at it and go are there any

transaction uh attributes on it and if there is i'm gonna modify that class you probably could

if you paired it with some kind of pre-compiling step but i i don't know how you would do that

in um like for an individual method obviously like the example i gave was

class attributes is because you can auto load a class but you can't really hook into when

a function is being called unless you literally put something in that function uh well so you could just i suppose do

similar to what i mean doctrine have it through a compile stage don't they where they you did you don't use the actual entity

use something that extends that entity and does something different so i could know what i need to do to the

class to modify it yeah and so so you say i want to autoload

uh you know um i don't know personal repository but what it actually

does is it also loads you know my modified personal repository and as part of that there is

you know before you call whatever method it calls another method you know so you're rewriting the code on

the fly yeah exactly and i think there are lots of tools out there that do this already right

aspects mock for conception and that basically puts in a couple of hooks at the start

and the end of every function that you call in the test so that it can sort of do its own checks

oh i'm thinking it's already a possible thing yeah yeah okay cool

uh has anyone else got any more questions no right well thank you very much