 testing one two when you press that one it goes green one two all right so now it should work yep all ready just so everyone is aware this is listen up Drupal and it's confusing because the booklet says it would be in a different room so there were some changes but the website and downstairs on the screen it's the actual thing I'm gonna wait a few more moments because maybe people downstairs are coming here because of the confusion all right I guess they will we'll get started then um goede middag or that's that's how we say good afternoon in Dutch listen up Drupal it's basically a story about event subscribers and these are the topics that I want to discuss first introduce myself what to share a little history of how I got to the session do some background information on the symphony goodies that you can all work with doing my take on how to work with controllers and how I combine it to create a new kind of do a new kind of API building in Drupal and if I got time I got some bonus content and of course I'll end with some conclusions so to start off who am I I'm Robert's and I'm a PHP developer at media monks I'm not sure if anyone knows us but we are a global creative production partner which basically means we can work with all the great brands in the world and we're with over 650 people in all over the world and it's not just Drupal it's basically everything digital from Drupal to VR to post-production and to go further with PHP in 2006 which is a long time ago I believe everyone had their own spaghetti framework who created their own framework at some point we're PHP developers so we like to reinvent the wheel do we don't we and then two years later we started doing Zen framework in 2012 we got composure and packages with which I think is one of the best things that happened to the PHP community a year later we started doing Psylex micro framework it's also from the same guys that created symphony and in 2015 we started doing symphony framework so I hear you thinking there's no Drupal and indeed I don't do Drupal however we have a team doing Drupal since a few years and that's how I'm involved other than that next to being developer I'm also daddy I'm a gamer I'm a DJ and I like my beers and if anyone gets this joke they know which game I'm playing I see one someone laughing it's League of Legends so my goals are with this that I'm showing you is to create a scalable team we have some Drupal developers but we also have a lot of symphony developers and it would be really nice to sometimes if we have a high demand for Drupal developers that we would be able to have the symphony developers join the Drupal guys and be able to actually help out on the project and combined strength it's really nice to see discussions between the symphony developers and the Drupal developers to see how things are done in Drupal and how things are done in symphony and I think we can learn a lot from each other there get people of their islands and it's one of the reasons I'm doing this talk I really would like to show you some new ideas that are totally not common in Drupal so please look beyond Drupalisms and my ultimate goal would be to look to make Drupal look like more like symphony framework and so some viewer discretion is advised I'll be showing some stuff that might be really uncommon and some things that you might see are really stupid when looking at it from a Drupal perspective please correct me afterwards if you see something really stupid but this is just my take on how I enjoy working with Drupal so a little history at the company we work with a lot of different background languages and all of them have their different frameworks obviously there's PHP but there's Ruby.net, Node, Python and we also have a lot of different frontends to work with obviously there's JavaScript we have iOS developers we have Android developers we have Unity developers and I'm still listening at Flash it's of course that but this is a big part of our company for many years so API for really messy we had XML we didn't AMP which is an Adobe message format it's ugly and now we use a lot of JSON or message back and we also had discussions about data how we handle status codes and error handling and pagination what would happen with form handling so we decided to come up with our own standard I think this is pretty common but it worked really well and we sat together with all the department leads we created our own API spec and everyone joining the company needs to read the spec or only developers obviously and we all the frameworks that we create are making sure that this spec is being used if you like you can read it but it's it doesn't really matter for you so to make it easier for PHP developers I created an event subscriber for Silex which is the micro framework we were working with back then and basically it allows you to return anything from a controller like a Drupal you can also return a response a symphony response object and you can return an array to render a view but I wanted to also return objects and such and also be able to throw exceptions anywhere and then it would convert it into the API spec this event subscriber was a single file there were no tests or anything so it was full of bugs but still it worked pretty well eventually I ported this to a symphony framework bubble and it was no longer a single file it's customizable it's tested and if you like you can find it on kit up this is also the point that I started doing unit tests it's really good you should if you're not doing it yet please do it because it will really improve your code and so to show some code and this is how a controller would look like to the sample you can return in this case an integer or a string and it would in this case just convert it into what we believe is our is the right spec for our company and you can also return an array or you can set your custom status codes or use any custom headers just return any response that you like and it would automatically convert exceptions into the errors that we've defined so you see code error matches full which is the thing I passed in the exception and it would also recognize a symphony HTTP exceptions so you can just throw a 4 4 exception basically not found and it would automatically convert that into the right status or the right error code this is something I'm getting back to later in the session but with symphony form you can just pass the entire form to the exception and it would automatically give you all the errors of the form or the validation errors that you got back so it's it's really easy for front-end to process this so profit is this is a lot easier for us to work with and it says a lot of time to not redo this in any every project but what about Drupal because that's what I'm here for so a little background on the symphony goodies first to get a better understanding of how it works and this is a phrase that I've heard a lot in the past few years Drupal 8 is using symphony framework which is actually wrong because it's actually symphony is a set of reusable components and there are currently around 50 and next to that it's also a framework so there's the symphony components and the symphony framework which are two different things so they're not the same and in symphony we have bundles and in Drupal you have modules and basically it's the exact same idea it's just packing combining a bunch of code you define your routes you can define services but unfortunately they're not compatible but it will give you an idea so what components does Drupal 8 actually use the most important ones are HSP kernel which consists of HSP foundation and event dispatcher it uses the routing component dependency injection and YAML and a few other which are less important right now so what the HSP kernel does and this is basically I'm pretty sure that most of you open the index.php at some point it basically what it does is it converts your request and it could be from a web server or a unit test and it converts it into a response that will get sent back to the user and if you open your index.php this is basically what you will see you can hook into this kernel with with event subscribers and that's basically what Drupal is already doing it's defining basically on the on the request that's getting in it's defining which controller to load which will do its thing and return return response. It's a powerful way to change behavior so what kernel events are there actually so these are the actual symphony kernel events there's kernel request and you can use it to add more information check something in the request like if there's some kind of parameter that's also a moment where you could maybe fetch something from cache and directly return it because if you can if you are able to set a response in this event subscriber it will return automatically and it will skip all the rest that it otherwise would have done. Kernel controller this allows setting or updating the controller that will be called and you can also use it to pre-initialize some other services maybe. kernel.view this will actually transform a non-response object response into a symphony response so this is also this is also what what is happening in Drupal when you return an array with views it will use this event to transform it into HTML. Kernel response you can use it to add some headers stored in cache inject content or serialize it maybe as JSON or or a message back something like that. There's kernel exception well I think it's obvious this will get triggered when there's an exception and you can hook into it and convert it into any kind of response that you'd like and this is not used often kernel terminate you can use this whenever you are using some kind of email or an email tool you can put the email in and when the request is sent already back to the user you can send out the actual email when the process is still running on your web server so the user will have a smooth experience while the heavy work is still done on your web server this is only working with PHP FPM so it's good to know. How do you create an event subscriber it's really easy you basically create your own class you implement the event subscriber interface from symphony and the only requirement is that you part of the interface is that you have a function called get subscribed events there you define all the events that you would like to listen to you point it to a method and then do your thing so in this case I'm setting a custom header saying Drupal loves symphony and if for some reason you would like to change priority because sometimes it can really matter much which event subscribers called before the other one you can set priority to make sure that yours gets run first or if it doesn't really matter you can have it a really low priority so that's what it's useful for and then you need to register the service in your service java file which I think everyone will know how to do so you can do it like this the most important thing here is to see that there's a tag called event subscriber and then it will get hooked into the system I would consider this the old way of doing it and this would be the new way which is a feature from symphony 3.3 actually and luckily Drupal 8.5 now uses symphony 3.4 so this is actually something you can do it's now a new thing to recommend it that you use your fully qualified class name as the name of the service instead of making up a name and then you can omit the class and it will use it will assume the class name is this it's the name of the service so it's shorter it saves you typing and it's also some other advantage but i'll show you later so in this case i'm not sure if you can actually see it but this is response and the last line it will it will say a custom header which says Drupal love symphony so really easy to do so getting back to the the bundle i showed before this library only relied on htp kernel and so i decided to split the symphony framework bundle into a framework agnostic package and then i would implement only the part in symphony to glue it together um so i was really curious would it actually work in Drupal so actually yes it did i created a custom module with two yaml files and it simply did the trick um so i i think everyone knows the info yaml and the services yaml and i think the top thing is is most important i create the event subscriber and also a new thing that you can use all the code examples are assuming you're on 8.5 because it's cool i'm using auto wiring so it would automatically fetch the right service from the container so it this saves you a lot of a lot of configuration so there are some few more services that i that i needed but obviously that didn't fit in the screen so after that i created a controller in Drupal i created my action i called it and it actually worked and this was pretty much my reaction because i thought it was really exciting that i could do something from my symphony knowledge in Drupal and it would actually and it would actually work so then i decided to take a step further and also implement the way i like to work with controllers and the way i like to work with controllers is to use them as a service and i'm not sure if anyone knows how to use it but most people have have no idea that it that's it's a thing what it means is that your controller doesn't implement or doesn't extend the controller base which you which is provided by Drupal and you would only inject the service that you need that you actually need and this is coming from a documentation from Drupal itself document dependency injection is the preferred method for accessing and using services in Drupal 8 it should be used whenever possible so please stop doing this everywhere i'm seeing it a lot also in core don't do it because if you are typing this it means that probably you should be using dependency injection instead the advantage of using controllers and services is that you can do everything with configuration with dependency injection and i think it's easier to do replacements of services or do refactoring by doing that it's easy to see your controller what's actually available and it helps preventing getting fat controllers because you should have small controllers or slim controller how you want to call it obviously there are also disadvantages because you need to create your own helper functions like if you want to render something or you know those helper functions better than i do but you would have to create them all yourself so in the end you will probably have your own abstract controller where you define those helper functions uh a controller is not used not usable most of the times anyway so why bother creating a service and it takes more time to configure but this will improve a lot when using Drupal 8.5 so how to do it um this is when i was looking at it this was the the way that i found in documentation by implementing the container injection interface and you would have to create a create function that would get stuff from the container and uh have to construct in there but now there's still a create function there that that's tied to the framework that you're using and there's so i'm not really happy with it so you can also do it without create and then it would look like this which is really clean it's not tied to Drupal at all you can just would be able to take this controller put it in another framework using um htpkernal and you would be fine um you can register it like this so it's just a service like any other and if you're using the auto wiring um i'm using a word generator as an example now um it would auto wire it so that makes it really easy to auto configure and all of this and as you can see uh i wanted to show an example on why it's helpful to use the the class name instead of the name of the service as you can see here um return new static and from the container you would uh get you would use the the class name of the um of the service instead of having the the kind of the name that you came up with to well defining the service i think this is a lot more readable um then you need to set up routing yes i think we can probably spend another session specifically on that but what it does is um let's go to this one uh in your construct i'm requiring now the the word generator and um here i'm defining the word generator generator yes it's clear all right and so it would automatically figure out that this is the required service and it would inject it so this saves you from setting the arguments manually basically um so setting up the routing it's fairly easy you just define your path and you set your controller and uh you use the the name of the service which is now the name of the of the class set the action and you're good to go um while i was looking into this it was undocumented so obviously i did the thing that was right and i added it to the documentation so you can you can find it there um then i think the most uh let's look at the time just to be sure all right um controller annotations this is something i believe is fairly uh unknown in Drupal in symphony we use it all the time and it's coming from a a bundle called the extra bundle and it's not delivered by default in symphony but a lot of symphony developers are actually using it and it allows you to create controllers by using simply simply setting annotations so you can define your route what method it might be restricted to uh if there's parameter converters or what template it's rendering security cache so this is basically the full-blown example of what uh the extra bundle can do and basically it saves you from going to your routing file and defining everything there it it can save you a lot of time um so can we do this in Drupal uh which was one of the first thing i was looking at uh what fine stuff uh nope you cannot do this in Drupal uh but uh it's based on uh event subscribers so i was thinking we should be able to do this and that's when i started or decided to port this to Drupal and uh this is how it looks as you can see it looks nearly the same as in symphony framework uh so you can define your route you can set your method a few things are different though because the security in in Drupal is different from symphonies um so i've ported that to make sure that it's the same and um this is how you can register the annotations from for the routing uh you can with paths you can give it a prefix like if you're creating an api you don't have to put slash api in every controller which is annoying and set the annotation type and set the name of the module and it would pick it up so you would be able to create a controller with these endpoints slash examples in this case would be api examples and have a get method for it and have a post method for it so that's really easy to work with um you can set all the kinds of security that you know so you can use roll access csrf you can make sure something is marked as admin you can uh give uh you can set it to render a template which i believe this is the correct way of defining a module or a template name so feel free to correct me if it's wrong i'll put the slides online so you can later bug me somewhere to make sure that i do it the right way um you can set cache uh in a lot of ways um because this is all parsed by symphony so it's it's really easy uh param converter and please note that this is actually a different param converter than the one that's already in Drupal there are different namespaces so this is the one from symphony um but this way you can make sure that you when you get have to show action that there's actually a article note provided before getting into the uh getting into the controller action so in the in the parameter converter itself if no article is found with this id you can directly make sure that this throws a not found exception uh this also is supported by default it supports dates so you can have any date format in there that you'd like and also you could create your own but just creating or implementing the interface you can have an apply to do anything that you want and support checks if the object or the thing that's passed to the controller if it supports this kind of parameter conversion so it's really flexible um i also wanted to port psr7 support which is something that is in the framework extra bundle and while doing this i found out that it's already supported by core so i didn't need to port this but it's just cool to note it this is actually a possibility in Drupal so how does this actually work um it's nothing more than acting on certain events and um it modifies the request and responds objects to um to do the actual rendering and make sure that everything gets uh gets done that needs to be done like for instance setting the security um for the routing it uses the route routing route dynamic event which is something specifically from Drupal but after all the routes are taken care of it will add the routes that were found with annotations um development process was kind of messy uh first i required the extra bundle from symphony and that that worked uh i created a custom module i registered all the event subscribers that were in the in the framework bundle or in the extra bundle i would fail it wouldn't work at all uh and mostly this was because of uh the priorities uh because Drupal already has a set of event subscribers and they were basically conflicting so i needed to make sure that the event subscribers from uh from my new module were actually uh being done earlier than the ones from Drupal and a lot of there were a lot of incompatibility incompatibilities and um act for example as security um and i need to redo it entirely and eventually i decided to remove the framework extra bundle entirely and um make it a separate module which was self-containing without any extra uh symphony requirements um so it worked and i was really excited by it and you can actually try it yourself uh i created a module uh from it and um uh it's good to good to know that i know eric is sitting there uh he reviewed it um and security wise i i think we think it's all good but it will never get a security batch because it's following psr standards sorry um and it's also primarily hosted on github and it's using trafic ci to do automated builds or multiple versions of php and drupal which is i think something that's really fun to do um so it should be compatible but there's no security batch um so using all of this i think it's nice to be able to create an actual api with this um content wise i really like working with fractal uh not sure if anyone heard of it but it's it's a library to convert any object into an array and um it's it's really nice it looks like this a transformer in this case i'm i'm getting a note object which i'm assuming now is an article because there's no type hinting for at least that i'm aware of for notes so you might would like to check here if it's actual it's an actual article um but then you return a return an array and this is something that will be outputted by your api and the nice thing is that you can use it for a single entity or single note uh all the code is it looks like this you have your fractal manager you define your transformer which is the article transformer and in this case you're saying resource item because it's just one and with create data it will convert everything to to an array um you can also do this with with a collection multiple entities you would just use a different one you would use the the resource collection pass the array of entities that you have and it will run them for every entity it also supports includes so if you have in this case an article you might want to optionally include the author and you would have a separate a separate transformer just for authors and that's why you can really create structure in how things are converted um so to enable these includes you would potentially use a get parameter or you would do it by code um it's it's fairly easy to to activate all of this be aware of lazy loading um i think everyone working with lazy loading or i think truple does it too i'm used to work with doctrine orem it's really a pitfall because if you're doing this it will lazy load every entity and it will mean a separate culture database for each entity so that could really make things slow so make sure to find a optimized way for loading entities first before you're actually starting to convert the entities just try it um it's not a truple thing but the thing i want to show is that you can use any php package in truple because it's all php you can just use what is there what's available so forms um i i hate to work with forms and i think most of us do it's it's usually very boring um but symphony form eases the pain i believe there's a great great builder it's highly customizable and it includes validation and the beauty is it also can be used in truple without any issues you can just use composure to require all of it and just start using it it doesn't because it's ruple it doesn't mean you have to use the truple form api so simplified example of how a form would be built is uh you add a title and it would be a text type you would have constraints it can't be it can't be empty and there is a minimum and a maximum length and um i think it's it's very clean because it's all code it it's not user arrays but it's just it's code that you can actually read um so an implementation in in truple could look like this again this is just how i think by looking at the documentation how i can do it if everything in my form is uh is uh is validated and it's valid um i can just use this to create a new note and uh i'm sure that then everything is valid and i would return my response saying created um you can also use twig to render these forms it's it's basically the same as in apis there's a handle request method on your form and it will take care of all the errors and stuff and it will it will all push it to uh to a form object which you can pass to to twig and in twig this are the only lines that you would have to use for a default form being rendered so this is very easy and it's really extendable because you can for any type of form or header whatever you can override the twig template so it can look exactly how you want it to be um there are four times for for every need i'm just listing a few but there's tons of them you can you can look them up in the in the symphony documentation and the same thing with validators there so many you can you can also create your own um it's it's really easy to work with um so try it sometime uh it's really well documented uh i wouldn't say the form component is the easiest i'm actually thinking that form is is maybe the hardest component in symphony next to the security component but if you are getting um uh if you're using it more and more you'll feel better at using it and you'll be really confident and it it will save you loads of time so putting it all together 45 minutes is too short to show it all but i created an example api module which combines all the things that you've seen in this session so it combines using form and the controller annotations um uh just the way how i like it with auto wiring so it does require drupal 8.5 and pgp 7.1 but i think it's just a nice example of what could be done with drupal we're taking a picture yeah all right um right let's see if there's time yeah we do uh so a few bonus things um another really practical use of of event subscribers it's uh using uh pre-render um and it's it's a thing we use for for co um because we've been working decoupled for for quite a few years at media monks and um um it's it's always a big thing because you would miss your CEO you would have a beautiful front end but it wouldn't be optimized for search engines um why are we doing why we're doing uh decoupled is because we have uh a really we are really big so we have the luxury of having a 40 front end developers being split into templateters and scripters and we would have different backend uh teams so like i showed we have python teams and so they can really do their own thing in front end that they would like to work with they have their own frameworks and we shouldn't be touching that um so basically scalability they can do whatever they like we can implement it how we want um they also need creative freedom uh we're really focused on creating beautiful experiences so you would need page transitions and stuff we have projects for which are using webgl and it's something you cannot do with refreshes and such so the ceo part um yeah it's annoying uh and there are luckily a few solutions uh you can decide to ignore it completely sometimes you actually don't need ceo it could be a short living campaign uh you can assume everyone uses google because google actually knows how to work with front end frameworks um you could duplicate a routing in back end um so when um when someone refreshes the page uh you would actually render the piece of content in in in a non-beautiful way and javascript will just take it over or you could use something like pre-render or phantom js which is a hapless browser which you can send a request to it will get the page render all the javascript and uh you would be able to do with it whatever you like so a common implementation for this is to have a request detect if it's a bot based on their user agent and then send it to pre-render and then give it back whatever pre-render sent sent back uh our implementation is slightly different because we're usually behind a cdm so we don't actually have access to the user's user agent because it's handled by the cdm so what we did was crawl our own website with with that tool and then every URL that we found we send it to the pre-render service we store the results in the database and whenever a request comes in we just try to match it with something that we already crawled or crawled before and if we found something we basically inject the content in the page that was crawled before and that works really really well so for this we created a crawler it's using generators so to keep because the first version didn't have it and it would always run out of memory so we were uh we updated it using generators and now the memory will always remain low it's highly customizable you can use white listing or black listing of URLs you can do normalization so if you want to strip out certain get parameters for instance you can do that so this would be a example like crawling our own website it would just be a loop and you would get any page back and do with it whatever you like um so for instance you could get the title of the page or you could get the meta description or get some content from a certain diff and just store it in your database and you're done um you wouldn't be crawling your your admin or your service pages so you can exclude those it's really easy or use the white list to only make sure that you crawl specific pages how you would be able to do this implement this into Drupal you would maybe with Drupal console create a command for it have an event subscriber doing the the request detecting the request and just return the response if it was found and like keeping it up to date you can use different things you can do time like do it every day or you can have some cms trigger like whenever this piece of content was updated make sure that the url gets crawled again into put it in some queue we also have a website with users priorities because some pages change a lot some don't so whenever a page is changed it would increase the the priority and that way it would automatically sort itself out and another big benefit is that you would have a full site search because you have every page in your in your site if it's auto generated or not if it's if it actually contains content from frontend like maybe there's jason files from frontend implementing content you would have all combined together and you would have a you could put in an elastic search and it's really easy to you to have a a search with that um also you can give it a try you can also if you want to do this in Drupal you can probably look at the symphony bundle because it already has a console command which is the same as how Drupal console is doing it so if you're interested just take a look at it more i do a few few things development made easier yeah five minutes all right development made easier working with Drupal was very hard for me because it would have all the caches and you would constantly have to clear cache or go or you'd trash to clear the cache or something and the things i'll be showing never use them in production please don't blame me if you for some reason do it at some point i've warned you this is a really simple way using event subscribers once more to just disable route cache so when i've requested come in you would first rebuild the cache and then whenever you are adding some kind of controller or some endpoint you don't need to mentally do the cache clear it it saves me a lot of time and also a disabled container dumping like when working with services it's really annoying to again to clear the cache all the time and actually the third parameter it was some it was really easy to do it but i first needed to figure out how the third parameter in your Drupal kernels actually allow dumping and if you set it to false it will stop dumping the container so whenever you add a service it's there on the next refresh so that that's really really easy to use and if you're working with services or routes use Drupal console use the debug options to search for specific services or routes it's it's really easy so too long didn't listen event subscribers are awesome i think it's really powerful and Drupal is built on it but you can leverage them to to make it even better symphony knowledge is really useful if you want to work on Drupal and it would allow me to help out on a Drupal project with even without even knowing how to do anything with Drupal because i have no clue how to build a content website with Drupal really there's more than Drupal.org people there's tons of packages on packages and it's PHP so it's actually things that you can use it doesn't have to be a module to to be used we can really learn from each other solutions i think it's really fun to see because we have a symphony team and a Drupal team and how we can look at each other and and discuss like how's Drupal doing this how's it saving its content and we're using this and we are actually looking for a way to copy how Drupal is storing its content to use it in symphony framework so i think that's that's really exciting please i'm not sure if anyone is not using it please use Composer it makes it so easy to do all of this stuff and in the end it's it's all PHP so it's easy thanks for your attention um are there any questions i'll shall repeat the question uh does it result in technical debt for only a few people knowing like you mean what's going on that maybe Drupal developers don't know what's going on in there um that that might be a risk that's a good point um but i think the concepts are pretty easy and when you would open up a controller it i think it's really obvious without knowing how it works um i think it's pretty easy to copy and paste it into into improving it or changing the behavior so i i don't think it will lead to actual problems uh but like i said it's it's my idea on this and i'm not saying you should be using it or doing starting with this right away uh but it it it could be an option yeah yeah well yeah if i'm saying it correctly please please correct me if i'm wrong uh the question is that would i rather see people move from Drupal to symphony to have the same basically the same way of working uh yeah i would love that a lot and i think um i i'm i'm really convinced that that Drupal could have been built as a set of of symphony bundles rather than than copying a lot of other stuff so uh i would really like to see the direction where Drupal would use more and more components of symphony um uh instead like config which i know is also highly debated um and i would really like to see that Drupal would switch to psr's more especially coding style um is it gonna happen soon probably not uh but would i like to see it yeah very much and i think it will there were these islands and i think uh we're building bridges now but it would be really great if if we would actually be in the same island or just create one piece of land um and i hope that this will contribute to make that happen and we're done all right you can find the slides there um if you're dutch you know it's a funny name but there's a few duchies out here um thanks a lot again for your attention you know me i'm excited about sharing the story yeah that's why i put uh like i did this session before at the tech conference and browsing code during this i think the the format of this i think the code example takes a bit more time for people to consume and maybe to you