Why write PHP on the front end?
Have you ever had a thought in a moment of deep and quiet reflection? Have you ever thought to yourself, I wish I could write more PHP? Fame, I've had the same thought. We've been writing PHP on the back end since the dawn of time, but now we get to write PHP on the front end too. There's no more view, there's no more React, there's no more third JavaScript framework. There is only PHP. PHP on the back end, PHP on the front end, PHP in the past, PHP in the future. Because as if a million voices cried out, but not in terror, in excitement, we love PHP.
What Livewire is and how it works
What I'm talking about is Laravel Livewire. Livewire allows you to write PHP on the front end. Are you actually running PHP in the browser? No. Are you actually running JavaScript in the browser? You bet you are. This is very similar to Phoenix LiveView, or if you're in the Rails ecosystem it's very similar to Hotwire, or I think it's very similar to React Server Components, but what do I know about React? Not very much. What Livewire does is it allows you to write your full stack in PHP and then it manages that network chasm for you. This is what Remix is supposed to do—it's supposed to span that network chasm so we're not worried about writing controllers, we're not worried about writing API endpoints, we're not worried about sending JSON over the wire. We're just writing our regular views and Livewire is going to bring all of that together for us. Enough of me talking about it, let me show you how it works.
Creating a new Livewire project
All right, here we go. We're going to create a Livewire project from scratch from the very beginning so you can see exactly what we're doing. First thing we're going to do is we're going to use Composer to create a new Laravel project called Livewire. So we're creating a new Laravel project in a directory called Livewire. It's going to install a bunch of stuff, so now all of the Laravel packages are in there. We're going to change into the Livewire directory and we're going to say require Livewire. Livewire. So this is going to bring down the Livewire package and now we are good to go. I'm going to open this in the browser just to make sure it is there at livewire.wip. We have the standard Laravel start screen, and if you're paying attention we've got the docs open next to it. Okay, now we're going to jump over to PhpStorm and start actually doing some Livewire. So far this is a standard Laravel application. We haven't done anything special. What we're going to do is we're going to come in here into this welcome.blade and we're going to replace the entire thing with this default boilerplate here. What we're doing is including the Livewire-provided styles at the top and the Livewire-provided scripts at the bottom, and we'll say, 'Hey YouTube.' We'll put that in and refresh. Here we go. Great. Now we're at 'Hey YouTube.' Let's start binding some stuff up together. Let's start making Livewire do its thing.
Creating a Livewire component
One of the core tenets of Livewire is components. Because it's a front-end framework it has components just like every other front-end framework, right? It allows you to encapsulate a bit of view, a bit of state, some logic, some actions, all of that into one logical unit. The way that we can make these is by using the command line helper. So we'll say 'php artisan' and then let's just take a look at what's in the Livewire namespace. It looks like we've got Livewire:make down here and we can create a new Livewire component. So let's do Livewire:make. Let's clear this out. We'll do Livewire:make and we'll just say 'hello world.' And it looks like we were created. There was a class created for us and a view created for us. Let's go take a look at both of those. You see that there's a new directory here called Livewire and here is the view that was created. So we'll say 'hello' from inside hello world. Now if we refresh you'll see nothing changes—we haven't actually put that component on the page. If we come back to this welcome view we can drop out this 'Hey YouTube' and what we're going to put is Livewire and then the name of the component that we just created, which is 'hello world,' and we'll just do a self-closing tag there. If we refresh in the browser we'll see 'hello from inside hello world.' So we have a component, but it's basically just a view. That doesn't seem very interesting, I agree. That's not very interesting. What we want to see is the actual PHP component because now we can start doing stuff.
Data binding with wire:model
Let's put a name of 'Aaron' in here and if we come back to the view we can say 'hello name' and if we refresh that... okay, huh, that's interesting. Now we're passing down data from this PHP class into this view and we're rendering it on the page. That's a better start. So far we've just been displaying data. Let's start actually modifying some data. We're going to say input type equals text and we're going to bind this input. We're going to bind it to the 'name' variable and the way that we can do that is we can just say wire:model equals name. This will be very familiar to you if you're coming from the Vue.js world where you could say v-model—it's the exact same thing. So this binds the input to the 'name' variable in this component. So now if we were to go back to the browser, refresh, let me blow this up for you, so we're gonna go back to the browser, refresh, and look at that. So now 'hello friends.' Now we have bound an input to a PHP variable that lives on the server that's being rendered in the view but we didn't write any JavaScript, right? So, oh wow, that's pretty cool. How is this actually working? Well, one way that it's not working is there's no websocket running, there's no connection that we're keeping open. It's all just pure HTTP. So that's a good thing—you don't have to have a long-running process for this to work. That kind of breaks the spirit of PHP anyway. PHP creates the world and destroys the world all on one request, which is either its great strength or its great weakness depending on your point of view. But there's no websocket to keep running; it actually is all just HTTP. Let's open the network tab so we can see a little bit about what's going on here.
What travels over the wire: serialized state and rendered HTML
So if we open this up we'll switch over to the network tab and we'll change this to 'hello Aaron' and then just for giggles we'll change it back to 'hello YouTube.' If we look at the network tab we see that there are a lot of events that were fired off. So this first one you'll see that the event that was fired off was a sync input with a value of 'a.' So this is Livewire, the front end telling Livewire, the back end, 'Hey, we need to change the name property and we need to set it to a.' Now remember there's no long-running connection here, so all of this data has been serialized on the front end for this component and then sent back to the back end to be rehydrated and then have the updates applied. And that's why we have this fingerprint here—to make sure that nothing was tampered with on the front end, right? So Livewire sends out the data with a fingerprint and then Livewire, the front end, will send that data back with the fingerprint to make sure that nobody went in and changed anything in the front end itself. So if we keep going we'll see that now the name value over here is 'Aaron,' the value over here is 'U' then 'UT' then 'YouTube.' So this is as I'm typing, it's firing off events by default. There is a debounce applied to make sure that you don't just totally spam your server with messages. You can change that; you can change that debounce amount. You can also set it to 'defer' so if you're typing something in and you don't actually want to fire it off until somebody clicks a button, you can set it to 'defer' and that will batch up that request with another request and send them both off at the same time. Very cool. Now this is good to know what is being sent, but what is being sent back from the server? What is being sent back from the server is in the effects. You'll see HTML. It's actually sending back HTML over the wire, so this is why it's like LiveView or Hotwire or I don't know what React Server Components is, but you'll see here it sends back 'hello YouTube.' So it sends back the rendered version of this component with the new data and then it intelligently walks the tree of the DOM and swaps out anything that has changed. So that's why it's like writing PHP on the front end, but really it's sending the data over the wire, it's executing on the back end, it's rendering that component, that view on the back end with the new data, sending that HTML back over the wire along with that new serialized data and that new fingerprint. That's data binding.
Actions: calling PHP methods from the UI
Let's look at calling methods on the back end from the front end. I always love this because there is no controller that you have to write, there's no API route that you have to write. You just have your component and your component is fully encapsulated. We're going to change some stuff here. Let's go back to hello world. Let's do, instead of public name, let's do public count equals zero. We will switch back to the view, we will say that the count is the count, and then we will instead of having that we'll do button type button and we'll say 'increment.' What we're going to put on here is we're going to put an attribute called— you probably guessed it—wire:click. Now what are we going to use as the actual action here? Let's just call it 'increment.' Now this is not a JavaScript method; this is a PHP method. So even though we're writing wire:click on the front end we need to implement the increment function on the back end. So we're going to go back to hello world, we'll come in here and we'll say public function increment and we will—let me have to return anything—we'll just say this.count plus plus. That should be good enough, right? Let's check it in the browser. Close out that, come over here and look at that. We are now incrementing a counter on the back end that is actually on the front end showing up on the front end, but it's being sent over the wire. So let's open up the network tab and watch a few of those and it'll be basically exactly what you expect. So if we check in the server memo of the payload, we'll check in the updates call method and the method is 'increment.' So Livewire, the front end, is sending this over the wire to Livewire, the back end, telling Livewire, the back end, what to do, and then it sends back out the new HTML and it will increment the value on the back end.
Features, Alpine.js, history and closing thoughts
really disliked it until then stay tuned to this channel for more videos about PHP see ya