 Ie, mae'n bwysig, mae'n bwysig o'n gyffredinol. Felly, roeddwn ni'n fawr ar gael, ond yn cael ei wneud, ond mae'n gweithio yn bwysig, mae'n gweithio yn ei dda i'r bwysig. Mae'n arfer o'r cyfrannu, a'r arwtod drwng yn ddweud. Rwy'n ddim yn y tu'r cyfrannu. Rwy'n ddweud y tu'r tu'r gweithio yn y ddweud, oedd y cwmgrwythiaeth yma. Yna, mae'r olyf y Davies. O.P. Davis ond most places, so Drupal.org, Twitter, GitHub, everywhere really. One of the lead developers at CTI Digital, Manchester. Drupal 7 and 8 core contributor, module maintainer and contributor. So I've maintained modules like override node options, copyright block, if you really. Y symphony 2 hobbyist is probably the best way to describe it. So I've been doing a bit of research into Drupal, sorry, in the symphony 2. Probably the last six or nine months or so, really, in any depth. Just to try and get my head around that type of thing, really, prior to Drupal 8. I've released a few symphony-based things on GitHub, so if anyone's seen the Drupal VM generator project that went out of cover recently, that's something I wrote based on symphony console that builds a config.yaml file for you for Drupal VM. So ask your questions of what you want to do and build the file for you. So that type of thing, really. It's a type of thing we're going to cover, where modules are located in Drupal 8 and how they're structured, how to build your own module with permissions and routes. I could try and say routes. How to add your own control and service classes. What is the dependency injection container and how do we use it. And a little bit of our tools like PHP storm and Drupal console. So there's going to be, if you're not used to symphony or object-oriented code, you can pick up some new buzzwords, I guess. Do you like this? It's my right. This way? If the thing will stretch far enough, yes. Okay. Is that better? Okay. Cool. So module location, modules live in the modules directory. I guess most people, when they first come to Drupal, my staff included, went, oh look, there's a modules directory. We'll put our modules in there. No. Modules may go, as you all know, in the sites star something directory. In Drupal 8 they go in the modules directory. We expect them to go. Core modules go in core slash modules. So, yep, we can put modules in core slash module slash contrib and module slash custom. That still works. So if you're used to doing that in Drupal 7, you can still carry on doing that. I'd recommend it. So the simple module structure as we have an info.yaml file rather than an info file. Potentially a .module file. Permissions.yaml, routing.yaml, and any number of controllers based in the SRC directory. I had notes. So, yeah, new things. Yaml replaces the INI-ish format that we've always used in Drupal 6 and 7. As I mentioned, the .module file isn't always needed. So, yeah, only for using certain things we need that. It's quite possible to write Drupal 8 modules without the .module file. Permissions and routes live in separate files, as we just saw. An SRC directory for storing your classes. So, pretty much everything is done within PHP classes. No more .inc files. So within Drupal 6 and 7 we had a convention of calling things .inc. Those don't live anymore. And we use lame spaces and PSR for autoloading. So I'll mention a bit about that more in a second. So, if you're not familiar with Yaml, Yaml is a, I think the term is a recursive acronym. It stands for Yaml-inc markup language. Originally it was get another markup language, but it was changed. It's basically simple key value pairs. So, keys on the left, values on the right. Indentation matters. So, if you're putting child elements, you just indent them with two spaces or four spaces if you're doing a symphony. And you have to use spaces. So, if you use tabs it will shout at you. That's an example of the system permissions.yaml. So, the machine name is, can you see that back with the colours? Minister modules is the name of the permission. And the title is below. Indented study, so it's within that. These are using quotes. Core tends to use quotes quite a lot. They're not necessarily needed in Yaml. Unless there's a certain syntax thing that you have to use them, but generally we don't. Although in core we seem to quite a lot. So yeah, if you've got a basic module that just needs its own set of permissions, this is fine. If there's something like the node module, obviously the content types are different per site. So, we can use the permissions callback. So, this is how we do it in overhead options. Because again, the content types are different. So, within the Yaml we specify a permission callback. And this essentially is a namespace class with the double colon and then the method name. So yeah, that double colon is called a scope resolution operator apparently. And yeah, we'll see how those namespaces work in a second. So, is everybody familiar with namespacing? And maybe not familiar with namespacing. Okay, so namespaces are a way of having classes that are named the same that don't conflict with each other. That's the way I tend to think about it. So, the best way I've seen it explained recently was if you're organising your music collection, and if you have all your songs in one big playlist, you'll get some with the same name. The then conflict was if you group them with an album, as in namespaces, they're separated and don't conflict with each other. That seems to make a bit more sense to me at the time. So, everything is within the Drupal namespace. One, there is a Drupalism here, so we're using the node keyword in this example, as in the lower case one. If you're doing symphony, that'll tend to be camel case or whatever. So, you'll use the uppercase and for node, but we do use the machine name there. So, if they're in within the SLC directory, it would be Drupal slash node. If it's within a controller sub directory, it will have slash controller on the end. So, these match up with your directory structure essentially. And then override options is the same with the underscores rather than the capital letters, not with underscores. So, autoloading. So, autoloading is provided by Composer. Does every not know about Composer? Good. So, there's an autoload file in the Composer directory. There is one in Core as well, which will throw something else. It replaces the file square brackets syntax we used to using. So, we don't need to manually include each file or each class that we need. The autoloader does that for us. The standard is that use one class per file and the file name must match the name of the class. So, if you're doing a node permissions class, it would be a node permissions.php. The namespace must reflect the directory structure, as I said. So, what would in fact happen is Drupal slash node slash controller would be equal to Core modules node SRC controller. So, this is part of the PSR for name as standard for autoloading. Reaching. There is no more hook menu in Drupal 8. It's all done through using the symphony writing component, although the two did exist together for a while in the early stage of Drupal 8. The hook menu has gone all together, and again, it's all defined within YAML. The symphony itself does other things apart from YAML. You can use PHP or annotation, although in Drupal we're just using YAML. So, this is the example of the reading from the system module. So, this one is the machine name is system.admin. We give it a path, which is slash admin, a default key, and then the default key we have underscore controller. In the same thing, we have slash Drupal, the fully qualified namespace class, double colon, and then the method name. We also give it a title for our root. And we also use requirements. So, in this case, we have a personal requirement to access administration pages. Let's see that way. Again, this is a bit more of a complex example. So, the path routing, this one is using square brackets PID. So, that's a, we're passing a variable in. So, rather than using the percentage or like the percentage side we used to use in a hook menu, we use the square, sorry, the curly bracket name. The default system, you have a form. So, again, class name to a form, and then a title, and then a permission. So, the main thing, I guess, is the difference. This is the underscore form and then the variable. I was looking into why some have underscores at the beginning of them. So, you can see they have underscore form and underscore title. This is something I found on Drupal static stage site. Which is plain it. Underscores are special for everything that are not parameters to the controller. It's sort of the same then, simply. Okay, so, creating your own module. Create a directory within modules or modules as custom, as you sort of would do normally. We add .info.yaml file, and then we add any additional files that we need. So, .module files, .routine.yaml files, or .permission.yaml if you need them. So, I've made an example module. It's called the DrupalCatLondon module, because it's DrupalCatLondon. It's core is 8.x. There is a new type of module. So, that didn't exist in 7, but now I have to define the type. So, I could be module or theme, I guess. And the package works in the same way. I'll group them by package name. And this is fairly similar to the infosal syntax we're used to seeing. But it's colon separated rather than equal sign separated. And the number of times I've tried doing a Drupal 7 module in this way, and then we're trying to figure out why it's not working. Quite a few times, quite recently. So, in this case, we're going to add a route, a root, even. So, I've tried to not use the hello slash name example, but I've got as far as speakers slash name. So, in this case, we're going to make a path speakers slash name. So, the name would be an argument. Given the page or title called speakers, I've made this controller. So, it's because it's within the DC London module. The namespace is Drupal slash DC London. I've added a controller directory. And then the file and therefore the class is called speaker controller. And the method within that is called hello. And then it just requires on the access content permission. So, this is what this file would look like. Class called speaker controller within our namespace. The function is hello. The variable name is name in this case. And we're returning the marker. So, we still have render arrays. This is slightly different. So, symphony would normally you return a response class from HTTP foundation. But, yeah, we're still using render arrays. Pass. This should be fairly familiar to everybody. Using an array with hash marker at the beginning. The interesting thing with this, if you go back a slide, is curly bracket name. So, whatever is there, whatever that string is, that's what the variable name becomes. So, it's not done and position is done based on name. So, if I had more than one of those, I could reorder them. And then there's arguments however I want to, as long as their names match up. It's fine. In this case, we're just using the t function. The t function is still there. If you're not familiar with this square bracket syntax, that's PHP 5.4 array shorthand. So, it's using triple seven quite a lot with the PHP requirement being 5.5 something. You can use that quite safely. So, this is what that page would output. So, I've gone to speaker slash Oliver and then it's said hello Oliver at the bottom. So, that's fine. So, the next step would be to change this to a service. So, a service is just a class that does something. You also get some model classes, which are things like nodes, which is just whole data, but a service class is something that actually does a job and provides a service hence the name service. So, what we do in this case is I've made, within that SLC director, I've made a subdirectory called service. So, the namespace has slash service in it. I've made a new class called speaker greeter this time. With a function of greet, we're just going to capsize the first letter using the UC first function and return it back. So, very simple straight forward controller. And then, sorry, within the controller, we can import the class using the use statement. So, it's saying use anything within that namespace. We can instantiate it using the new keywords. We'll say new speaker greeter is this variable and then we can use the greet method within the greeter class and pass it the name. That works fine. So, services, all we've done is move code around. We haven't changed it. We haven't added anything new. We've just moved from code around essentially at this point. Service container is something that's sort of fitting new. If you're not used to using it, I'll put it onto things. It's added by Symphony's dependency injection component. It's an object that essentially holds other objects and instructions on how to create them. So, it's a centralized place for you to create all your service classes. It makes them reusable. So, you can reuse services in different modules. And they're only instantiated when they're needed to be. So, the drawback, if I go back slides with this approach, is whenever your calling speech name, you're instantiating a new speaker greeter class on every occasion. If you're using a service container, it creates one instance of that class and reuses it every time. So, it's better for performance. It also has a clean name. You don't need that. Yeah, the only example needed and there's only ever one instance, as I said. So, the service container is also known as the dependency injection container. They're the same thing. So, if we wanted to add our service class in the container, this is what we do. We'd add a mymodule.services.yml file. Our controller would then extend another class called controllerBase, which we didn't need to know how to extend before. But that adds a create method, which then basically means it has to us to tell Drupal how to create this class. Whereas before, Drupal would just make a new version of the class, but it wouldn't know what we needed to create that class with. So, that puts the responsibility back on us to tell Drupal how to create that, how to instantiate that class. We can add properties and then inject files to the constructor. And then we can reference them using the magic this variable by using this service name and then method name. So, in this example, we have in the services file we have services. We give it a name. It's DCLondon.SpeakerCru there. We tell it which class we're going to use. We also can pass a list of arguments, but in this case, it doesn't have any. So, we're just going to pass it in empty array. You still see. So, in the controller, we're importing the controllerBase class. So, we're importing it here and then extending it. So, we're including the constructor. We're going to make it greater property. We're then going to pass that through into the constructor, and then we're going to set that property. This is dependence injection, essentially. We're injecting the dependence into the class rather than calling it from within the class. The other thing I've done is change it to use a greater interface. So, there's a thing that says you should... It's one of the solid principles that you should build interfaces rather than implementations so that things are solvable if you need them to be. So, if I wanted to change to a different reader type, I could swap that out there as long as we extend the same class or implement the same interface, then we can swap them out quite easily. So, the main thing we wanted to do was use this create function method, even. So, it's a static method called create. The main thing that this gives us is this container interface or this container variable which is an instance of a container interface. And what we can then use is this container get method. And we can reference it by name. So, we call it dc-landon.speaker-greeter. That could be that variable. Then, out of this create method we're just going to call return a new static. So, static is just this class. So, if we're inside speaker controller, then it will just return back a speaker controller class. But we're also passing this speaker-greeter in there. And that's where that comes from, from that create method. As a result, within our hello method we can then just use this greeter. This is our service class here. And then use the greet method with the name. And it works in exactly the same way. So, again, the added benefit is that if we want to change the type of greeter we're going to use we wouldn't have to change this class at all. We have to change things outside the class and we can just inject in a different dependency if we need to. That's what we already said. Okay, so then, if we were going to take this a step further and if we say we were going to start logging results we can do it in the same way. So, we can add an extra extra property called logger. Within the constructor we can add another argument. So, the one that's used is the logger channel factory interface. We can assign it to this variable and then we do it the same way we assign that variable to that property. And within there should be a create function there somewhere. There it is. So, within that container we can get that also from the container call it logger. The name is logger.factory. We can then just add it into our new instantiation so we can call it logger here. That thing gets assigned to this variable and then we can reference it in the same way. So, we can then just say this logger without being the name of the class and then this is also done by the logger class. We can get the default type and then pass it in. So, that essentially logs our output. This bit is the same thing. Okay, so, the other thing that we can do within the container is call service parameters. So, within the same services.yaml file we can do it the same way, exactly. We can assign things as an argument into the constructor and assign it into a property. So, in this case we're going to set a variable. So, as well as having services within our services file because of parameters. So, these are essentially our variables that we're setting and passing it through into the constructor. So, we're calling this speaker-greeter.shout. We're going to set it to be false and then within arguments section. So, this previous, he was empty. But now we're going to change it to use a list. This is the way of doing lists in the aml just to use an indent and then a dash followed by something. We tell it that it's a parameter by using this percentage and this percentage. If you didn't do those it would just pass in the string which is not good to anybody. So, we just wrap it in the percentage signs and it passes the value of the parameter in. If we needed to inject a different service, we could use the at symbol followed by the service name and that would actually pass the whole service in rather than just the string. So, this works in pretty much the same way. We assign it to a property and we pass in the word shout in here and then we can use if this shout and then do things. So, I think in this case we're actually making it up a case if shouting is equal to true. So, that just gives us the flexibility to move conditions outside of our logic, outside of our classes. The one thing I haven't put in this slide actually is these parameters can be changed outside. So, there's a default, I think, I believe it's called default.services.yaml within call. You can include. Within settings of PHP you can tell it to include a local services file where you can override all these variables. So, if you wanted to change something, you could do that outside. You wouldn't have to touch any core code to change that. You just change the parameter you pass into the code. Okay, so configuration. So, configuration lives in the config directory within your module. Again, it's defined in YAML. So, there's the pattern origin. So, src slash install where you can add the files, add variables you want to set when the module is installed. You can then use an src schema directory where you can define what your variables are. So, they could be strings, they could be arrays. You can actually define what the variables are in that file. There is an src optional. That should be config. That's optional. So, I've seen it in the honeypot module where if somebody had the tool module enabled you can set variables that the tool module would use for honeypot. I haven't actually used that in any real sense yet, but it's still there. Yeah, that should be config. So, in this example within config install, I've made a new file called dclendon.settings.yaml. I'm going to set reader text as a parameter, have a name, and then within the controller we can do the same thing. Sorry, within the controller we can use stashDrupal so we can get the Drupal class on the global namespace the static thing called config. We can get the name so dclendon.settings dclendon.settings and then finally we can get the name of this variable. So, this would return back hello and then when we pass it through into the class it works exactly the same way. I've also made a form for this module actually. The way we generate forms is to add a new root in the routing file add a new controller in this house we're going to extend another class called config form base and there's two required methods that we have to call so get form id and get editable config names there are two things we have to use those are required by one by an interface and one by an abstract class that depend on later done the chain so those we have to have in my case then I use two other methods that are over a road called build form and submit form it's actually adding my own fields and things and my own submit handlers okay, that's gone a bit quicker than I thought so, useful tools PHP some I use a lot I've been using for about a year and a half now but generally you use an id rather than just a sort of tech editor one reason that I like PHP some is auto completion of everything which is cool auto import classes so when I'm typing out all those really long namespaces you can just start typing and press tab and it will import everything for you and there is a symphony plugin that I think has like 3 million downloads or something but it works very well with Drupal 8 because it's based on symphony which allows you to it also completes all your root names some YAML files that does loads of stuff there is a Drupal bridge plugin that I have used yet but looks interesting Drupal console everybody hasn't used it it's a command line tool that generates a scaffold's code so if you can tell it to just create module or generate controller or generate it will just write code for you based on questions although it does interact with your site so you can actually call things like rooty rebuild or cache rebuild and that you can get from Drupal console am I sitting your way sorry from Drupal console dot com just use download as a file and you can download it see in my slides I have got the actual module if people want to take a look at it I will put them up on github as well by the end as well as a quick walkthrough of this so you can get it on to the screen there we go and then we've got some question time still all this stuff so my modules directory we've got a custom directory which is where my DC London module sits this is my info file as we saw our rooting file is on my roots in it I'm going to collapse this down so you can actually see it so this is where I've put my hello my hello my hello root and then this is the config form that I made this is a cool thing a friend of PHP you can assign files to different things so I've marked this to be a sources directory so if I take that away it goes back to that orange color but then I can tell it to mark it as a sources directory so that knows that it contains classes to use a source I believe that the flagrants of directories modules custom DC London it's a very very small screen so because it's blue you can see a source strip but if there's an option hidden off the end of this screen you can tell it will also complete your namespaces as well for you so so these were where I put my controller so I tend so these don't have to be in sub directories but I like to make them that way just because it's easy to see what's going on so speak controller is the one that I was doing before so it's within the DC London controller namespace these are all the import files that it needs so it's using control base and it's got the greeter interface that I did all those things have been set over here it's good practice to put these dock blocks at the top and to say which type of things they are I couldn't fit them on my slides fortunately there you can see with these things so again it's good to type in things so we're telling it that this greeter variable is an instance of greeter interface or something that extends and I can't get over to the right and the same thing then it's gone that would be better there you go so then I've got the logger channel factory interface that is the logger variable again those both get set up here always set the parameters and then the return so it notes up in a reading code knows what these things are we're passing the name variable through as we saw this is me getting in the config put this away again so we can use the Drupal code method so this tells it that this is within the global namespace it goes back up to the top of the namespaces and down if I took that away it wouldn't find it it looks within Drupal within our namespace which doesn't exist this is where I'm setting the parameters to go into the container speaker greeter this is the service class that actually does the things that should be gone so yeah there's the shout variables being passed through set into this property here we can say if this shout or else so we can use stringDrupal you see first depending on what set turn that value back this implements the greeter interface so this is just a contract that says anything that extends the greeter interface has to have a public method called greete which is where a lot of the flexibility comes from so if I was going to change it to use a different thing as long as it implements this interface then it has that thing that it doesn't the speaker greeter doesn't know or care so this is not its responsibility to know what's coming in it just knows how to deal with it so that's always good practice settings controller excuse me this is my settings for the class extends config form base get editable config names this I'm getting straight from the routing from the services file and then the get form ID method just returns back string so these are the two that mandatory the build form method so this is very this has hardly changed actually the form API is very similar between 7 and 8 and we still build it forms the same way excuse me the default value then getting from the config in this case we have changed the appearance because we are extending this class this class also has a build form so we are returning we are running the parent version of build form as well we are returning it and then the submit form we are using this config so config is available by extending the other class can you set just say set this variable so this is variable set and variable get essentially we save it and then this and it does a drupal set message yeah so originally I had that as return and it complains excuse me okay we can get rid of that again because that's not right so that's actually that I'm going to put this code up on github actually afterwards people want to check it out and critique it and pull request it if they really want to that's fine but yeah okay so yes time for any questions maybe you've got any questions so you're taking a book that you might recommend for a translation from 2 to 7 to 8 I've been mainly looking at the symphony books actually so they're big if you've gone to symphony.com it's got all the components all listed out on there so I tend to go through that so that's the way I've approached it so you've got a build form so I used to really like the pro drupal books there is a drupal 8 module doing a book that's been written it's not finished yet but there is one on the way so that would be pretty good but that's at least what I've used up until now to get my head around a lot of the concepts in 8 so far that's definitely been helpful to be able to apply it in looking through this examples module is still there looking through a lot of core modules everything's really well documented in this but also I found a lot of the reusability everything is a lot more reusable it's like the number of times I've just said we use YAML for this and we use dependency injection everywhere that's consistent across everything so once you've learnt it in one place it's very easy to apply where else as well the plugin system which I haven't covered is very similar it works the same whether it's a block whether it's a migration plugin it's all very similar so the reusability is definitely a plus in the first example I was wondering why does the hash markup look like that might be funnable to exorcise itself possibly let's hear so the question was is it funnable to cross-ite scripting because it's going through markup in this case we're using the T function which is the same as what is in dribble 7 and depending on which thing we use here depends on the level of sanitisation so you can either use an exclamation mark which will pass it through as it was the same I think the axon will sanitise it without a placeholder and the percentage sign is sanitised with a placeholder so that should get sanitised just the way I don't know I think my first response is usually to actually call a response as you would do in symphony but then you'd end up with just a white screen with just the words hello something you wouldn't get any theming there or anything like that but then you'd have to use a renderer as we did in dribble 7 to do it I'm not sure if you just put in a string whether it would work try it afterwards sure this is so we've got the services section this is the name of my service what I've called it this is the class so it's within the DC London namespace it's within the service sub directory and it's called the speaker greeter tags are also a thing I haven't used them yet for this and then arguments so it's taking this variable here and injecting it into that and one thing that the symph I believe I can then just control and auto click it will take me here so the rooting the rooting that was a silly thing to search for wasn't it yeah this one so we're actually so here we're defining two roots we've got the speakers root which is speaker slash name and then this is the one that's the configuration most of the core examples tend to use slash something here I haven't both seem to work but this seems to be the convention in core at least any more questions yeah this so like with files like this with the casing yeah this is normally the way it's done at least with symphony usually if they're all done in this way so they all start it's not camel case I can't think what the name is I can't but they do tend to start with uppercase letters and then by word and then the file names have to reflect that fraud loading the difference being that yeah something like this with any time you're in a Drupal module normally if that was like a symphony thing it would be so Drupal Camp London if that was the name of the thing but we're actually using machine names it would be like the lower case name with machines in the same way that we have to use Drupal slash override node options slash controller so again if that was more of a symphony thing it would be sort of override node op that way but that's yeah that's just a bit of Drupal Drupalism there are still some Drupalisms there so but still Drupal T of this so the question was where but when I'm using T within the controller I think it depends on where it's what do you think the search for speaking controller yeah I think it depends where it's used because I've seen it used 42 yeah T yeah I've definitely seen it used sort of this T as well yeah both work in that case yeah so that's a particular function here from that trait yeah I've seen both I'm not sure whether there's sort of a standard for it I did try it doing it one way once and it broke so whether it was also in the wrong context but in this case it seems to work for both yeah it could also be a case that the T function is still there as it was but so I've deprecated so this is sort of my personal thoughts with Drupal 9 eventually are we going to take away things like T that are just there for backwards compatibility and then we'll break that layer sort of how Symphony 3 is done it so Symphony 3 is 2.8 without the backwards compatibility they've just taken that layer away so I do wonder whether in this case of T is the backwards compatible version whereas because you can still call things like no load entity load but this is deprecated and you should use entity manager slash something but I think maybe sort of not to work for that find the definition of that function what does that look like so this is a function called T it's within directed that's that's in the global thing but if I call this T because you have a lot of global names based on the controller so if I go api slash T let's see what it has so the T function obviously still exists okay when possible use tonystrings slash T otherwise it creates anything okay so apparently yeah we should probably just use this T function T let's just try this again so T as it was is just within bootstrap.inc so as long as that file gets included it still exists as it was so it's not within name names is this within me yeah it works pull across it sorry were you looking markup um sure marked as internal yeah I guess it's probably that no I think I say a lot of stuff still works like no loads still works that type of thing so a lot of the things still work but I guess try and use the new way of doing it as much as possible I guess any other questions because I think it's quarter two okay one more it's a scaffolding tool so it was just very much at the symphony console where you could just generate a router or generate a controller it would just generate the class but now it's sort of morphed into more of a it does a cash rebuild a router rebuild as well so it's sort of consistent it's very similar so yeah Drupal console well thank you very much