 All right, it's one o'clock people will probably file in from lunch, but we might as well get started There's a lot to talk about can everyone hear me. Okay Yeah, and everyone can see So this is Drupal 8 routing My name is Tim Plunkett. I'm a developer at Stanford University Graduate School of Business and a core subsystem maintainer mostly with the views in core and Drupal 8 but Wanted to talk today about the new routing system for Drupal 8 So first show of hands who has never Written hook menu in a module before anyone Okay I'm skipping all of that so I'm assuming you all know that so that was only like two or three people raised their hands Hopefully you'll catch up as we go Who here has yet to use who has started already using Drupal 8 and looking at it So about half the room. Okay First things first Hook menu did too much. I don't think anyone will argue with that. It was responsible for routing menu links local actions local tasks breadcrumbs contextual links and even the overall menu hierarchy Which is not necessarily a function. It was just a kind of hidden feature that you got But that's you know six different things one hook. It's it's a it's a lot Hook menu is dead in Drupal 8 or will be shortly There are a couple things in this presentation that have not yet happened But they will this week and I will point them out Which ones haven't happened yet, but already just like an hour ago the breadcrumbs are now completely path based We'll get into that later on So routing a route is just a map from a URL to a controller Here's an example of a d7 hook menu. This is borrowed from the pants module, which is a nice example module So you have the path admin config people pants, then you have a title pants The description is to administer pants page callback to will get form page arguments is a string pants setting That will be the function name that is called The access arguments are just administer pants and this callback happens to be located in a separate file So this is all familiar to everyone. Yes Great, okay. This is the Drupal 8 version of hook menu. I said hook menu is about to die. It's about to die Right now if you're working on porting your modules You'll need this for any visible menu links But the only thing that really remains are the title and description You'll notice we have a route name here And it's just pants dot settings. It's a machine name and you can choose it. It's not magically named at all So this is the pants routing yaml This is the part that takes over the routing aspect of hook menu from Drupal 7 So there's the machine name again. You have pants settings and the path So the path is the same thing that you used to put in the items is a key in the array of the menu items And then there's two other sections defaults and requirements. You'll see that this is exactly the same as They are here Just the instead of access arguments administer pants. We have permission administer pants as a requirement And the title is also here. The new thing is this form Drupal pants form pants settings form so that's all psr0 and Names PHP 5.3 namespaces. I'm not covering that But the point is that this is the form that we want to be used as this instead of the old page callback So here's the D7 version of page callback. It was just a settings form it determined. What type of pants and In this case, it has no no pants option So you can see we have a just a regular form API and then this magical system settings form So here's the Drupal 8 version this is the what we call a route controller and I'll cover a bunch of some of this stuff more in depth later But we have this it's a form and it has a build form method and we're doing the same thing We have form API all the way down and then we have build parent build form That's just you know proper object or in where the parent class config form base Contrack provides most of the magic that system settings form used to do There's a couple other parts of the form base that I've cut out from this because I'll talk about it later So don't just copy and paste this and hope it works But that's the the general idea is instead of a single function in a file you have a method on a class So menu links we talked writing was the first part the second part of hook menu We're the menu links. This is the part that's not done yet There's a patch to do it and it's in the process, but these are the ones that are physically visible on your site So the new way to do them will be called hook default menu links and it will just be What route name it's for the title of the description and you specifically have to tell it which its parent is So before if you were defining menu links, it just if you had you know admin config Development and you had admin config development testing Those that would be the child of it just magically based on the path structure Now you can have links be the children of anything just based on its parent and it's not restricted to the path This will let you kind of build better menus Where you can just pull something in you can give it the URL you want not the URL that you need it to be With an extra slash at the end So if you want more information on it, that's the issue and it should probably go in maybe this weekend Local actions local actions are the buttons at the top of the page. They look like that. That's triple seven and that's triple eight So a note local action It used to be in hook menu and now it's in a YAML file Like a lot of our code is in YAML files now Including the info files and the routing files and local actions files and local task files and contextual links files and the config files and the config scheme files So there's a lot of YAML Thankfully, it's really easy to write. It's white space sensitive. It takes keys and values and that's it so you'll see just as just as simple that this is actually the exact one I was just showing you the add content type and It's takes it appears on the node overview types route and It has a title of add content type and a route name where it links to is the node type add to add a new content type So you'll have just a file full of these just by themselves and then you can keep all of that Those little buttons Separate from the actual routes themselves and you just reference them. The other nice thing is in triple seven and before this You could only kind of put that on one place you had this this button can only appear on this page Now this you'll see appears on is an array You can just list as many routes as you want here and that button will show up on all those pages Local tasks, they're kind of very very similar in code to local actions But they're completely different in implementation and use case. These are the ones. They're sort of related tasks Not necessarily a new thing So those are the local tasks on the views page for views settings. So you have like lists your settings basic advanced This is the definition of them it gets a little small at the bottom of the slide, but you just have a machine name completely arbitrary the route name that it links to and the title and Then each of these has a root ID you'll see that these all have these two have the same root ID that's the list and settings and these two have the same sorry parent ID, which is the The other ones so they're all all four of those are grouped together But using the different the parents and the roots this code might change a little bit in terms of the naming We just it's this is matches exactly what was in menu dot ink in triple seven But as we all know menu ink is pretty confusing So there's work to rename those keys but it the idea is that it will keep it separate from all your actions and all your other things and You can just have a file of all your local tasks Contextual links those are the little you know, you can see them. They pop up Generally on a an entity We don't really use them anywhere else But you can put them on anything and they're little helpers for that little piece of Content or that that block or menu what not and those are also going to be to find any ammo This is also not yet in core But it will be very very soon and it's exactly the same you have a route name Which is just a machine name and then you have the title and these are grouped So that you can have them, you know in a specific order and all of these support weights Actually, I think I had yeah way down at the bottom of this. It says weight 10. They all have weights So you can you can the order of the ammo file is not necessarily important If you want you can list them in any order or any grouping and just change the weights Breadcrumbs. This is the thing that just went in today. So breadcrumbs are a huge problem for most people I don't know of anyone that actually really Uses the breadcrumbs that are provided by default in core There's about Dozen plus different decent breadcrum models and contrib and all of them do very very different things But they all do them in very different ways and some of them are actually huge performance problems And they're not very well written. So the one nice thing in Drupal 8 is that we have a Consistent API for how you change breadcrumbs on a page if anyone doesn't know that's what breadcrumbs are these right here. So Here's an example of how the the new breadcrumbs code would look so you start off you have a breadcrum builder interface Breadcrum builder is you know You provide a separate builder and you can have many builders running at one time and each one kind of claims You know that that path so this one if you don't have any new Fancy route stuff. You're still porting old code This one will run and it will just call Drupal set breadcrum if array return So this is an example, but the the idea is you just get an array of attributes You do whatever you need to do and you return an array So there is about four or five of these in core so forum module comment module book module those all provide Custom breadcrumbs. So instead of just on every single page. They want to change the breadcrum They have to repeat that code over and over again or put in a helper function You just register it completely separately and tell it which pages to run on So here's an example of comment breadcrumbs here. You have you say oh if this is the comment reply route This works on these these routes So then anytime it's on a comment reply you you find the noted and then you link The first thing is home, and then you have a link to the node Normally on a comment page. It would just be the comment name, but you want it to be the noted from so anyone can provide breadcrumbs with this new breadcrumb builder interface and it'll it's it'll kind of the Unify the ones that are consumed and the other thing is my favorite breadcrumb module was a breadcrumbs by path Which is if you build out your URL structure It just takes the title from each page before it and you have this nice breadcrumb that matches your URL And that's actually in core now So the default implementation of breadcrumbs is to look at each path and find the title Instead of just meant working off the magic menu structure Okay, so that was just a blow-through really really really quickly of the six different things I'm gonna talk a little bit about advanced routing so The first thing is these defaults So I in the example. I just showed you this one just says underscore form That means it's a form it has a class name after it and it just loads that class and Calls a build form method on it So these are the other main examples of the different kinds of things you can use So for example, we have controller a controller is when you're actually returning a full response. So for example You're returning some JSON or you're redirecting to another page You are completely in control of every single piece of output on that page And before if you wanted to return some JSON you had to like print Drupal JSON and code Drupal add footer and an exit or die just to make sure that the theme didn't Print print out the entire, you know page and breadcrumbs and menus and everything This is saying, you know Drupal don't put anything else on my page. Everything. Everything. I'm returning you is everything It should go Content is the opposite of that. That is saying I'm putting something in the main content region. Please do all of the other things There's a couple other very specific ones that are for entities So in Drupal 8 everything is an entity. I mean almost everything everything that's not an entity We just didn't get done in time. Everything's an entity So we have three different routing defaults that are intended for the entities So for example the node edit form you have this entity form and you say entity form the entity type and Then the operation you were performing and this will automatically build you the entire entity form that you needed same thing with lists we have these lists of content so You can list your Content types or you can list the nodes which generally done with a view But if you're not using views you can you can provide an entity list and you just say entity list and then your entity type And the same thing for like the node view page You say I'm going to view the node and that's it's the view mode that you can put in here So this could have been teaser or if you're using any custom view modes. You can put them in there oops, so routing parameters so Before in Drupal 7 you sometimes had the little percent node And that man meant that you magically called the node underscore load function and that would give you your node back And you could write those for anything, but we found out that 99% of every single Loader was for an entity type. So this will magically match If this it'll look for this curly brace and anything in here if that's the name of an entity type It'll try to load it. So for example, you go to this page and it's the manager content type page So if this says the string article it will load the entire article node type object So that can get kind of tricky and there's other ways to add your own Upcasters, which is what they're called it. They take this placeholder and the value you provide and turn it into Something else generally an object But for everything that you're doing with entity types and entities, this will just work automatically So there's also the ability to pass a default parameter So if you have something like this just says admin structure types But if there's nothing in that path that says it's for nodes or node types So we have this generic entity list controller class that says I will list anything and you have to tell it Why entity type to use so we can just say entity type and you'll see here This entity type the actual parameter name has to match exactly to the machine name you give here So it's gonna call the Drupal core entity controller and you do this controller with the listing method with node type Passed into entity type ends up here You have the any list controller the listing method and it passes through entity type So if you can provide any arguments you want to your routes even if they're not in the URL When you pass them like they're in the URL that is the equivalent of an optional parameter. So this is the views The views edit form normally when you go to a view edit form It loads like the default display or the page display But then when you click to the different displays you have like it'll be like slash block slash feed But it's optional. So this display ID here at the end is completely optional. So we say display ID equals no That way it doesn't require anything While this view is obviously required So that would be the the machine name of the view it gets turned into an object and the display ID if it's not Specified will just be turned into null Routing requirements. That's the bottom of the the routing info This is just a way that we it's kind of like the access arguments in Drupal 7 but it also has a little bit more power to it So you'll notice all these things have different underscores in front That's like a machine. It means internal like don't mess with it compared to this Excuse me display ID, which has no underscore So this underscore permission is the equivalent of calling user access So it says okay this they can only get to this round if they have the permission administer pants These are some other examples of access checkers So if you used to do access callback equals true, you can just say access true For example, if you want it to be if you used to write Oh, you have to have the access callback was a function that checked and said it's if the user was logged in you can just say user is logged in true and This access theme for example was used by the blocks module So if they if you want to make sure that they have access to the theme that that page is for you You can just say access theme and it'll check which theme and ensure they have access to it You can also get a little bit more complex. So in addition to the permissions ones We have entity access very similar to the entity form and any view It's the entity type name and then the operation you were performing So if you just put entity access node edit They have to have the ability to edit that node that will check, you know All of the different things like the permissions and if they're uid one and if they're the owner of the node all that logic Is kept elsewhere still and you just tell it which entity type and which operation When it comes to creating that implies, you know any access implies you have an entity and you want to access it when it doesn't exist Yet like if you're checking access for the create form you use a separate entity create access And this one is even more complex. It says that we're creating a taxonomy term But also check and see which vocabulary was in the path So it knows which vocabulary to create that term for so you can you can add some very complex access checkers That inspects the path And do and perform logic on it also at the bottom. You'll see access mode any so As of right now this moment it that's the default, but it's being switched to access check access mode all and That way that if you list multiple access checkers, they're all anded together So they have to pass all requirements if you wanted to say they only get to this page If they can administer nodes or if they can edit that node, you will have to specify any And that was another thing that we didn't have in Drupal 7 where if you wanted to combine two or three different types of access You had to write a separate call back and then check them individually now You're able to just stack them in a row and you don't have to write any custom code all these are provided for you The other cool thing is you can do regular expressions on these and with no extra work So for here when you're on the views UI and you're enabling or disabling a view There's an op we only allow enable and disable there's no other operations to perform But we didn't want to have to define this whole route twice So we said the only valid values for op are enable or disable and that's just regular regular expressions Same thing with user view. It ensures that To prevent it from clashing with like user login or user lock out. We say user slash something has to be a number So that's a regular expression for a number. These are not subject to the Any all rules these are applied first. So if it doesn't match the regex then nothing else will happen but you can get really creative with those and They're very very powerful so Controller so I've used the word controller a couple times That's just the callable that we're using instead of what we used to call a callback You symphony allows for many different ways to use controllers, but everything in Drupal 8 now is a method and it's a instance methods non-static method and But it is its responsibility is to return the full HTTP response if you're using that underscore content that Drupal will then take that and wrap that in a full response But if you're using underscore controller, you have to actually return a response object So let's put it all together here. So this is the block admin form. So if you're adding a new block It's got a machine name and it takes two parameters plug an ID and theme but the theme is optional and It's got a title the title is configure block and of course its administer blocks is the permission check This is the actual class. That's in core So those plug in ID theme that are in the routes as placeholders are the exact Parameters of this method plug an ID and theme and it says and you'll notice that even though we said theme was optional There's no equals null there Because we specified null here So it will always have a value in Drupal 7 you would have written that differently You just had plug an ID comma theme equals null in case it wasn't there. This ensures that there is always a value So then it just calls out to the any manager and creates a new block and then presents the form for it So this is the when you write a controller you want it to be about this size You don't want to put everything all of your application logic into that entire method You'll see this delegates to two different things the storage controller and directly to the any manager It first creates the block and then gets the form in Drupal 7 This code would actually create the new block object as a standard class and then have the form code in line This way everything is kept separate. It's very very clear what this this method does it just creates and then hands off to the form So you should strive to keep your controllers Thin as they call them. You'll also notice here a controller base So controller base is completely optional. There's just a lot of helper methods inside of it So this is a controller base It gives you the any manager quick access to cache the config for configuration management The module handler to check is it installed, you know what? invoke hooks and alter hooks L for links the current user instead of using global user all Controllers can just ask what's the current user and you don't have to worry about global user anymore the T fun method which replaces the T function and then a quick way for doing redirects and URLs I know when the there used to be Drupal go-to right everyone remembers Drupal go-to and it did about 27 things based on what you passed into it And most of the time you just use it for a simple redirect But then they replaced it with all these different methods and I remember when the change notice was posted Everyone on Twitter went crazy and said oh my gosh I have to write 20 lines of code because I can't call Drupal go-to anymore But we just provide a method that is the 90% use case of it And now you don't have to look inside there at all you just tell it what route to redirect to and you're done And same with URL. It was the same thing. We used to have this little URL function It is now an entire URL generator that can handle the internal the external and path based and route based and All we have here is just URL that takes the 90% use case and puts it in this controller so the controller base class so this is just very useful for you to Cut down the boilerplate of your controllers and just call the things you need to do So these are just some example form classes. I said earlier. We used to have system settings form. There's now a config form base Confirm form went the same route. There's no more confirm form It's now a confirm form base that does all the things where it has it asks you what you want to do And it presents you with a button and a backlink and all that stuff is in a in a base form that you Just extend and don't have to worry about And then each of the individual previous page callbacks like node form user profile form user login are now all classes in their namespace So you have node form profile form and user login form Form interface is what guides all of these you saw when you had the beginning that Content and controller took a class name and a method name But y'all form just takes a class name that works because there's a single form interface that every single form will use Plugin forms block forms entity forms your own one-off forms. Everything will have to use this I remember when I first started using triple It I had no idea how validate and submit worked some of them It seemed like it was magic some of them specified them in the method and the function and some of them did both Instead of that you just have this interface that reminds you these are the things you need to do Get form ID is only because it used to be the function name would become your form ID and Because PHP will only allow one function of one name. It was magically enforced to be unique now You actually have to specify your form ID But you can then create what make it whatever you'd like and you can even include logic in your get form ID method And then build form is the old you know the actual used to be the function and then validate form and submit form are the methods that replace those old magical callbacks But the nice thing is when you set up your form you can have all your dependencies and then your build form you can store things It's instance variables or properties and access them later And all your code that kind used to be just spread over three or four functions all becomes one nice cohesive class And if you have multiple buttons that have multiple submit handlers You can just add other methods here and specify them So you don't have if you have you know a form with maybe three buttons on it like there are in core Instead of it being six functions. You can have just one class with six methods So that was the end of my whirlwind tour of routing I have to put this up here to remind you all to come out and hang out tomorrow I'm gonna now start taking questions and showing off other things and I can go back to anything I talked about So is there someone with a mic or a mic thing? Okay shout and I'll repeat your question pants namespace Oh the PHP namespace stuff. Yeah Okay Yeah, so the question was some people are saying that your modules shouldn't be in the Drupal namespace and other people are saying it Should be and what do we what's enforced? What's the rule? So the rule is they have to if your stuff isn't in the Drupal namespace. It's not a real module We have no one's tried that otherwise The people who say it probably shouldn't be in the namespace are right But that's not how the Drupal ecosystem works yet. We're not there And that gets into whole sorts of like using composer. I'm sorry using composer in interesting ways And kind of revamping how modules coexist with each other, but right now now everything has to be in the Drupal namespace It's just that's how it works in the middle Right, so I think I had that on a slide, but I didn't talk about it. There is a Yeah, I didn't talk about it. I did put on the slide in case someone asked so Before you had title titles easy. It's static, you know, you have title call back So all it is here is another one of those underscored Things in your defaults and you list out the method that's called 90% of time That's going to be a method on the same class, but it allows you to reuse other ones So for example like the entity page label the generic one you can even specify that Right, so I didn't get into that because a it's crazy right now And we need to fix it and I didn't want to do a whole bunch of slides on something. That's terribly terribly confusing that so the question was what about Jen dynamically generated routes, so in your hook menu used to have a for each loop or conditional logic and stuff and there's other ways to do that It's called a route subscriber, but they're insanely verbose right now And we've just been kind of chugging along and there were only one or two and they were in like modules like views UI So it wasn't a big deal, but now that we realize that like most of contrib and custom modules will need that functionality we need to revisit it and To come up with a better way to make it easier for you to do that because it's I mean I can show code It's basically you have Well, it simply there's a whole concept of events instead of hooks and you subscribe to an event and it says okay now Build me all your routes and you actually have to Build them in the like as PHP objects and return them So I can show one Wow, that's big. I Can make that a little smaller I think Can anyone still see that? Yes, okay great, so Well, that's really big still okay, so yeah, this is a that's a bad example. I'll use field UI So the field UI has a bunch that you know You have all the different every entity type has its own page with this like manage fields manage display So this is just a class called event subscriber interface we call it a route subscriber and It has a method that you get this event You can get the existing routes from it and then this just loops through all the entity types and it's the same thing as the yaml except in Parameters to this object so you just create new route objects and pass them through So this is the same thing where here's the path. Here's the defaults. Here's the requirements Except it's as I said like setting this up is really complex every time I do it I do it wrong and I've done like three of these already So we need to and I helped to write it and I can do I do it wrong So we need to come up with a better way, which is why I kind of skipped glossed over it There are this the six or seven examples in core, but those are hopefully I will to change That's something I want to work on this weekend So I hope that answered your question. Okay anyone else next yep, so Where do okay, that was really good. Where do controllers get their dependencies from like services and stuff so It's a very good question. There are there is a special interface Called container injection interface and if you're a controller and you'd like to have so okay for everyone It doesn't know what services are. I'm sorry. You should have gone to Larry's session But there's these global helpful Objects basically classes that you might want like the caching Factory or the entity manager and you would very often want those in your in your classes And that's what actually the Controller base was when I was saying oh controller base has all these helpful methods That's just getting those services for you So if you need other dependencies, you can implement this container injection interface And it will when creating your form let you pass things to your form So there's a I mean there's like 150 examples of that in core So if you need other services and you should I mean you should be handing off to your services You shouldn't be querying that database directly under your controller You should be asking like a manager or something or a repository what to look for You can use this interface to to get those injected Follow up Right. So the question was would it be better if forms or controllers in general? Sorry Where services themselves and yes, you can use service names instead of class method in those YAML files So when we first the very first module to use routes interpolate was views UI We decided to pick the hardest one first just to see if it worked And when we wrote it all every single one was a service But that meant I mean already you have to just like you didn't dribble seven You have to declare it and hook menu and then write your callback in driplet You have to put it in routing YAML and then write your callback to do it as a service You have to declare it as a service declare it in routing YAML and write the callback And the other thing is that then you have this kind of You have all of your useful services that are actually like stateless helpful objects Mushed in with all of your controllers, which are one-off and thin and and whatnot So it was polluting all of our services. So we chose not to do that If you had some very very very useful one that you wanted to do you can and you can do whatever you want in contrary I mean custom code so you can do that. It's just we decided it was to verbose and there was no real gain Okay, next question Seriously, okay No, yes in the way back Sorry is load keys What keys are allowed in the YAML files? so, yeah the what keys so these the path defaults options requirements those four keys are straight from symphony so the symphony documentation has you know explains all of those and each of the underscore ones in here are our Intern they map to our code, but they follow the symphony patterns So each of these like access mode and access theme and permission If you you know if you grep for them, you'll find the class that defines them Explains what they do, but the path defaults options requirement stuff is straight vanilla symphony and Can be found either like I mean there's plenty of documentation online, but they actually I think That's wrong class So it's in the constructor of the route object path defaults requirements options so and you can actually also do like other things like hosts and schemes and stuff like for You know other stuff, but those the these are documented there and and there's really good symphony has actually really great documentation So all right next question. Yep down here. Yes So in form-based controller validation is required the method is required And there's actually I didn't mention this so just like there's controller base and we had form interface there's a form base and it Gets a lot of those other the same methods and it also just puts an empty validate form So it says validation is optional so that way you don't have to do it I mean you can just leave it you could do that in triple seven You could implement the validate callback and do nothing. It doesn't matter unless you've set an error or something So yeah, so this is there. So you don't have to have that in every class But almost every other form has a you know has a build form obviously and 99.9% of them have a submit form Okay, there's another one Other question Someone's pointing. Yes. Okay you again Yeah, so the question was you still use form set error No one has pointed that out yet that we're still doing that There's a couple. I mean that obviously the goal has been to Remove as many procedural function calls from inside your classes as possible but the main one of the main reasons to do that is for Unit testing and if you want a unit test form API, that's your problem Until we rewrite form API as you know object-based We're not really looking to do that So most of your forms are obviously still going to be tested with a web test of some sort Larry Right. Do we use any of those yet? Actually not really Yeah, so there is the ability to use different MIME types and specify them I don't know offhand where we actually even do that. Although I do know, sorry. Oh Sorry, the question was as you can actually see from this route class In addition to those other things we now have the ability to That's not it specify Like the URI scheme or the HTTP method that was used so that it'll One can be used for JSON and one can be used for HTML And that way you can reuse the same path in multiple different ways And I didn't put it to get any slides on that because there was a rest session this week But it is very possible and it's very very cool I was mostly shown off the stuff that you could do in Drupal 7 as well But there is a lot more that you can do now Okay. Yes again. Yes Okay, so the question was in Drupal 7 the menu hierarchy was just determined from the paths themselves and from your hook menu And now you have to explicitly specify a parent and you're saying you don't didn't really care in most cases so right so the the thing is we there's a lot of magic in that and if your Paths change or if you want something to be in that hierarchy It's really hard to get it in there And there was always a lot of hacks to set like especially with menu set active breadcrumb in the callback itself to trick it into thinking It was in that menu Now it's you can being able to specify explicitly and forcing you to set the parent We'll make it faster to compute the hierarchy And make it easier to figure out what's actually going on and we'll make it easier to do things that aren't strictly Based on your path So it's considered a feature not not like a we didn't do it on purpose to make your life worse. I'm sorry Yep, so to sum that up. He doesn't like any of this So your point is that yeah hook menu doing too many things was it was a good thing and it made your life easier and it was easier to write and It was the job of menu.ink to figure it all out the end And that's true until you actually try to do something a little bit more complex Like has anyone tried to set up default tab and local task with a view And done it right the first time Good because it's not possible It's like undoable. So it's very very very complex to do especially with the relationship between default local tasks the path itself and The local tasks to get that right the first time And I think maybe local action is a good example of where it was nice to do But the the idea is that this local action has nothing to do with your route And we have these route machine names now that we didn't have before everything was keyed based on the actual system path Now that there's machine names You can swap out what path it's on and it'll just continue to work. So let's say I want to move node add to Content add I don't need to use any alicing aliasing or anything I can just say the node add machine name route is now pointing to this path all the local actions all the local tasks Everything will show up exactly as it was before with completely different URL because everything's built around this machine name So it allows a lot more flexibility to do things you couldn't do if you continue to build your sites exactly as you did before This will probably seem verbose But the idea is that it'll it's easier to understand when you're trying to debug something harder And it gives you a lot more flexibility that you just did not have before Blue yeah, I can't I'm sorry. Can you start over? Yes, so in Symphony you can Take an entire set of routes and replace other ones or add them in and so that's exactly what views does So for example when you if you install Drupal 8 with just the minimal install without views You still have an admin content page and an admin people page And that's on a specific route and then when you enable views we have those views there that replace them They're not well in core they're doing it wrong But the idea is that they will actually then directly replace those routes and you can add on a set It's just like we have info hooks and we have alter hooks those route subscribers There's a there's a dynamic event It's like the info event and there's an alter event. So you have two passes at it in addition to defining static ones There's two separate events to let you change things and add entire sets based on other ones and introspect that There's another question next to him Right. So the other those route subscribers with the dynamic events You as I said you have to two passes at it to get everything you want Why we didn't because we didn't really think about it and then right now I think if you so the question was why are we doing it wrong in core and It's because we didn't know any better Now we found out that we're doing it wrong. So we're fixing it Okay Yep, is there a way to have a menu that skips the bootstrap? There's no way to specify the bootstrap level of as far as I know anything you can't decide that for yourself Unless you're writing completely external Drupal code So unless you are manually doing the bootstrapping from outside Drupal you can't control when the bootstrap stops You get it or you don't and menu links. I mean menu links are in the UI. They're super not Vital to an application level. So you can have routes and without menu links at all And you we could reuse Drupal routes outside of triple context, but no, there's absolutely there's no way to do that so what he was saying was that as we've progressed throughout Drupal 8 we've Tightened up bootstrap made there be less bootstrap levels less things need to be done in order to have Drupal run and Try even repeat the other thing you said is a bad idea You can actually listen at the request level before Drupal even gets to it and kind of intercept it and Prevent the rest of Drupal from working which is cool, but probably not a normal thing to do. Yeah We didn't tell you about it. So All right Anything else? Yes, I'm here Okay, so the question was we've just finished replacing a hook with about six different things and Is it will we see more events instead? So the one thing I think is a shame in Drupal 8 is that we won't have enough events There are very very very few events and I think most of our events are actually fired from symphony code Anyway, like this routing thing is not we're not dispatching that event. It's just happening There was a lot of talk of actually replacing all hooks with an event that happened to call the hook for you So no more module implements or module invoke all That just didn't happen and I don't think there's enough hook events in core And we might want to add a couple extra just as an example so that people do it right and contribute But I think a lot more of those will be events by Drupal 9 for sure Events are really cool and they I don't necessarily think they're any better or worse than hooks We did kill a ton of info hooks, but those weren't even hooks anyway They were just a way of declaring data so but the true the true hooks that are reacting to events. They're still there for the most part In terms of I don't no one is really benchmarked it as far as I know I mean there was the benchmarks of the implementation of Backwards compatibility having both at the same time for every hook and that was bad I don't think anyone actually benchmarked ripping them out just because it would be way too much work to do in core And I mean hooks are like our thing so we weren't ready to just rip off the band-aid Yes Yes, there's the question was is there any way to do multilingual paths the answer is yes they do that I Couldn't tell you offhand how but I know they do there's the well the same thing where you can have domain or path prefix or query string and all those still work and And So yeah, I mean, I don't know at what level did they do that but it's definitely There's enough places to interrupt this flow that you can do almost anything as Carl said there's a request listener You can beat Drupal to the request and do whatever you want So I mean obviously you can do anything, but the other the look the translation stuff is working so they must have done it somehow and That's the nice thing is there are a lot of complex use cases already using this code So there's a good chance that your contrib modules not more complex than the entire translation system and to use UI So there's a there's a lot of code to learn from if you hit a problem All right, then that's gonna be it for me. Thank you very much for everything