 I'm gonna start basically like right now. I think we're gonna have people like wandering in forever. They're all like binging coffee downstairs. So welcome to master the new core of Drupal 8 now with Symphony and Silux. This is a very serious talk and I'm a very serious person. So I'm gonna kind of suit up here at the end while we kind of go through the beginning with my polka dots eye. So bear with me. And when you do this on stage, it's gonna end up where like my tie is like this long and I'm gonna look totally ridiculous for the rest of the time, but that's how it goes. All right, so about me. This is my time to talk about myself while I get my tie tied here. I'm actually from the symphony world, not the Drupal world though, I'm getting all kinds of dangerous inside of Drupal these days. I'm the lead contributor to the symphony documentation. And I also work for Campy Labs which is a symphony training and consulting company. And how many of you guys have heard of Campy University before? Yeah, several of you, awesome. We are a website that focuses on, oh, Moment of Truth, what, no, no, no. That focuses on screencasts around basically symphony and namespaces, dependency injection, that kind of stuff. So check us out. And around the back and up and over. I think I just may have done a triple Windsor with this. I don't think that exists. Hey, all right, not bad actually. All right, welcome all lay people. You just missed me putting on my tie. So I'll perform it again at the end. And most importantly, I had the privilege of marrying up, way up, so I'm the husband of the much more talented Leanna Pelham who is right there. I was like, did she move and hide? Hello. So Leanna is actually much friendlier than I am, much more intelligent than I am, much nicer than I am. So make a friend and say hi to Leanna afterwards and she'll be very grateful. All right, so let's start with some serious business. And actually, I'm gonna move around a little bit. My wife usually helps me with that. Is it only on the right side? Oh, I'm a little surprised it wasn't on all the sides. Does it look presentable enough for a Drupal conference? Okay, good, all right. Yeah, everyone's like, I wouldn't go outside in public, but. All right, so let's start with the serious stuff. Which is, that I need to re-sync this for some reason. All right, hold on a second. Sorry about that, guys. I just had this working a second ago. Aha, there we go. Cool. All right, serious business. I have some bad news for me. Which is that tomorrow I face one of the scariest things I've ever faced in my entire life. I turn 30. Yes. Oh, I don't know if that's a good applause or those are all the people that turn 30. It's like, it's okay. So I don't know what it's gonna have in store. This may be my last presentation ever. I may go crazy and go AWOL and have a third life crisis or whatever you call it when you turn 30. So we'll see. I'm happy to be here though and maybe tomorrow you'll see me at the conference and I'll be old and decrepit. I'm not sure. So we'll basically see how it turns out. Actually, this is my favorite here. That's nice. Okay. All right. Maybe it's not all bad though, right? Maybe turning 30 is gonna be okay. All right, anyways. Onto the actual stuff we wanna talk about. So I wanna talk about the anatomy of a web framework. Any web framework in any language, Drupal, Symphony, Java, anything like that. This is, how many of you guys have seen a little bit of Sylex before? Okay, a few of you, okay, that's good and the rest of you, it's new. So Sylex is a micro framework. This is your entire application right here. This is an application that serves up a little page at slash hello slash Ryan or slash hello slash Drupal and it returns a page that says hello Drupal or hello Ryan. And this is actually the entire thing inside this one file. There's absolutely nothing else. So this is our application and I wanna go through the steps of how we'd actually get this working. So we write this, we're really proud of ourselves. We wrote seven lines of code. Now we're gonna configure Apache or maybe not. This is just kind of an unrelated gem. How many of you guys have used the built-in PHP web server? I saw an excited hand immediately come up from the back. If you haven't done this yet, in PHP 5.4 and higher there's a built-in PHP web server. It's not something you use on production but it's really useful locally. I basically don't use Apache on my local computer anymore. So you just type PHP dash capital S in whatever directory you want your document to be in and that's it. So we'll just start up a web server like that and you can see that's my command line doing that and boom I can go to localhost colon 8000 slash hello slash Texas. It says hello Texas and that's the entire application right there. So I wanna talk about through these steps. These are the steps of the same in every single framework that you, like kind of web framework that you have. We always start with the request. That's what the client is asking for. It then goes into routing and then it executes a controller and then we return the response. So let me talk about those one at a time and also kind of go the right direction here. You have to forgive me, I downloaded this app right before this. I've been using like the old school remote so I thought I'd get all trendy and so far I'm just kind of going backwards and forwards. All right, so the routing is basically the process where the URL comes in and it's gonna match one of these things. We might actually, this application only has one page but we may have many of these pages. That's called a route. This route will be matched if we go to any URL that's slash hello slash anything. That curly brace name is a wild card. It'll match anything. When this route is matched it's going to execute that function. Cool, easy enough. As an added benefit, whatever we have in that curly brace name wild card spot is actually gonna be passed as an argument, a dollar sign name argument. It's actually matched up by name. The fact that it's name there means it's dollar sign name there. And finally, our job is then to just fill out that function that builds the page. And we can do anything inside of here. Like this is just a simple little string. We can make a curl request out to an API. We could make a curl request out to our Java application. We could do Drupal stuff inside of here. Whatever we need to do to build the page right there. So this should make a little bit more sense. We start with the request. It figures out which route is matched. The job of the route is to say which function should be called for this page. The route's kind of the map between the URI and which function is actually going to build this page. And then the function, the controller, when I say controller, just think function. That's all a controller is, is a function. The controller is just where we actually do our work to build the page. And then our job is to return the response. Or really, we're just returning a string right now but that string becomes the response that's sent back to the user. Cool. So let's kind of look into, let's kind of take this to the next level little by little. So first thing I want to talk about is like our job as developers, our only job as developers is to understand the request and return the response. You may have a simple application like this. You may have a giant complex Drupal application but it's always just understand, well what page do they want? Do they query parameters? And then create the response, the page that they want. So this is what the request looks like. You should all be fairly familiar with this if not really familiar with this. So it all starts with this. Somebody's going to send this request to us and we have a couple familiar pieces there. These are the two most important ones I want to look at. The URI, which is the uniform resource identifier and the HTTP method. So we want to think about our applications as almost like repositories for resources. The client's basically saying, I need to get a resource. And we say that's great. Do you have the address to that resource? And they say yes. The address is slash hello slash Texas question mark page equals five. That's the address to the resource. And then our job is just to give them that address or give them that resource at that address. And the get there is the action. So we're all familiar with get. That means I want to get it. So there's also a post which without getting into technical stuff means I want to put something there more or less. So there's different actions. There's also a delete method for that. So it's all actions that you want to take on that resource. And of course the client can also send headers which is just extra information. And then obviously the response is very similar. We have the status code on top. We have a bunch of headers that we're going to send back if we want to whatever headers we want to send back. And then we have the actual body. So even like a Drupal seven application we all know this is really what's coming back to our users. So one of the weird things in the PHP world is that we have this nice request message and we have this nice response message but we explode it into all kinds of crazy parts in PHP. We don't have like one variable we can go to to get all, oh, what's the request method? What's the request URI? What's this header on the request? Instead some of it gets into the server super global. Some of it gets into the get super global, the post super global, the file super global, the cookie super global. To make things worse inside the server super global some of the headers are renamed. Like there's a host header that's always sent. But inside the server it's called HTTP underscore host. So some of the headers are actually renamed. So we've gotten denormalized from that nice request message. When I first started doing PHP, I didn't even know what a request was. I just knew that I had like these magic variables and I was like sweet. And then the same thing with the response. We don't have a nice response object or something like that. We just kind of call header and then when we're ready we just start barfing out content. And this is actually transformed by a PHP into that nice message with the status code. Cool. So the first thing that's a low level framework should give you is an abstraction of request and a response abstraction. And that's what you get inside of Sylex. And by the way, fast forwarding here. Everything that I'm telling you about Sylex is the same in symphony is the same in Drupal 8. So I'm talking Sylex, Sylex, Sylex. But you can replace the word Sylex with Drupal 8 and this is all true. So in Sylex we have a request object which is so simple. It doesn't do anything. It just holds all that information from the request. It literally takes the server super global all those other super globals and re puts them back together in a way that makes sense. So if you want a query parameter it's request arrow query arrow git. If you want that host header it's request arrow headers arrow git host. You don't need to worry about the fact that PHP like renames it internally to HTTP underscore host. Cool. So we have a request super duper simple. And then the same thing with the response. Sylex has a response object. And basically responses are easy, right? What's the content? What are some headers you wanna set? And what's the status code? So you don't see it here but you could also say response arrow set status code and put the status code on there. So request response abstractions these classes are very, very simple. All right, so let's talk about next thing. Let's kind of take this up another level to namespaces and auto loading. So the controller remember we have the route which is the URL part and then we have a controller which is just that little anonymous function there. A controller can really be any function that you want. It doesn't need to be an anonymous function it could be a flat function or like you see down here in the bottom it could actually be a method that lives inside of a class. So down here I'm actually you can set up an anonymous function the second argument to get is the full kind of this long class name colon colon and then a method name inside of that class. And this works exactly the same. So then in here I just create a class I give it the namespace let me flip back here because you see it's Drupal slash Acme slash controller slash demo controller. So namespaces Drupal slash Acme slash controller classes called demo controller. Hello action was the end part of the string that I had there before. So it works exactly the same way when we go to when we match when we go to a URL that matches this route it's just going to execute this function exactly the same thing. Now namespaces namespaces why did we invent namespaces? Well we invented namespaces because we wanted to make our class names longer. That's actually it. I mean really it's so that two libraries if they both had a request class would there be no naming questions but really namespaces were not created for you and I they were created for library maintainers so that they didn't crash into each other. We take advantage of it slightly because I can now use two different libraries that both have a request class but mostly sometimes people are like I don't get namespaces they just make everything longer you understand it they just make everything longer. It's you know it's not that big of a deal but you're not missing something. So yeah namespaces let us have a longer class name because the class name is Drupal slash Acme slash controller slash demo controller. Which is pointing at it cool. A side benefit this technically has nothing to do with namespaces though in practice they're totally related auto loading. So Drupal 7 has an auto loader not too familiar with it but basically it's the thing where it's like I don't need to use require and include statements. I can just call functions I can just reference classes and it's magically there. So Drupal 8 has the same thing Sylex has the same thing Symphony has the same thing. The only rule is that your namespace needs to match your directory structure and your class name needs to match your file name. So notice I'm in a Drupal slash Acme slash controller namespace and I'm in a Drupal slash Acme slash controller directory class demo controller is in the file demo controller dot PHP. I guarantee when you start doing custom modules in Drupal 8 the number one error you're gonna get is a class not found error of one variety or another. And it's gonna be because you've violated one of these rules you've like, you know you made your class called demo controller but your file is called demo dot PHP or something like that. If you mess any of these things up then you're gonna get a class not found error. But as long as you name these things the same then you're gonna have no problems and you're not gonna have to worry about require or include statements. This by the way is called PSR zero. How many people have heard that term thrown around? Good, okay most of you guys know, okay awesome. So that's just a standard that floats around the web. It says if you name your classes in this way then things will work. If you're interested in more about that then Google it but most of you guys have heard of it and it's not something that you need to know. Right. All right so let's go up another level. Services in the container. So services which I'm sure you've heard that term many times at least over the past 24 hours. Services equal useful objects. It's that simple. An example of a service would be a mailer object that helps you send mail or a database connection object that helps you query the database. Those are examples of services. A container is an object that holds services. It's a really simple idea. So imagine you had all these 10 objects, these 10 useful objects and you put them into an array just so that you could pass that array around because then if you pass that array around then if I give you the array you can get out the mailer object and use it. That's a container. Container is technically an object but it just acts like an array and it's only purpose is to kind of hold all of the services in it. And it's actually like an associative array so if I have like a mailer object it's gonna be in there as like a mailer key or a my underscore mailer key. So if I want to get the mailer object I just kind of need to know what it's nickname is. My underscore mailer. You'll see an example in a second. So the point is that Sylex, Symphony and Drupal they all have this container. They all have these ideas of services so this is gonna be exactly the same. So in our little Sylex application could we use the container to render a twig template. So twig is just a, there's a twig, there's a twig object. It's a service because it helps you render templates because remember services are just objects that do something. And if you use Sylex, you have to do a little configuration. If you use Sylex, then there's a twig service inside the container. So this is our controller again, our hello action method. This is our function that's called. And the way this is a little bit different inside of Drupal and I'll show you. But the way that you get the container inside of Sylex is by type hitting this little application argument. That's a Sylex detail. The point is whenever you're inside of a controller in Drupal, Sylex or Symphony, you have access to this container. And this just happens to be the way that you get access to the container inside of Sylex. So the nickname of the twig service is just twig. So we're getting out that twig object there. It says, hey array please give me that object. Thank you very much. And then the render functions of method that's on the twig object. So you know that because you read the twig documentation to see how do I render a template. And that is it. So going back to this, we have the routing controller flow, which hopefully is boring. It's always, hey I make a route, it points to controller, I return a page. Got it. Now as an added benefit, when you're in the controller, and really anywhere, but when you're in the controller you have access to this container, which means you have access to this big group of useful objects. And you can use those if you want to, or not use those, to help get your work done. You might use one to render a twig template. You might use one to talk to the database. This is your kind of bag of tools. And I do not come from a Drupal background, though I'm starting to get pretty dangerous. In Drupal speak it basically be like in Drupal seven we're used to like saying, okay what's the function I need to call? If I need to talk to the database I need to call this function. Well in Drupal eight it's gonna be, I need to go get this service object and then call this function on it. All right so let's talk about events. And by the way I'm gonna come back at the end of this and basically show all of this same stuff in a Drupal eight module. So we're gonna get kind of a second pass at some of these details. So events. So just like Drupal hooks, Sylex has events. They're just, they have the same exact purpose. They're just kind of registered in a slightly different way. So in Sylex or Symphony or Drupal eight, see where I'm going with this? A lot in common. You can basically say hey Sylex when this thing happens, when this event happens in your system, when you kind of get to this part of your process, could you call my function over here? That would be super. All right. So I mean that's right. It's kind of like Drupal seven hooks. It's just that in Drupal seven it's sort of like if you name this function in this exact way then when Drupal goes to run to your theme or do this or do that it's going to call your function. So the end result is exactly the same thing. Now this is the flow from request to response. What actually happens is after the, basically right when everything starts before the routing's even run, the first event, the first hook point is dispatched. Kernel.request, that's the name of the event. And what I mean by dispatched is this is the moment at which the core of Sylex notifies or calls all of the functions that have said that they want to be called when this event happens. So again, just like Drupal seven hooks, the only difference is that, and I'll show you how in a second, is that it's not done by some magic naming of a function. You'll still create a function that you want to get called, but it's not about the name of that function. There's an extra little configuration that will tell Sylex, hey, don't worry about what this is called, but do know that when you get to that kernel.request event, call this function, call this function, my callback function or something like that. So there's a little configuration step that says like this function should be called for that event. So kernel.request happens and the core of Sylex, it's called the dispatcher, the event dispatcher, just calls all of these different functions. Next it runs routing, more or less, runs routing, next it dispatches another event, then it executes our controller, and then it dispatches two more events, and then it finally sends the response back to the user. So the point is we have like this anatomy of the framework is like it's always kind of like routing controller, and there are also these hook points between each step. It says, hey, if you needed to do something between the routing and the controller stage, you can do that. There's an event called kernel.controller there. You just need to make a function and tell Sylex about your function. Hey, I have a function. I want you to call it when the kernel.controller event happens. So this is what it looks like and I'll show you another one inside of Drupal in a second. So in order to create an event listener, I keep saying it's a function and you can just do a function, but typically you'll have a class like this. You have a class. I want that onView function to be called when the kernel.view event happens. You see that kernel events colon, colon view. That's just a fancy constant. That means kernel.view. So we're talking about that kernel.view event down here. So this class is kind of the way that you set up an event listener or an event subscriber. So these functions that are called are called event listeners or event subscribers. And then this is specific to Sylex. So I'm gonna come back and show this in Drupal 8. But this is how you tell the core about your function. It doesn't magically see it because it's named some way. Step one, I wanna focus on the top three lines of the top entry first. So we have this container full of useful services. When you use Sylex or you use Drupal 8, that container comes prefilled with lots of good stuff. And then you can add your own stuff to it. You're like, ooh, I have this helper class over here which helps me query the database in this very special way. Well, if you want to easily reuse that, register that as a service. And then in any other part of your application, you can just say, hey, give me my database helper object. And then I'll call methods on it. So it's a way to organize your code. And in Drupal 7 or before this kind of paradigm, you would have, if you wanted that same functionality, you would have just created a flat function. Function called like get database, query database table, something, something, something. Instead of a flat function, we put it in a class, we registered as a service. So that first line is simply doing that. It says, I'm gonna have a new service, a new useful object in the container. Its nickname is acme.view underscore subscriber. I just made that up, but that's how I would reference this later. And when somebody asks for that service, here's what you give them. You give them a new instance of my view subscriber. And it's that easy. So that's kind of like one thing, that's you adding a service, cool. Now, we actually want our service to be an event subscriber. So here we basically get the dispatcher. This is a, don't worry about the details of this, because it's a little bit different at Drupal 8, as you'll see in about five minutes. We basically get the core of Sylex though, and say, hey Sylex, this is an event listener. Be aware of this guy over here. And that's how those two pieces get hooked up. All right, so one more thing I wanna talk about before we get into the Drupal side of things, which actually ends up being pretty nice and easy, is the profiler. How many people know what I mean by the symphony or Sylex or Drupal profiler? There's one hand over there, a couple hands, awesome. All right, prepare yourselves then. So Sylex, symphony has a web profiler, and because Sylex is all of the same pieces as symphony, it has a web profiler. For any page, while you're developing, for any page, you can access this screen for that page. And this contains lots of information about that page, like what's some information about the request. You see that events tab there? What events were dispatched? What functions are listening to those events? So you can usually, you can see, oh, on the kernel of that request event, here are the 10 functions that were called. So you can kind of reverse engineer things there. Logs, routing details, you can see which route was matched. You can actually see that it said this route didn't match, this route didn't match, this route didn't match, but this one route matched. And most importantly, it has the timeline, the timeline. This is awesome. This is everything that's happening from request to response. It has the very top, the first tiny little black bar, if you could read that, says kernel.request. That's actually the amount of time it's taking to execute all of the listener functions that are subscribing to the kernel.request event. And you can see there's a couple of tiny, like, light blue lines below it. Whoa, whoa, there we go. Oh, there we go. I strayed too close to the sun. Actually, I just unplugged this a little bit. Those are the actual individual listeners. So you can go here and say, oh, I see that in kernel.request there's a listener called router listener, I wonder what that does. And it goes on, there's a black one in the middle for how long it took your controller function to run, and then other events there on the bottom. So this is meant for, how do I know? This is meant for profiling, because you see like, why is my application taking so long? But it's actually a lot more than that because you can use it to really understand what's going on behind the scenes, what kind of secret layers are going on behind the scenes. If you imagine that this existed for Drupal, which it does, then you could actually see I installed this module, it's doing some magic for me. You can actually go inside of here and be like, ooh, I see how it's doing its magic. It has a listener on this event and a listener on this event, and here's what those classes are called. I'm gonna open those up and see what's going on inside so I can understand what I need to get done. Yep, so there's the routing, the XT of the controller, and oh, and that's our listener. We made that kernel.view listener earlier. That's kind of our listener on the bottom being called. So this is all to say, of course, that everything is basically the same in Drupal 8, which is why it's easy for a guy like me that's not a Drupal guy to understand Drupal quite easily. So first I have to do a shout out to my friend, Jesus. Hey, Zeus, are you in here somewhere? Hey, Zeus, oh, shame. Hey, Zeus, because he actually has some really great blog posts on this. I'll have the link on the bottom. So if you're curious about going through this in a little bit more detail afterwards, you can. And there is bit.ly, d8-hello. So I made a nice little bit.ly there if you wanna go to his blog post on that. All right, so step one. So, and again, our goal here is actually basically to create that hello world page again, and we're also gonna create an event listener. Step one, create the module. This should look familiar. We added .yml on to the end and added some colons to it, but basically you guys are, this is exactly what you had in Drupal 7, just a slightly different, just in YAML format. And really, there's no important information for us. Step two, let's create a route. How do you create routes? So this is hook menu in Drupal 7. In Drupal 8, you're gonna make a route. You just make acme, whatever your module name is, acme.routing.yml, and Drupal's gonna pick that up. And it has the exact same pieces as before. Path is the URL, so you can see the pattern there. And you see the underscore content key? That's the name of your controller. It's this class name, colon, colon, this method name. That's what I want you to call when someone goes to this page. And there's also a bunch of nice Drupal stuff. There's underscore title, underscore permissions. I think there's a few other things. There's also, if you're rendering a form page, instead of underscore content, you actually say underscore form, I believe, and point that to your form class. Say underscore form, colon, and then your form class. And it kind of takes off down the form route of things. And this actually might not be any different than what I showed you earlier. This is your controller. This is exactly, maybe even down to the same character what we had in our Silux application. We can get at the request object by type hinting request. It's a small detail, but it's the exact same thing that we had before. And this is what the whole guy looks like. We have the info file, the routing file, and then we have the demo controller. And notice I have the directory structure there. The good news is, by the way, this might actually already be done. You might be looking at that as like, that's a lot of extra directories, and you would be right. So they're making a change right now, and it's already in there. They just need to convert over the modules that will get rid of a couple of those extra directory structures. So it's gonna be a little bit flatter than this, but that idea is exactly the same. Cool, and that's it. So we have route, route points to controller. We return some stuff. So when you're building custom pages, custom functionality, you're not like cacking through stuff. It's very simple, and I can do it really easily because it's the same as Sylex, it's the same as Symphony. And by the way, there's also, and I'm kind of pimping this because I actually think it's really useful. There's a code generator that's being worked on. It's actually, Hazus was one of the contributors on it as well, and this is a screenshot from its page. There's some stuff for generating modules, generating controllers, generating forms, and generating plug-in blocks, and there's gonna be some other stuff. So this is actually kind of cool stuff that helps you generate the route and the controller. It's exactly what you're seeing here. It's just a tool to get it done faster. Also, when you start getting into services a little bit more, it has some stuff for it to be like, you're generating a controller. Would you like me to help you get access to a couple of Drupal services? You say, why yes, I would, and you actually start typing service names and it auto-completes the service names and then it generates the code to get that service. It's really, really cool stuff, so check this out. All right, so does Drupal 8 have a container? Yes, it has a container, we all know that. This is actually, well, the way that you're gonna get at the container inside of Drupal 8 is actually gonna be slightly different than this. I use a simplified example. But again, the point is that you have access to the container in Drupal 8. And when you wanna get a services off of it, you call the function get, and then you give it the name. So really, the only thing you need to know here is like, oh, I need to translate something, like what's the name of that service? Let me just Google real quick or look at the docs and say, oh yeah, when you want the translator, it's called string underscore translation. Good? Now you can get it out. Then you just basically use it like normal. So before we had like the what, the t function. So now this is gonna be the pattern. It's not a flat function anymore. You go out to an object, and then you call a method on it. Other than that, it works exactly the same way as before. All right. And are there events like in Sylex? Well, of course there are events like in Sylex. In fact, it's more than there are events like there are in Sylex, there are the exact same events as there are in Sylex. Because the same core, core, core, core stuff of Sylex is the same exact code that drives Drupal, which means we have a kernel.request, a kernel.view, a kernel.controller. All of those events, all of those hookpoints, all of the way the routing and controller is done is all exactly the same. So let's create a listener class inside of Drupal 8 and see how that looks. By the way, let me back up real quick and say, this is all, I'm taking through routes and controllers which is how you'd kind of build a new custom page. Even the core, all the core functionality of Drupal, like if you go to a node page, you go to like slash node slash one, there is a route that is responding to that. That route, it's a core Drupal route. That route passes to a core Drupal controller. In that core Drupal controller, it goes and looks up your node and does stuff with it. So you're building your page in one way. Drupal core is building its pages in the exact same way. If you wanna get really nuts with it, that core controller that's always being called when you go to a node page, you can swap that out for your own if you wanted to. That's very, very simple. There's just a spot that says, oh, and this route goes to that controller and there's a way to basically say, mm, that route goes to my controller. I will handle the rendering of a node or maybe you subclass it and add a little functionality and then call the parent thing. That's one of the side benefits and as you get into this stuff more, you'll understand why it's one of the side benefits of the new architectures like everything can be ripped out. Doesn't mean you should go do it, right? It might make upgrade paths harder in some cases, but the most core, darkest, deepest, weirdest parts of Drupal can just be replaced. Because everything, not everything really, not everything has been fully converted to a service but most things have in Drupal 8. If something's a service, you have the opportunity to say, wherever through all of the core of Drupal that Drupal refers to the string translator service and maybe that string translator service is being referred to 100 places in the deep, dark parts of Drupal, you can say whenever anyone asks for the string translator service, it's now my class, not the core string translator class. It's my class over here. So you've actually just made your object replace what the core string translator object is and that goes for any part of Drupal 8. All right, so we're going to create a listener class. It looks the same way as it did inside of Silux. So I have this class response subscriber, implements events subscriber interface. That's going to be another common thing. Whenever you want to do something in Drupal 8, a lot of times you'll read the docs and it says we'll just create a class that implements this interface. This is a good thing because when you implement an interface that interface says you have to have this method, this method and this method. It's documentation, it's directions on exactly what you need. The event subscriber interface says you need to have a get subscribed events method and makes sense, right? So when we point Drupal at this object, it's going to call the get subscribed events method early on so that it knows which events we actually want to listen to. And then the kernel events colon, colon response, that's a string, kernel dot response. Kernel dot response is the last event in the process. This is after routings run, after the controllers run, right before we return the response to the user. And so what we're actually doing here is we are going to go into the details but I'm basically saying hey, if this is an HTML page and there's a closing body tag, I'm going to inject a script tag onto the bottom of it. And this will happen on every single page. You could also have an if statement if you wanted to have it only happen on some pages. Cool, that's step one, make the class, make the function. Step two is to plug it into Drupal. So again, there's two things happening here. First, this is how you register your own services in Drupal 8. And you will do that all the time because you'll say, you know what, I have this function. This function is a nice bit of reusable code so I'm going to put it in a class and I'm going to register it as a service and call it foobar. And then everywhere else in all your controllers, all of your classes, you can just go say, hey, Drupal, I need the foobar service. And it says, here you go, then you can use it. So services primarily are a way for you to kind of organize and reuse code. So if you look at the first lines of this, ignore the tags part, the first lines of this are how you register a service in Drupal. You just have to call this file, act me again, modulename.services.yaml and it will be discovered automatically. There's also, I'm not showing it here, but if your class has constructor arguments, like you have a public function underscore underscore construct, under class, there's also an arguments key. We can say arguments colon, you can say my first argument is this, my second argument is that. There's even a way to say my first argument is the string translator object. So you can actually inject that in. It gets a little bit more into dependency injection. The point is, this is how we do services and there's a little bit more flexibility you can do with this, but this is you making a service. The tags thing is special though. This will only be on some of your services. So most of the time, you're just gonna make a service because you're saying this is a reusable unit of code. So I'm gonna register in the container because it makes it just really easy for me to get that object out from anywhere else later and use it. Great. Occasionally though, you're doing a little bit more. You're saying, no, no, no. This is not just a service that I'm making for my own benefit. This has a special purpose inside of Drupal. So I wanna raise my hand and say, hey, Drupal, this is not a normal service. This is an event listener. So I need you to kind of see me. I need you to notice that I'm here. The way you do that is with tags. So we have this tag named event underscore subscriber. Literally when Drupal boots, it goes to the container which contains all of our services and says, can you give me all of the services tagged with event underscore subscriber? And the container goes, why yes, I can. Here's those 10 services. And it goes, thank you. And then it makes sure that those are registered properly as event listeners. So again, tag is a way for us to raise our hand and say we're special in some way. There's only a finite number of tag names that exist. So there's only a finite number of these little things that these names that you can put there. If I said tags, name, colon, foo, that's not gonna cause an error. There's just no system in Drupal that's asking the container for all services tagged with foo. So nothing really happens. So you don't need to worry about these other than just kind of like understand what the purpose of these is. And you'll see these all the time. Like when you, I can't remember if this is, well, it's actually done slightly differently. But if you got Google like, oh, I need to hook into this part of Drupal or that part of Drupal, you're gonna read a blog post. And it's gonna say, now registered as a service and tag it with this string. Cause they know that this string is like the magic string that kind of hooks you into that core process. And boom, I now have the most annoying website on the face of the planets. I actually had to turn that off. I was like, this is aggravating me. Awesome. And does the profiler exist? Why? Yes, it does. Again, cause the profile, this is one of these freebies that we get because we're using the symphony components. The profile is just another symphony component piece. So there was a little bit of integration work, but somebody, I actually don't know the two contributors on here. This is some work that somebody has actually done. I've used this. It's fantastic. So it's built, it's a contrib module and they did a really, really, really fantastic job with this and I'm sure they're probably gonna do even more with it. And it looks like this. So I install this and then magically on, in D, obviously you turn this on and off when you go to production. But when I'm developing, I have this bar along the bottom. If you can't see it, this bar tells me I have a 200 status code. It tells me which route was matched to build this page cause there's always a route. It tells me that this took 230 milliseconds and it took 11 points, something megabytes of memory that there was 120 something queries. And there's also some things about configuration variables and themes and other things like that. If you click into this, you get even more information. This is actually the profiler. So the thing before is known as kind of like the web debug toolbar and this is actually the profiler. You click into this. This is actually showing us all 126 queries that were made on this page. You also have other things like these are the active modules. There's form information up there. This is actually really cool. Here are all of the routes in the system, including all of the core routes. You can see like, I know it's hard to see over there but basically like that block admin ad says slash admin slash structure slash block slash ad slash something. All of the core functionality is a route. You guys can actually get a lot of, you can peer into the heart of Drupal and see like, well, when I go to that page, oh, it's just this route that's happening. And you would see the second one I have on there is actually the route that we added. So you can see all like 200 or so routes that are added into Drupal. And most importantly, the timeline has made it over as well. So never has it been easier to see the heart of darkness, the core of Drupal. These are all the layers. It actually goes a little bit further down than this. These are all the layers that are happening inside of Drupal. And you see the exact same things as before. That gray bar, the top gray bar is kernel.request. The amount of time it's taking for all listeners to be executed on kernel.request. All the little things under it are the listeners to that event. And what you're seeing to the left there are their class names. About two weeks ago, without having done much of Drupal at all, I went through one by one and just dissected the whole system. I did it by going here and I just started opening those classes. I was like, what does this class do? Well, what does this class do? Well, what does this class do? What does this class do? It's very easy, because it's all just right there. It's not like hidden functionality somewhere that's happening. It's all just being spelled out right there. Same thing, we have the controller down there in the middle. It shows how long it took the controller to run and then all the other events afterwards. So again, this is for profiling, which is good, because we can see what's really slowing things down. But it's also for figuring out what the heck is going on behind the scenes. What kind of magical layers are there? They're still magic, but you can actually get a little visibility into what those are. By the way, one thing that I will mention is you see the long bar, the long blue bar. The black one above it is kernel.views. This is all the listeners under the kernel.view event. The blue one below it is the, what's that, the view subscriber? Yes, the HTML view subscriber. So one of the things that, one of the ways that Drupal works is that when we were looking in Silux, we were returning the page from our controller. We were just returning the HTML right there. The core Drupal controllers work a little bit differently. Instead of returning the page, they're just returning data. So if you actually went into the core like node controller, you'd see it's just returning data. It's just an array and the array has like the node on it. It also has some other information on it. So by the time the controller is run, the page, there's no HTML yet at all. There's then a listener on the event that happens right after the controller is done, whose job is to take that information and to turn it into HTML. And that's actually the part that goes through the theming system. Now why was it done that way? Because it's also the same layer that has the capability of turning that same array of data into JSON or XML or whatever invented format that you have. That's where that magical layer happens. Controller prepares data. Another layer transforms that data into whatever format you want, which is why it's so easy. You probably heard it. If you need a custom format, if you're like, I need to return JSON for my nodes, but not exactly the structure of JSON that the core gives me. It's just a matter of putting in your own, I can't relate, a view formatter, I believe. Your own view formatter that hooks into this process. And then you're able to say, like, in our case, I want you to hand me that bag of information and I will turn it into JSON. So those two pieces have been decoupled. All right, in the home stretch here, that's the Sylex logo, it's a rock. It's cute, has eyes. All right, so the big things are we have request response, routing controller flow, namespaces auto-loading, services containers, events listeners, and even profiler as an extra thing. And these are all the same in Sylex, Drupal, and Symphony. Sylex, technically, has a different container library, but it works almost exactly the same way. So that's the only thing that's technically different, but you won't see any, they work all the same way. And so this is really awesome because it means you can use Sylex right now to learn Drupal. And Sylex is a great tool for small problems. You're like, I have this thing, it's just processing some data. I need a client that uploads a document to this endpoint and then we're gonna process it into a database. Just get Sylex for that. It can be one file if you want. And of course you can use Sylex to learn Symphony and this is a really good path because all of those concepts are exactly the same and you can use Symphony to learn Drupal, which is actually basically my story. I know Drupal pretty darn well now because I know Symphony. And the big thing for me is this, this means that we have more tools. You guys, by going to the Drupal 8 architecture, are gaining the capability to use Sylex, Symphony, or anything else that uses those same components without a learning curve. And there's gonna be some new things probably, but like all the core things are exactly the same. There's also another framework called Laravel. It's built on top of Symphony. You use it, you're gonna see familiar components. And going the other direction, I actually gained the ability to use a CMS. I would not have used Drupal 7. I can use Drupal 8, it makes sense to me. So you guys have basically different tools for different problems. I'm not saying use Symphony, not Drupal. Totally different problems. If you're handling content, don't use Symphony. That's gonna be an uphill battle. And that is it. Thank you guys very, very much. And we're gonna leave that up for like a couple more hours. If you guys wanna grab a free tutorial on www.campioniversity.com, maybe you wanna get your feet wet inside of Symphony or something like that, grab that coupon code. They'll give you a free screencast up there. We also have a couple other screencasts that are always free, like one on dependency injection, one on Composer, one on PHP namespaces. So if you're still kinda getting used to those then check those out. Does anybody have any questions? Do we have a microphone? Oh, you guys, man, you guys are awesome. Yeah, go ahead. Hey, you might not be super familiar with the concept of the way hooks work in Drupal 7, but they do still exist in Drupal 8. Oh yeah, I'm glad you said that, yes. And I'm wondering with the event system in Symphony and in Drupal 8, is it easy to create your own event types and to establish them in your documentation so other module writers can then subscribe to your event and when you call it. And if so, where do you see the balance or where do you see the responsibility between hooks versus these events? Yeah, so I'm glad you said that. So yeah, hooks absolutely still exist. And I don't know where they're going, but hooks may eventually, and I'm talking like Drupal 9, go away in terms, it would be entirely events. There had been too much to change. It also turns out the way hooks work is it just goes functions exist, functions exist, functions exist in the core like a billion times, turns out that it's actually pretty darn fast. And there's so many hooks inside of Drupal that they were like, let's keep that for now and we'll start converting stuff over to events, but it's cool, we'll leave everything there. I think going forward, you should be using more events though there's still parts inside of Drupal where it's like, well, that right there, you need a hook to get into that layer. There's no event being dispatched at that layer. Now, inside of your custom modules, that's such a great use case. So let's say that we're creating a third contrib user module, some sort of like how it gives you like a registration page or changes the registration page in some way. What you could do right after you save the user is like you were saying is dispatch your own event. You're gonna be like, I'm gonna dispatch a user.registered. You just kind of invent a string. I'm gonna dispatch a user.registered event and any other modules or any other core applications can then register listeners to that event. So you just say, I'm gonna dispatch an event. I'm creating my hook point. I'm dispatching an event and anybody can basically hook into this. And when you dispatch an event, I didn't talk about it too much. When you dispatch an event, you actually pass an event object to all of your listener functions. And that event object can be whatever you want. So it'll be any object you want. You'll basically create your own event object and you'll store any information on it that you think is gonna be useful. Like for example, in that example, you would store like the user object or some user information on there. So if I'm a listener to that, you're actually passing me information about the user that was just created. It's absolutely something that you see inside like the symphony bundle world and it's the use case certainly for like third party modules. Yeah, great question. Hi. Hello. Thanks for your presentation. I've not seen any of this stuff before. I'm super excited about the profiler in particular. Yeah, isn't that crazy? Yeah, I mean understanding how Drupal's doing the stuff under the hood is really difficult I think. And so that seems to expose it, which is brilliant. And I thought your presentation style was really good as well. It was really interesting. I have a kind of lower level question I guess is that I noticed when you had your, the registry, the code that was like doing the handling of stuff, that the method get subscribed events was static. Yeah. So how do you extend? I'm looking forward to more OO stuff as well because my background's in OO. So how would you extend an already existing thing if you've got a static method that's returning the events you can have? You typically don't override events. I guess I don't know if I'm using the right term there about events, but you remember your code where you say it? I'm sorry, event listeners. Yeah, event listeners. Yeah, you typically don't, there's not, you typically use case for overriding event listeners. You'll add your own event listener. You can't actually replace the entire class. So the kind of like the long, the true answer for like Swiss Army Knife, like how the heck do I, like I don't want to use that core listener at all. The core listener, even though that method is static, the core listener and the class for the core listener is registered in the container. And there is a way to say that core listener, that service that's registered as listener, when the event dispatcher uses that service, I want, I'm going to actually short circuit it and point it at my class. So you'd completely basically replace it. You'd have your own static. But your class could override, say the Drupal core way of doing it and just extend, like do your bit of magic and then call the super class. Yep, exactly. If you need to, yep. You'll find with listeners, sometimes the solution will be, you'll just register another event listener and kind of take care of that business, maybe before them. Like for example, the routing layer, the whole point of the routing layers to establish like basically what controller should be executed. So if you needed to like extend that in some way, you wouldn't necessarily need to override the core router listener. There are other ways to hook into it, but you might actually register a listener on the same event. There's a priority of listeners. You usually don't care, but you can say my listener has a high priority. So your listener is executed beforehand and you can actually do that work before that listener is called. And typically, what you'll find is like, I don't know if this is actually with the Drupal router listener or not. The router listener in the beginning of it, the Drupal core router listener will basically say, has somebody already done my job for me? Has somebody already determined the controller? Oh, they have, then I'll just peace out. I'm not gonna do anything. Thanks. Good question. One of your slides earlier you showed like grabbing the translation service off of the container. In Drupal 7, you just call the t function, which does all of that magic for you. I went to a presentation yesterday that basically said, well, t still exists, but it's just a wrapper around this Drupal super object and it's got a static method on it that does the translation. But the caveat that he made was, well, it has to fire up its own container because you're not calling it from within the container you get inside of your controller. So is all of that loaded up and it doesn't matter if you do t or you grab it off of the container you get, or is there a performance advantage to doing sort of the two line method as opposed to just calling the wrapper? Yeah, I'm fairly familiar with how they wrap those. So a lot of times, a lot of the legacy stuff is still there and it's literally like you're saying it's just a wrapper to actually go out. So like the t function exists and just goes out and says give me the string translator service. The way that's done is very lightweight. So I don't think that there's an extra performance hit from getting that. So practically speaking, like use the string translator service. It's the new way of doing it. Things are going that direction. There are some subtle things I can tell you about like one advantage of the other where like if you're unit testing your classes you can't unit test the t class. You're gonna get less kind of WTF moments long term because everything's kind of, you're not kind of going through the static kind of cheater way of doing things. It's not gonna kill you if you're using the t function and they are kind of going the same way. Obviously you'll be much more ready for backwards compatibility stuff if you're using the new thing but there's not gonna be much of a difference and I don't think performance is gonna be a problem with that. Yeah, there are definitely cheater things left in there and you'll see the way examples are being done and the way docs are being done. Like we're trying to guide the community towards the best way of doing things but there is kind of like the other way of doing things that's still kind of made available. All right, one more. Hey first, excellent presentation. Thank you. Thank you. This was really great. And you may have answered part of my question from the gentleman asked when you talked about prioritizing events and listeners but the question is also to piggyback on hooks. Sometimes you find with contributed modules some don't play nice with each other and then we kind of prioritize it by putting weights on it but the modules and stuff like that. So how does Sylex or something handle that kind of when different modules are competing for the same to modify the same part of a response? Yeah. How is that handled? Yeah, so it's really truthfully not going to be much different. You still have a priority thing which most of the time you don't care about my event listeners registered before another one but occasionally you do because you're like, I need to get in front of it. That's cool until there's another module that has that same idea and tries to get in front of it and you're gonna basically run into that same problem. Now one nice thing is your, you know, because we're working with more objects and less kind of like deep arrays that should be a little bit more obvious. You're not passing on this object. You can call this method on this object versus kind of like different arrays being handled in different ways. So you're gonna have a little bit more clarity into that but that will still gonna be basically the same problem which is good in some sense. It's a way of me saying that like under the hood the end result of hooks and events are the same thing. You are gonna have things competing. All right, thank you. All right, you are all free to get coffee or whatever. Thank you very much.