 Can you see that? So apparently I'm, oh yeah. That's definitely on, okay. Should we make a start then? So, good place to sit with some identity instructions. So, this is me. I'm Phil Norton, I'm a technical leader at Access. You're very quiet, Phil. Am I very quiet? Yeah. I can hear myself on this microphone. It's a talk down. So, technical leader at Access, I help run NWDoc, which is the Drupal user group in Manchester. I also blog occasionally at HatchBank code, occasionally. And also, you can catch me on Twitter. So, speaking of NWDoc, if you're in Manchester in November, then please come along to our unconference, where you can get a great t-shirt like this. Yeah, if you don't know what unconference is, it's not, it's not like scheduled or anything. So you just turn up and people, the conference attendees give whatever talks they feel like on the day. So, you know, there's some really top quality talks last year, so well worth a visit, I think. The GIF hasn't worked, Eli. Yeah, so I shall wait for the GIF to finish. So, you've probably seen this thing, if you haven't, then you might see it in the future. So this is the service container in Drupal. So, I see this, when I first got in Drupal 8, I saw this thing a lot. And it didn't really make much sense. So, you see things like this, like there's a Stack Overflow article, and the guy says, you know, how do I get a path for a page? And the guy says, oh, you need to use this thing. So, this is Drupal service, current path, and I go, great. What does that do? Out of context, it doesn't really make it as much sense. And when I first saw it, I was like baffled as to what path current is and how it works. So, I'm going to try to explain that today. There'll be lots of code, so, I'm not sure if you want, but I'll be posting the things on slides online later, so, you know, feel free to number here all the weekend. So, feel free to catch me if you need. So, what are services? I'm not talking about web services. That's something completely different. These are internal things that allow access to a lot of different things in Drupal 8. This sort of wrap objects define a common interface between these things. They're automatically dependent to the injection. I'll come on to and cover a dependency injection in its entirety later. They're very powerful. So, do a lot of stuff behind the scenes that you don't need to worry about. And they are certified awesome because when I first found out about these things, I was like, okay, that's brilliant. They allow access to lots of different things inside Drupal 8, so, this is just a small selection of some of the services you can get access to. So, if you want to look at the config, run chronoclet caches or look at permissions or mess around with dates, it's all in there, ready to use. So, how do you use it? So, generally it's like this. So, your Drupal service thing will create an object, and then you can use that object to do something. So, take a real-word example. If you want to find out an alias of a path, you can use this. So, this is the path alias manager. We pass in some path, get the path by alias, and yeah, that's all we need. So, the path manager there is an instantiated object that we can use. So, it's a usable PHP object. You can also string it all together. So, you don't have to put it on one line in different lines just to do something simple. You can also, this is a pro-tip if you do this. So, if you put var and the object you want to access at the top and then what the variable name is, you can create intelligence in your ID, which helps you a lot to figure out what's inside your service and when you're using it. Which really helps a lot, so. So, where to find them? So, all services in Drupal are defined in a services.yaml file. So, here's an example of core.services.yaml, which is fairly extensive. So, you've got alias path manager there and you've got what class it pointed to and some arguments. So, if you look at the class, there is set in path.alias.manager and that's the class itself. Fairly standard I guess, but what's important is that, sorry, the constructor here accepts some things. So, you've got storage, whitelist, language manager and cache and these are the arguments in the definition. So, you can see each one of these contributes to the constructor in some way. So, a quick note on types. So, if you put at symbol, that's another service. So, Drupal will instantiate that service before passing it on to the service you're looking at. You can also do a configuration item. So, if you put the percentage symbols in, Drupal will transfer that into a configuration some sort and you can also pass in like a variable. So, config or true or something. So, you'll see a lot inside Drupal core. So, this means that when you instantiate the class, all these dependent objects are ready to use and this is what's called dependency injection. So, it's a good point to move on to that. So, dependency injection is a really complicated sounding subject. When you first look into it, it's like very extensive, but essentially it boils down to when I instantiate an object, I don't have to worry about all the dependencies of that object, I just get the object that I need. And so, in Drupal 8 Symphony, dependency injection component manages these dependencies for you. So, if you use the symphony world, it's very similar to what's going on here. So, rather than talk about dependency injection, I thought it'd demonstrate how useful it is. So, I'm going to try to use path alice manager without dependency injection. So, if I instantiate the class straight away, this is the alice manager class. I see I need storage, whitelist and language manager. Sorry, I can't obviously go further without doing that. So, I start for storage. The alias storage class needs a database and a module handler. So, let's go from there. To create the database, I can get the connection from the database. And then for the module handler, there's another object there, but I need to pass in root, module list and a cache backend. So, at this point that I've got root, module list and cache backend and you can see there I've made a decision. So, the backend is actually a database backend. So, I've had to create a database cache, which might not be actually the cache that we're using. So, I've cheated there by just putting in that logic there, but as it was basically been made before we even got to the object being instantiated. And at this point, I gave up, because what the hell, Drupal kernel and how to get that object is beyond me. So, at this point, you can see we've written a pager code and I haven't even got the object ready yet. And not only that, but if you drop this into your code, every time you need to access the path manager, you're in a world of pain because your code will be thousands of lines long just to produce a path. So, we can pull that down to this, which is far easier and far more easier to sort of follow. So, what it shows, so that demonstration there shows what Drupal's doing behind the scenes, but also shows that it integrates with decisions that your object's making. So, if you don't have a database cache back end, but a mem cache back end, it's twice as fast. What you end up doing is making decisions and Drupal makes those decisions for you so you don't have to worry too much about where the cache is coming from. I mean, this is an extreme example, obviously, but that's the sort of general thing that goes on behind the scenes. On a side note, there's also this dependency injection interface. So, any forms or controllers you use, they implement the interface, which is, or would speak, the container injection interface, which basically means that they have to use this create method that they can be injected with services from Drupal. So, you have this static create method which defines the service you need to inject into the controller or the form. And you sort of see this sort of construct around. So, you have this create method at the top. And you can see here we're passing in the country factory and the path alias. And Drupal will figure that out and instantiate a country factory and a path alias manager for us. And the usual standard practice is to store these in properties within the object, which basically means that when we're doing something inside that class, we don't have to do this, we can just do this. So, the services already are there, ready for us to use. So, quick recap before going on. So, services and dependencies all defined in service.yaml files. There is some other complexity there I haven't covered. And I'm not gonna cover that today, but I've covered the basics or we'll cover the basics. So, dependencies injection makes life easier. Controllers and forms have their own dependencies and you can inject those in a slightly different way. So, how do we build a run? Now that we see that what Drupal does, I can show you how to do your own stuff with it. So, if you have a module, you want to create a module services with numl file. And this is a very basic sort of template, but you'll see you've got services, what the service name is, the class that it points to and any arguments you want to pass in as well. Again, going service argument types, you've got that symbol which constitutes another service. You've got configuration item or some sort of variable. So, if we create an object looks like this, we see the config factory is actually the service that allows us access to the config. And this is the class we're gonna make. So, before we make the class first, we need to make an interface. I'll comment about how interfaces are important later on, but basically they allow easy overriding in the future and show that any pass dependencies conform to an interface and not just the class. Or revisit this in a minute, so there it was me. But this is the class. So you can see we're passing in the config factory interface and instead of just storing the whole config factory, what we're doing is going into the config factory and picking out a config from the module itself. And that's it. So then we can start using it. Pretty simple. It's a silly example obviously, but that's the basic template of creating a service in your own module. So let's move on to some real examples. So for a recent project, we built PCA predict interface. Who's heard of PCA predict? Used to be called postcode anywhere until they changed the name until this strange marketing thing. But so it's used for address matching and auto-complete informed. So you can get a user to fill out their postcode and you can match that to an address. So what we do is integrate with the PCA predict web service. And we created a Drupal service to wrap that web service. So what we did then was to create this PCA predict service. So this is the PCA predict services.yaml file. And that's all we needed really. Then we create an interface. So what we need to do is to find two different ways of accessing the API, which is find and retrieve. And then our instantiate class takes in the config factory, loads the PCA predict key on that factory, and then we've got access to find and retrieve things. So you can see that our object influence implements that interface that we defined. So it has to, it had to find and retrieve. And we've stored the API key in the property basically. That means we can do stuff like this. So we can pass in a postcode and get results. So we can find an easy list of results. And that's about it. So you can see, I'm not gonna talk about the complexities of the postcode anywhere API, but we've written the service. So all we need to do to access that API anywhere in our application is just to write this single line of code, which saves you sort of time and effort basically. So now we have services. One great things about Drupal services and a Drupal services component is that you can alter them, which provides a lot more sort of future-proofing complexity. So I'm gonna look at three case studies about what we did here. But basically, all services inside the application can be overridden and altered in some way. There's a service provider class that allows this, which are automatically detected by Drupal. So what you need to do is, if you have a class that needs to override a service, you create this thing called service provider with a camel case version of the name. So let's have a look at some examples of this action. I'll show you exactly what I mean there. So who's used the Shield module? Pretty good module. It provides a sort of basic authentication layer in front of your website. Really useful sort of keeping Google basically out of your staging science and things. One of the problems is that it also blocks the access to the API, so if you have an API inside Drupal, you need to authenticate against the Shield module and then authenticate against the API, which tends to be a little bit complicated for APIs to manage. So basically what we did is poke a hole in the shield. So we allow access to the API end point through the Shield module. So create a module called Shield Override. We convert the module name to camel case. So in that case, Shield Override becomes Shield Override. Prefix it, suffix with the words service provider. So our class then becomes Shield Override, service provider. And we stick that in our social directory of the module. That's basically what these are the only files needed for that module basically. So our service provider provides this alter class, alter method, sorry. And what that does is basically the container then contains a list of all the services that you can see inside Drupal. And what we do is we get the Shield middleware service. Which is the service that Shield uses to provide the authentication. And we override it with our own Shield Override class. This class also provides a register thing so you can dynamically register services, but I can't see how that's useful. So it even says that on the Drupal website. It says, this is very rare. So don't worry too much about that. So this is our Shield Override module. Sorry, it's Shield Override class. And you can see that it actually extends the Shield Middleware module, sorry, class. So it provides all the basic functionality that does. And what most of this is to do is if our current method is post.get and we're looking at our, this is a SOAP service, then we handle the service, handle the request in a normal way that Drupal would handle it. So basically without authentication. If we don't pass through this, then we just go parent handle, which then calls the original Shield module class. Which basically means that it's not indicated. Does that make sense? So we put holes in the Shield straight away by writing a couple lines of code. We didn't have to fill out as much. And basically these are, these are per, I guess, per project classes that we create. But it allows us to sort of, on the staging sites, like have a staging API endpoint as well, so. There we are. So another one. So we built the PCApredict module. But in order to use the PCApredict module, you need to spend money. So I think every transaction is like two pence or something, so it's not a lot. But if you're testing and refining your UI processes, that becomes a lot of money over a few days if you're continuously, you know, using that form when you don't have to. So what we did is create the stub module. So the stub subservice that doesn't use the API system. So again, we created a PCApredict stub. Convert the module to camel case. So PCApredict stub becomes PCApredict stub. And then suffix it with the word service provider. So it then becomes that we then have our three classes here. So two classes. So basically we are a service provider here and we've got a stub module that's sort of a stub class, sorry, that looks like the original class from the original module. So what a stub service provider does is it gets a definition of PCApredict and it replaces it with our PCApredict stub class. Makes sense? So basically instead of, so what we're doing here is we're using the interface, which means that we have to define a retrieve method. So that makes it easy so we can verify that we've got all of our API endpoints covered. But essentially it means that we can go from using the API to using CSV files or something just by turning a module on. And we use a system called config split. So when we deploy into a staging site, it automatically config syncs against the staging environment config and turns on this module. So we're not using any of these sort of, any live APIs on that site. Makes sense? So stub modules actually are really useful. Useful for preventing analytics from being sent. So recently I was working with a analytics practical called Mixpanel. And instead of triggering the events to the Mixpanel API, I created a little stub module just to write the API triggers into the log so I can see that what was getting hidden things. But basically it means that we're not polluting the live analytics system with staging data or development data. You can buy complex setups and firewalls. So if you've got an API that sits in a VPN and not many people have access to that VPN, then what you can do is turn on a stub module that allows your testers or your front-end developers, for example, to create an interface against that without using the API itself. So you just sort of mock the data inside that. I found this very useful, especially with complex setups, just to sort of get people started when they're using the product. You can also test without actually using the API. So you can turn on the stub module whilst you're in the testing mode and you know the input-output methods that you've got. So let's say, for example, slightly more complicated thing. So we created, actually, I'll just continue. So we used the group module recently. To manage members on a website. We then created a view to show the group members and some information about them. We added some Ajax filters to allow that user list to be filtered in some way. And so the group context was loaded into the view using context-filled path. So let me explain what's going on here. So this is our path. So we've got account one of the members. So views automatically picks up one, two, three as the group ID and loads that in the context of the view. So then we only show basically the people that are in their group on this view. What's happening, though, was that when people were entering email address into here, a clicking filter, it was coming back with access denied message. And the reason that was is because behind the scenes, the Ajax wrapper looks like this. It doesn't match that at all. So by the time it gets into views, views has no idea what this is and kicks back an access denied message. So buried inside the group module is a class responsible for this. And what this does is it basically loads the group from the context that it has. So you can see here get group from root is used. So if the group, if this context class doesn't know how to load that group, it doesn't know the group and so views doesn't know what's going on upstream because it's the access to the group that's checked upstream. So it needs to have that object in place. And I could see inside the group module that this class is actually defined in the service, which means that I had a mechanism there to be able to actually override that. And solve this problem. So I created this group view service provider in the same ways before. So group views is my module name and basically gave it this override class. So this override class is fairly weird looking but let's look at the important bits. So it just extends the root context from groups. So it doesn't do anything on top of that. It's then checks to make sure, and this is a lot of checks to make sure, that we're actually looking at the right context. So this is the right group, sorry, this is right view. It's sort of the right display type with an AJAX request. It looks like a group ID inside the postdocs, that kind of thing. We then load the group into the context for the group needs, this class needs and then we continue on as normal. So we just do everything that it used to have. And that basically solved the problem. So where I was able to load the group in the right context and present it to the view, which then goes, all right, it's this group. Here's the thing. Obviously I could have solved this by putting a patch into the group module but this appeared to be like a custom situation for us so that made sense at the time. If you want to look up any resources. So the Drupal actually has a lot of documentation on this. So you can look up the group container sort of thing. There's a list of all the services available so this is actually quite a good list of, I showed you a small snippet of that. There's hundreds of other services available in Drupal 8 so go and have a look. There's also a pretty good documentation on how to use all this stuff that I've just talked about. Just sort of head to the end of your dog on conference again. If you're in Manchester on the second Tuesday of the month, we also have a user group so please come along and feel free to ask me questions and things. None of us, I don't think, dressed like this. Anyway, any questions? Have I lost everybody in the first five minutes? No. So, while you're post-code example, one would probably create a post-code lookup interface and then a concrete documentation of that interface, say PCA post-code lookup interface. And then you create a factory, like a post-code lookup factory that will create the confidence to do this depending on whatever it is that you need to, in terms of what you want to do. So in your opinion, what does the Drupal service provide or interface, and what benefits does the Drupal give you every different or traditional way? So you're right in that you can build, so the question was about what benefits does this give you basically. So you're right in that you can create a third-party library to create a PCA predict interface and do all the sort of quirky auditorium stuff that way. But if you want to override that inside your application or change that in any way, then you're sort of stuck with the implementation of it. Plus, you don't get all the tools for the dependency detection. So you need to make sure you're passing the right arguments to that object beforehand to get everything ready and ready and going. So your practice is to download the library using Composer or whatever and have it within the system somewhere. We then have an interface inside your module that will instantiate the class and do whatever it needs to do to get that up and running. And then it provides you a little hook to sort of alter that in any way. So if you want to swap it out for a CSV file, you can do. But it basically means you're not relying on the underlying class. You can swap out that implementation if you like. So just by changing the service provider you've got inside your module. Yeah, okay. I'll just think I've solved that real quick. Any other questions? Any other matter? Yeah, if they're working with a triple console module I just wanted to know I haven't tried but is it possible to generate services, files, and skeletons with a triple console module? I'm sure it must be. Anybody do that? I think so. I haven't tried it yet but I work with it for forms and for different other kind of objects and it works quite well for generating skeletons. Yes. I'm assuming perhaps for services. Would you look at the file as well? I'm sure you must be able to, I mean, but then again it's not a lot of code to set up a services class. Yeah, it does. Do you have to have your module set up? Yeah, it does. Yeah. It does. Thank you. Any other questions? Right, well, I'm here all weekend. If you need to catch hold of me and go through any examples or anything but thanks very much. I've gone on to the truth of the end now. You know what's up, have I? Love you. Yeah. Just because I didn't have time to do the thing. Yeah, yeah. Because you and Dan, I know Dan, you know, yeah, I'm round the corner from you now. Oh yeah. I think so. With, um, Lincoln? Yeah, Lincoln. Yeah, you get it on the side, yeah. Hopefully, I'm up. The sign's on us and not the phone side with the dog, so at some point we are. Good, yeah. Thank you. Yeah, what's the service? I had it. Now, you know. Cold and it's the only thing that's going on. I like it, guys, thank you. You're all depending on the server. This is original, so, yeah? Yes, yes. Okay. So, it's okay, it's okay. You're expanding. This is not the same class. Yeah. So, it's not the same class. Okay, so. All services have an author. So, the little services I never found in that kind of thing. The service provider, okay, the service provider base provides an author. And that author method allows you to use that to the set. Easily enough, yes. So, that's the offer group of what I want to offer. Sorry, I didn't realize that. No, no, no. But I've got one thing that's interesting. Yeah, I've got one. Semiconductor class is that. So, you can just say, you know, so you could turn on, turn on the server. Eight seconds. Yeah? So, that's the usual use of the services. So you're returning a thing.