 Hello, that's better. Hello, good afternoon, Faustum. I hope you're having a great conference. If you just joined us in this room, welcome to the PHP and friends deaf room. I'm going to talk about a dashboard I created using Laravel View and Pusher. So if that's the talk you want to see, keep in your seats. I'm Friek van der Hechten. I'm a partner and a developer at a company called Spassie. Like many of you probably, I'm active on Twitter. My handle is Friek Murza. And I have my blog Murza.be where I talk about modern PHP development in Laravel. I also organize the local PHP Antwerp group, user group together with Dries and Friedrich. If you ever want to talk at PHP Antwerp, let me know. Now my company Spassie has been around since 2003. We built websites, applications and web shops. Our team is quite small. We consist of four developers and one manager. And we specialize in Laravel development. Now we are looking for a new colleague. So if you know somebody that is a very good front-end developer or if you are a very good front-end developer yourself, let me know. First, before I want to talk a bit about open-source software. Now my company uses a lot of open-source software. From day to day, we use Nginx. We use Ubuntu. We use Laravel. And for this, we are very grateful. Our company couldn't really exist without open-source software. I'm pretty certain that many of you have your jobs due to the fact that open-source software exists. Now, because we are so grateful for this, we want to give some back to. And we are pretty heavily creating open-source PHP packages. Right now, we have 90 packages registered on packages. They have been downloaded for now almost 2 million times. And they are being downloaded at a rate of 270,000 times a month. Now, creating open-source software has a lot of benefits. We learn a lot by doing it. We learn a lot by the feedback we get from the community. From the issues they raise and from the PRs they open. We are also forced to write documentation because without good documentation, people wouldn't really use our software. We are forced to write tests because if we change our software or we get PRs, we want to be certain that our software still works. And there is also a bit of a commercial aspect to it as well. If you look at our code, then I think you'll conclude that we know our way around PHP and Laravel very well. And of course, we use our own stuff in our own projects as well. There is a big list on our company site with all the packages that we have published. And I want to humble brag a little bit. There is this website called GitHub Awards that makes a top of the amount of stars that the GitHub organization can receive. And right now, Spassius is at number six for PHP worldwide. At number one is Laravel with an insane amount of stars. Now, about the dashboard, let's take a look at our office. This is our actual office. And you see that in the back, there is a dashboard. Let's step in a little closer. So this is the dashboard that is hanging on our office. The first thing that I want to say is that this dashboard is completely open sourced. You can find the code at this GitHub repository. And this is the actual code that we deploy to our server. Let's take a look at what the dashboard displays. I'm going to pull up a chair. That's easier for me because I'm going to code a little bit too. So the first tile of the dashboard, that is a Twitter stream. And it displays all the tweets that mention one of our repos or our company Twitter account. The second tile, there is displayed all the events that are important for our company. That info is fetched from a Google calendar. These next four tiles, they contain the tasks that each member of our team should be working on. This one really needs no introduction. That is just a clock. I mentioned that we are really proud of our open source work. So we display some statistics about the amount of packages that get downloaded on our dashboard. So this info is fetched from packages. Now at my company, we are all big music lovers. So we want to know which music is playing. And this tile displays the current track that is playing in our office. For this tile, Last of Him is used. Does everybody know Last of Him? Yeah, okay. So this next tile displays the status of our internet connection. If internet is down, this tile will go red. This tile is a 30 minute rain forecast. So at Spassie, we all arrive by bike. And we want to know if it is going to rain when we depart from our office. So that in total is our dashboard. Let's first start with a high level overview of how this dashboard works. The dashboard itself is a single HTML page. And it is displayed in full screen browser. And once it has been loaded up, we won't reload it again because we don't want to see our screen rebuilt the whole time. So that's why each tile will be updated with the JavaScript. And each tile has its own update frequency. So the package's style with the statistics of our packages, that gets updated, I think, once an hour. And the clock obviously gets updated once a second. Now, which technologies did we use for this? Laravel, Pusher and Vue.js. Now, a quick show of hands who uses Laravel here in this day-to-day work. Okay, quite some hands. Who has used the Pusher service before? A little less. And who used Vue in one of the projects? Okay, also a bit of hands. Cool. I'll go gentle on everybody so you don't need to know any of those technologies. First, Laravel. In case you don't know, Laravel is a very nice PHP framework. And for this project, we use the latest version of Laravel, 5.4. It is, Laravel is used to render that initial page. And Laravel will also fetch data from external APIs. So Laravel will reach out to the Google Calendar API, to the last event API to get some information. And it will broadcast a signal. However, new data has been fetched from an API. How does it do that? It will just make an HTTP connection to the Pusher service. We'll see that a bit later on. To talk to those external APIs, we use a few packages. The first one, Spasi, Laravel Twitter streaming API, is used to listen to Twitter, to the real-time stream, throughout all tweets mentioning our company account. The second package, something we build ourselves to, Laravel Google Calendar, is used to read a Google Calendar. And that functionality isn't used in our dashboard, but that package can also write to a Google Calendar. So if you have a project where you need to integrate Google Calendar, take a look at that package. Last of them now playing, that's being used to see which track is currently playing in our office. The packages API is a simple wrapper around the package, around the API that packages exposes. And remember those styles with tasks for each member of our team. Those tasks are administered in a GitHub repository, in a few markdown files. And we use the Graham Campbell GitHub package to fetch the content of those markdown files. The second technology that we use for our dashboard is the pusher service. Now in their own words, pusher provides full duplex communication channels over simple TCP connection. You might know this as web sockets, but I like to call this magic, because it really is magic. It's so fast, it transports the events from the server to the browser. So when Laravel detects a change in the data or when it fetches new data from one of the APIs, it will notify the pusher service via an HTTP connection and the pusher service will via web sockets notify the JavaScript of our dashboard. We're going to see the entire flow in just a minute. Now pusher will communicate via web sockets in real time. It's really fast. It does this also in a secure way. Not that our dashboard displays a lot of sensitive info, but we don't really want the outside world to know which tasks that our team is working on. I should also mention that pusher is a paid service, but they also provide a free tier. In that free tier, you can use, I think, 200,000 events a day and the dashboard only needs 5,000, so you're probably good in the free tier if you want to run our dashboard. The last big piece of technology the dashboard uses is Vue.js. Vue.js, excuse me, is a JavaScript framework that has gotten a lot of love from the Laravel community lately and I can certainly understand why. Just like Laravel focuses on developer happiness and ease of use, Vue.js does so too. It's a very powerful framework, but it's very easy to get started with it. It's easy to learn. Now in our dashboard, each tile is its own component and each component will listen for its own events, so that package style will listen for its own events and when it receives one of its events, when it hears that event, it will update itself with the information from that event. I should also mention that we use in this project the latest version of Vue, which is currently Vue 2. Excuse me. So this is a schema that explains the whole flow. So on the one side, we have the external services. Laravel will fetch info from that. When it finds new info, it will notify Pusher via an HTTP connection and Pusher will notify the browser via web sockets that something needs to be updated. So this is the general flow that you will have to keep in mind. Now I can talk a lot about this dashboard, but it's probably more fun if I just demo it to you. What are we going to talk about? I'm first going to explain how the grid system works, so how tiles are positioned on the dashboard. I'm going to explain the clock tile, because that's a very simple tile. It only uses the JavaScript. Then we're going to explain a little bit more difficult tile, the packages style, and we're going to see the entire flow. And then just for fun, we're going to play a bit around with the Twitter tile as well. Now there will be some live coding and we're going to use an internet connection. So I hope the internet gods are happy today and hopefully all will go well. Okay, let's do it. Let's first take a look at the dashboard itself. And I hope it's big enough. This is a version of the dashboard that is very like to the one we have running in our office. And this one is just running locally on my computer. Let's take a look at the code that powers this dashboard. We're going to make this a lot bigger by entering presentation mode. And if you look at the structure of the application here, then the ones with a little bit of Laravel experience will immediately recognize this as a Laravel application. In a Laravel application, the view side of things lives in the resources folder, in the subfolder views. And we see that we have a single blade view here. Blade is just the view system of Laravel. And if we open that, let me close this out, then you see we have only a very little bit of HTML here. And you can see here that each HTML tag here represents a tile from our dashboard. I'm later going to explain how these tags get converted to real HTML tags. But for now, let's just put everything here in comments, except the current time tile. So this piece can go here. This piece can go there. Let's modify the grid here and put it in A1 and see what the result is. And you can see that we only have a clock left in the upper left corner. Now you should see the dashboard a little bit as an Excel file where all the rows are numbered and all the columns have their letters. So A1 is just in the top. If I want to go to the second row, I can just move it to A2 and it's a row below this. The grid system also has support for ranges. So if I want to make it a little bit wider, then I go from A2 to B2. And that's a feature that I can show off also is that tiles can be used multiple times. So now we have two clocks here. So that's how that works. Now for a clock it's a little bit silly to have two clocks on this, but you see here that we have multiple GitHub file tiles for each member of our team. So that's where we use multiple tiles. So that is the grid system. It's quite easy, but are there any questions about it? Everybody on the same page? Yes. So the question is, is it based on Bootstrap? Actually, I didn't make the CES part of this dashboard myself, but I understand that we hand rolled our own lightweight system to accommodate this. On my blog, a colleague of mine explained the inner workings of that grid system. I'll show you the link later on in the presentation. Okay, let's put the dashboard back in its original state. See that we don't lose everything. Are we back good? Yep, here's the dashboard again. Okay, let's explain that current time tile. How does that work? Well, current time isn't really a valid HTML element by itself, but it signals to view which component should be rendered here. If I open up the project again, all JavaScript in a larval application lives in the resources folder, assets, JavaScript, and if I open up components here and make it a little bit wider, then you can see here that we have a view component for each tile in our dashboard. Now, a view file. Let me open up the current time view file here. A view file is a bit of a special type of file because it can contain many sorts of information. It contains a little bit of HTML. It contains a little bit of CSS and it contains a little bit of JavaScript code. And that HTML CSS and JavaScript is all being used to build up a specific component. Now, in our project, because the CSS is a little bit advanced, we chose to add CSS in one file separately. So in this file, you see only a bit of HTML and you see some JavaScript here. Now, this HTML here, the template, that is what view is going to use to replace the current time tag here. So current time gets replaced by the HTML in this template. You can also see that in this template we have a few placeholders, namely date and time, and those correspond to the state of the view object. So if I scroll a little bit down, then we have a little bit of JavaScript here. And at the heart of every view component lives the state. So these are the two special properties that we are going to work around. And if that's something special that View does, we have two-way model binding. If we change one of these variables, it will re-render the HTML. So another special function in a View component is the created function. This function can be a little bit compared to a constructor in a PHP class. It will run whenever the View component is instantiated. So what are we going to do in the created method? We are going to call a function refresh time so we are going to call that function every single second. And what happens in that method, refresh time, it will just update the date using a well-known JavaScript library in moments, and it will update the time. And this happens every second. And because we update those variables, the HTML will be re-rendered. That's how this works. Anybody have any questions about this, how this works? Okay, then we'll move on to another component, the packages style. So the packages style, that's this one. That's the one that displays all the package information here. Let's open up our tree here again. And if I go into the Laravel application itself, you can see that we have here folder components. And we have a subdirectory here for every tile that our dashboard is displaying that needs some server-side info. Let's open up the packages style. So the fetch totals clause, I mean. So if I go to the top of this clause, then you can see that this clause extends a command. I'm going to come back to this later, why this is significant. If I go a little bit below here, then we have a handles function, and here this function is where the actual work will happen. So we are going to instantiate the packages API, and we are going to perform some collection methods to build up an array with the totals. So how it does that is not that important for the stock, but the result of this function is an array with the total amount of stars, the daily downloads, the monthly downloads, and the total amount of downloads. And what will happen with that array is that it will be passed into a class, a totals-fetched event class. And if I open up that class, what happens here is actually very simple. So every row in that array will get mapped to a public property on the class. Why do we do that? Well, Laravel, by default, when an event is broadcasted, it will use the public properties of that class as the properties that should be sent through that event. We're going to see it live in a minute. Good, so that's how that works. If I go back to fetch totals, I mentioned that fetch totals extended a command class, and that it has a signature. Now, for the people that know Laravel a bit, they immediately recognize this as an artisan command. Artisan is Laravel's task runner. And one of the cool features of Laravel is that it has a built-in scheduler as well. If I go to our console and to our kernel, we can see the scheduler of Laravel, and it's actually quite easy. So Laravel has a console kernel with a schedule function, and in that function you can schedule things. And here the code is a little bit messed up because the screen is not so wide. But here we can see that we are going to perform that fetch totals command hourly. So this command is going to be around hourly. Okay, what I'm going to explain next, let's just fire off the command and see what happens. If I go to my browser again, and let me clear this out, I can make this any bigger, so I hope that it's big enough for you, or I can make it a little bigger. This is the debug console at Pusher.js, and it will display every event that is coming in. Now if I go to the command line, and if I run Artisan here, then it will display all the tasks that are registered. And if I scroll a little bit up, then you can see here that we have dashboard commands. And one of the commands is here, dashboard packages. So let's run that, dashboard packages. And then hopefully if the internet gods are willing, we are going to see here the event coming in. You can see here that we have the information that we have received from the Laravel application. Okay, let's take a look at the JavaScript side of things, how this event is being catched. Back to the code. Let's open up the resource folder again, assets, JavaScript components, and we can see here there is a Packages Statistics component. So it also contains some HTML, and it also contains a little bit of JavaScript. And you can see here that in the HTML, we have a few of those state properties. Of the few instance, the stars, the daily, monthly downloads, and the total. You can see here that the default is zero. This is the default state of the component. Now, you can see here that this component has a special function, get event handlers. And this is what happens when an event is arriving at our JavaScript component. Whenever the packages, totals, fetched events is coming in, we are going to execute a function that receives a response, and we are just going to take off the properties of that response and copy them over to the internal state of the project. And remember when we update the state of the view component, the HTML will re-render. So as soon as this function is executed, new numbers will appear on our dashboard. I can prove that here. So I've just run the packages command. You can see here that the total now ends on 965, and on our dashboard, that should be here 965. So we got that data. If I jump a little bit deeper here, let's see here, then you can see that the component also has a special property, Mixin. Mixin in view is a little bit as the same as a trait in PHP, so it's just a way to combine some functions and apply them to multiple classes. Let me open up my tree here again. One of the Mixins that we use is Echo. And Echo is a library provided by the maker of Laravel to easily work with real-time web-circuit connections. Now if I open up that Mixin, so here is the Echo Mixin, then you can see that this Mixin provides a special function namely created and created. That's a function that will execute whenever the view component is being instantiated. And it will register the result of that getEventHandlers function from the component to the Echo instance. And the Echo instance, that's the thing that does the communication with Pusher. So it will listen for a specific event and you can see here that we prepend appEvents and then the event name, which is PackagesTotalSfetched. And whenever that event is coming in, we are going to execute the handler. So then we are going to execute this function. So that's how that works. And note that this event that we are listening for, AppEvents and then PackagesTotalSfetched, that is the class name of the event that was fired. So if I go over the events here, the PackagesEvents, you can see here AppEvents, PackagesTotalSfetched. So that's what it's listening for, for that class name. That is how that works. I know it's a little bit much, certainly if you don't know your way around Laravel Review, but are there any questions about this? Okay, good, clear or totally unclear. That's also a possibility. Let's take a look at another aspect of the dashboard. So I mentioned that the flow of the dashboard, our dashboard really isn't communicating with the server. It just listens for events to update its state. So you might think that if I refresh the dashboard, that it would be empty, but it is not. All the info is being displayed here. How does that work? We have on our component, let me go back to the component. We have another little mix in here called SaveState. And I hope I can get easily to that SaveState component. Mix-in, yeah, and this is the code of that SaveState mix-in. So this code gets applied on the view component as well. And it has a special property called Watch. And here you can define a few functions that should execute whenever the internal state of the view component changes. And one of the things that it will do whenever data changes is call function SaveState. This is that function, SaveState. Let me close it up, that's a little bit more clear. And what this thing will do, it will just copy over the data of the component to localStorage whenever data changes. And whenever this component is created, it will call function LoadState and that just does the opposite things in a safe way. That's why there's many code here. So it will copy over values from localStorage to the internal state. So if I open up this here, and I really don't know how to make the inspector a little bit bigger, but if I go to the localStorage used by this dashboard, you can see here, very small, that each tile has its own entry in the localStorage. So now if I just delete this one from the packages statistics, now you can see that the packages statistics are back to zero. Maybe this is also a good opportunity to demonstrate that the dashboard is also responsive. So you can display it on any TV that you want. So that's how those two make sense work. Let's go over one more tile, the packages tile. First in code. The package is the Twitter tile. The Twitter tile is actually a very simple tile. Our package makes it really simple to work with a Twitter streaming API. So you can just resolve a Twitter streaming API class out of the container. You can listen to the public stream. And whenever a certain word is mentioned, then an event will fire off, and our Twitter tile will listen for that event. Now I thought it may be fun to not listen for spas here, but to just listen to PHP FOSDEM for a while to see what is happening there. So if I start up here now the task that is actually listening to Twitter, the dashboard, Twitter. So now it's listening for PHP FOSDEM. And now I need some people that send a tweet to PHP FOSDEM and spas.ba. So if you're on Twitter, if there's anybody here, and here we have a random tweet here, you can see that it's working and it works really fast. So it works in real time. Sorry, Wim. So that's how that works. And if I take a look at the code here of the tile itself, resources, assets, JavaScript components, Twitter tile. Then you can see here that we are going to listen for an event, Twitter mentioned. And whenever a Twitter tweet is coming on, we are going to add it to a waiting line. A waiting line is something that we build. If a lot of tweets are coming in, then we put them in the waiting line and we just pick the latest tweet from the waiting line every five seconds to go on display so that they're displaying nicely. So if I go here in the inspector again and inspect the view here, it's a special plugin for Chrome to display the state of view components. You can see here that we have a Twitter tile. And if I open it up here, then you can see here that there's now one object in the waiting line and we've just missed it. Now it's on display. And now there's one back again here, which is displayed there. So that's how the Twitter tile works. Cool. Picture here. That's something we're taking here. Cool. Okay. Maybe one more technical thing that I can demonstrate. So the whole presentation, I used the pushers service to get events. But there is also another way. So I chose Pusher when building this dashboard because at that time, a year ago, that was the easiest way for me to use secure WebSocket connections to do that. But now with Laravel Echo, Laravel Echo is a driver-based library. You can just switch out to another driver and another service. And now it just happens that somebody built a Node server that just mimics Pusher.js, so you don't need the Pushers service at all if you run that Node server on your server. And that's the thing that I like to demonstrate now. So if I go to the environment file of our project, and it displays one key here, but below this file there are all my private keys and passwords that you guys won't get to see. But if I switch this off from Laravel to Laravel Pusher, what is it called? Laravel Pusher server? I hope. Let me start that server. Let me prove that I'm not using the Pushers service. Just turn off my Wi-Fi. Laravel Echo server starts. Let me boot up the server. So this is a Node server that just mimics Pusher.js. Laravel Pushers, I hope I typed it correctly. And if I refresh now, but Laravel Pushers service is not defined, let me check my config file here. Broadcasting, Laravel Echo server. Okay. Sorry about that. Laravel Echo server. And if I refresh now, we still have a dashboard. But I'm using local web sockets now. I also have a task. Let me make this a little bit bigger again. Dashboard demo, dashboard demo. I've made a task which can send a fake tweet. So it will just send an event with a payload that is just saved in the file. And if I send that now, you can see here that dashboard is updating so that we use our local web socket. Cool. That's how that works. So. Cool. The live coding worked. The internet connection worked. I'm happy. Cool. Thank you. Okay. Now, a few other points to cover. One of the things that I'd like to show you is how we display it on TV. And displaying on TV is quite simple, actually. We use a Raspberry Pi 2 for that. That's a little device that just lives behind our TV. And what the cool thing is about the Raspberry Pi is, besides that it's really cheap. It's only 30 bucks or so, is that it can be powered through an USB port from our TV itself, so we don't have any extra cords behind that. Our Raspberry Pi just uses a Raspbian Jesse, which is the default operating system over Raspberry Pi. And when it builds up, it will just start up a Chromium browser, which is the engine that powers Chrome, and it will show the dashboard in full screen mode. Now, I have brought a copy of our dashboard here, but we don't have the right cable to connect it to the display, but I made a little movie at home that I can show you how it starts up. And for me, this is much less stressful because I know that this movie that in the end it will work out, and with this it's always a little bit... I hope it'll work. So now I've just put it in, put its power in, so now it's powering up. It's now trying to look for an Internet connection. It will find that, so I know it will find it. And now it will start up its user interface, and in the middle you'll see a terminal window, and in the terminal window there is a script running that will open up Chrome and display our dashboard. So it's going to do that in just a minute, hopefully. It should speed this movie a little bit up, I think. But in real life it's also a little bit slow, but once it's displaying it works very nice. So this is the dashboard that has been started up. An older version without the Twitter tile. The Twitter tile is only a week old or something. So that's how that works. If you liked everything that you see, that you saw, you can try the dashboard out for yourself. I've mentioned that we've open sourced it. Its code is on a GitHub repository. I've also written an extensive blog post about it on my blog. That's the first link. And a colleague of mine wrote a post about how that grid system works. So if you're interested in that, check that out. Now, I've talked here the whole time, so you might think this guy can do everything. But I've not made this dashboard myself. It was a team effort. So my colleague, Willem, he provided the looks of the dashboard. He made it look very pretty. And he designed the grid system. And my colleague, Sebastian, he cleaned up all my crappy JavaScript code and made that good. If you want to learn more about working with the dashboard, I suggest that you just head over to the home pages of the technologies that we use, that you check out the documentation of Laravel Pusher and Vue.js. And if you want to learn more about Vue, I can really recommend VueCast.com, which is a video course on a service called LaraCast, where a guy called Jeffrey Wei provides the best introduction to Vue.js possible. Now, if you want to use a dashboard but aren't interested into tinkering with our code, there are many alternatives, like GeckoBoards, Sci-Fi, and RazerFlow. Those are hosted services where you can just click your own dashboard together. Or you can opt to use dashing.io. It was built by Shopify. It's a Ruby-based dashboard. It's no longer maintained, but it works really great. We used that dashboard before building our own, and we used many of the principles that we saw in dashing to build our own dashboard. And with that, I've said everything I want to say about our project. Do you have any questions about this? How is the time? Yes. Why do we use a push-off service instead of putting the data from the JavaScript? I've got always the advantages of doing this. It's for real time, but there's a difference if you do it between the second and the third time. Yes. So the question is why do we use WebSockets and the push-off service instead of letting the JavaScript just communicate with the server? I think the first reason that comes to mind is we want to play around with WebSockets. We want to get our feet a little bit wet with using the technology. And also because of the real-time part, because we don't want to pull a server. Now, Sparcy is a very small company. We have only one office. But imagine that we have a thousand dashboards. Then with WebSockets for a server that isn't really a problem because those dashboards will never go to the server. So it's very scalable in this way as well. And that's why we chose WebSockets. Okay? Yes. What API are we using for the ring forecast? So which service that we are using for the ring forecast, that is Bayerada. That's a well-known thing. They have a very crappy API, I should mention. But it works well. But the format in which they send data is really horrible, but it works. So it's Bayerada. Yes. Yeah. In Rava, usually when you create your own custom classes you can extend some functionality. And then you want to use those classes somewhere else instead of just this. Yeah. So the question is how did we get to use here our namespace? No. Everyone sends application because it's where you find your classes but you call them somewhere else instead of application. Yeah. I call this. This gets called by the scheduler. This one. You know what? After the talk, I'll go with you a bit through the code and then we can just solve your question with the code at hand. Okay. Yes. I was wondering. You just said that it's possible to show the database on multiple screen if you're a company. Yeah. It's possible to use for each test port a different source for files. For example, not very many people throughout the company. Yeah. It's not possible with the code as it is but it can be easily modified. So you can, if you have a dashboard on your server that needs to display certain things, then you can just put it in the environment file so this dashboard should display only the task for this amount of people and just let your JavaScript side of things read that environment variable. So it doesn't have built-in support for that but it's easily extendable to fit that use case. Yes. In your setup, you've shown Raspberry Pi and therefore a fairly dummy TV set. Yeah. You've played it all with any of the smart TVs or any of, are there any smart TVs on the market that do not require an external device that just... Well, I'm not a TV specialist but I think I hate smart TVs. I want my TV to be as dumb as they can be because that software on it is going to get older. So I really don't know if there's a TV with a browser built in for that that you'll have to investigate on your own. But why would you need a smart TV? You don't need a smart TV. That's just me. Okay. Well, I guess we are done then. So thank you for coming to my talk. You can review the slides on speaker deck. Take a look at the open source work that my company has done. Also take a look at my blog, Merzy.be and if you're a newsletter type of kind of guy or girl, just subscribe to that. Thank you.