 Rwy'n wedi bod yn ddim yn ymddiol fel y gallwn gweld. A'r ystyried i'r ddweud, rwy'n dweud eich wneud o'r eu ddweud yw ganladu. Rwy'n dweud, rwy'n rhaid i'r laptop yma o'r hwngau'r google o'r laptop Dupau. Mae'n ddweud i'r sphrein. Rwy'n ddweud yw'n ddweud. Rwy'n ddweud eich ddweud o'r ddweud yma, ac mae'n ddweud o'r ddweudio i'r ddweud. Just lowering some expectations initially just before we start. This is briefly the kind of thing I'm going to talk about now. I've put this slide in so if anyone's here for innovative journalism, you're in the wrong room and there's a sign on the door, don't know if you saw that. It's basically going to be about PHP middleware and this is something that I've only really been learning and using in the last year. But I wanted to share this because it's been a tool that has really allowed me to really cut a lot of complexity in some systems. First I'm going to talk about very briefly what I mean by that. This is Dystra who started the whole structured programming thing. Simplicity is prerequisite for reliability. Really it's kind of become my ethics of living my entire life as being about trying to simplify everything. There's an excellent talk by Rich Hickey called Simple Made Easy. Who's seen this talk? Maybe we should all even go and watch this talk instead of mine. Seriously the first thing you do when you leave go and check this out because it's amazing and you change your life. The real takeaway from it is that he talks about defining what simple is and pointing out that simple doesn't mean easy. Looking at the roots of the word, simple comes from simplex which means one fold as opposed to complex which means inter braided like many folds as opposed to easy which comes from something being nearby or at hand. So in our world that might mean that something is easy to get. It might be that we can do composer require ball of mud or that it's within the kind of thing that we're familiar with so it's easy. Easy has an element of subjectiveness whereas simple you can kind of get a handle of that by looking at how interwoven something is. In Rich Hickey's talk he brings back this archaic word to complex which means to interleave and to braid. We now have a word for when people are coming and add independence to our project. So this is kind of setting the seams because for me PHP middleware does offer a tool for decomplecting our systems. So another quote again mentioned by Rich Hickey. Programming when stripped of all its circumstantial irrelevances so writing code basically boils down to no more or no less than very effective thinking so as to avoid unmastered complexity to very vigorous separation of our many different concerns. So I think the key thing here is that programming isn't about writing code. It's about the learning that we do during that process. It's about how we master that complexity, how we deal with that and how we separate our concerns so that we can reason about it and then in the end hopefully write some code but not too much code. So with this idea of decomplecting, who is here for Ronald's amazing talk on microservices? Yeah, really good. So he'd already covered a few of these things in Think Talk about domain driven design. There's also this idea of hexagonal architecture sometimes called ports and adapters. So this is really just programming to an interface. So then at a later date you come and plug in an implementation. So it's a bit more to it than that but it's also to thinking about writing framework independent code. So ways of writing the actual important bits of our code and not worrying about the framework until later on. And in APIs is something that I've been working with a bit which is where essentially the API just becomes and this is something that's good if you're in an inversion of control with lots of stuff happening on the client side. Maybe you're building a rich client app. Then really your API could just be a thin layer of business logic on top of your data store. And also the modern PHP world with some of the better packages on packages have started to standardize around common interfaces. What this gives us is bits that we can plug in and switch around. So yeah, is anyone seems un-expressive? So it has this installation process which I've tried to blow it up a bit there. But this really shows the sort of modularity that's available in the wider PHP ecosystem because when you install this framework it doesn't just give you a whole bunch of stuff. It allows you to pick here the question which router do you want to use? Which dependency injection container do you want to use? Which templating engine do you want to use? And so you can really start to create the sort of environment that works best for you and take the bits and they will all inter-operate and work together. So I used this idea to think maybe what might Drupal be like installing in the future. So when we get to Drupal X, which we're all looking forward to, maybe in the installation we get to pick, do we want to use symphony's routing or is there something else we prefer? Do we prefer fast boot? Do we want to use that symphony's dependency injection container or do we really hate YAML? So I've fallen in love with something called PHPDI. Has anyone tried that out? So they describe themselves as dependency injection for humans and I really like it because you're writing in PHP. You're doing your definitions in PHP so you get all of those nice things that your IDE provides. But yeah, there are others as well and there's PSR11, which I'm going to talk a bit about PHPfig, but that's an effort to standardise the idea of a dependency injection container. And then maybe a question could be how do you want to define your content model? Do you want to use the Drupal's GUI entity construction kits or do you want to use a data map LRM like Doctrin or do you want to maybe use the Laravel LRM, Active Record LRM? So yeah, that's possible, right? We could completely plug and play all these different parts and they'll all work together. That's what we're aiming towards. And what's going to get us though is PHPfig. So there's mixed opinions about PHPfig, I know, but it has enabled amazing things within the PHP ecosystem and pushed PHP forward into the modern world of programming. Is everyone familiar with PHPfig? Yeah, lots of nods, good. So yeah, there's these three areas. Auto-loading, which really is the base thing that we need to be able to have packages that easily work together. Coding style, it would be nice to standardise on that. If you've got a project that's made up of lots of different components, it's nice to go from one file to another that it's not all laid out all differently. So unfortunately, Drupal doesn't use these coding standards, so there is a bit of difference there and you do have to keep going and changing your settings in PHP storm, depending on what project you're working on. Obviously the big thing here is interfaces. So I'm talking about PHP middleware. So I'm in particular talking about PSR7. This is the HTTP message interface. So it's a standardised way of thinking about the HTTP request and the HTTP response. And what this, so I mean, yeah, so then, sorry, symphony HTTP framework. You see a lot of projects all standardising on that, so you might think why don't we just standardise on that, but the distinction is that that is an implementation, whereas PSR7 gives us an interface. So there's many different implementations that work better in different contexts. Two popular ones, Diatros has one which is now part of the Zend free framework kind of world, and Guzzle on the client side has the implementation. And the great thing that, and this is like some sort of pseudo code to kind of demonstrate that, is that when you've got a common interface, these two different packages can actually work together. So in this example here, this is a very simple proxy that's wrapping an XML web service and converting it to JSON. So you see the first line there, using Diatros to create a request object from the globals. So that's generating a Diatros request object and then creating a Guzzle client, which is a different package, which expects a request, and passing that in, maybe changing the URL or something. And then what I get back from there is a Guzzle response object. But because that matches the same interface, I can then pass that back to Diatros to emit that back to the browser. So everyone has a few blank faces. Does everyone think that's a good idea? Okay, so hopefully that sort of explains a bit. So when we think about our applications and think what is our application, basically this thing here, this is our app, and what we take in is a request and we give out a response. So the idea with PHP Middleware is that we don't want to get involved with changing the app to change the behaviour because we may look like this. Oh, that's a bit of a lie. But we can actually change behaviour or add functionality by wrapping the app or decorating it. So if we can intercept the request coming in and if we can also do the same thing on the other side as well, essentially we can get in the middle here and change the behaviour of the app. So here's an example of taking an existing app and wrapping calls around that, a calls configuration. So again, I'll hopefully show you some more examples if the setup works in a bit, live examples. But we're taking in a request at the top. We're doing some analysis on that to see what kind of calls response we need. And then in the middle here you can see that in one of these cases we're passing that request onto the app and then just getting the response and returning that. In another example below, we're passing the request to the app, getting the response back from the app, and then we're adding on our cause headers before we return that to the client. So you can see this if it operates there, then essentially we're adding functionality without actually having to get into the complexity of getting into the app and changing it. So StackPHP is a way of using middleware with the HTTP Foundation from Symphony. This is what really, I guess, first popularized the idea of middleware in the PHP community. Obviously so these work with HTTP Foundation so these will work with Drupal. Another popular framework is the Slim framework. This also has middleware, and this first block here is where the middleware is being added, and then the second block is the actual action and part of the app. So when you get there, what it's doing is it's getting the response and writing out hello into the response. But because of the middleware above, you can see that that's going to intercept and first write before, then it's going to process the next, which is the next middleware or the next thing in the stack, and then before you get the response back it writes after. So again this is another way of wrapping and what you see here is a slightly different signature and this brings me to the single pass versus double pass. So going back to mentioning about PHPfig again, PHPfig was about standardizing what was happening in the PHP world. So looking at the frameworks and the frameworks coming together and saying let's standardize the way that we're doing things. In this particular case, the first option here, the double pass approach, is actually what kind of became standard with all the early adopters of PSR7 objects. So in this one you can see that your middleware takes a request, takes a response and takes this next callable. So what your middleware will do is potentially do something with the request, then it can call the next to pass down the chain into the next middleware and then pass whatever comes back back so it has to return a response. And this is the format that is popular in JavaScript like with Express. This is where this came from and it's good, if I remember why it's good, I've got my notes. Because obviously dependency injection, so the thing inside you're passing the response in, so the thing inside doesn't need to know about what particular implementation of response you're using, it can just get that response object and add what it needs to into it before it returns it. But the single pass approach, this lambda approach, this just takes the request and takes the delegate to the next callable. And so in this approach you need another way of dealing with that like being able to generate the request and so the response. So your option is to either bake in creating a JSON response using a symphony JSON response object or use a factory and pass in a factory that will generate responses as a dependency so you remove that dependency. So you get the benefit of the double pass approach but you also benefit from the fact that this is much easier to reason about because one of the problems and I played around with double pass for quite a long time before I finally got one over by the arguments for single pass, one of the problems is that when you're getting the response passed in you're never really sure what state that response is going to be in so ideally it would be a blank response ready to put your result into but you can't actually guarantee anything about that response because you're the one who's generated it. So the single pass has kind of won out and that's what's going to be in PSR 15 so this is what you get when you search PSR 15 it's someone paying a Yamaha PSR 15 with their feet but this is the actual thing so this is a draft recommendation and it uses that single pass approach and so you have the process so the bottom one here is the middleware interface so this is what you implement where you will take in the request and you'll take in the delegate which will be the next thing in the stack and you will return from here always an instance of a response interface and the thing above is the delegate interface so that's what you're actually being passed in and that just has a process function so you know that the thing that you're being passed in you can call process on it to trigger the rest of the inside of your stack as I said to make this work with dependency injection you need HTTP factories so there's a draft recommendation for that as well and there's also something which I find in working with all of this that really is really useful is this invoker interface so on there read me they describe it as who doesn't need an overengineered call user funk so what this interface does is it and there's an implementation here as well is it explores on the kind of idea of like I need to call something so perhaps you know if you've has anyone worked with the rabbitmq thing in PHP because I find that really horrible to work with because you get these methods with long lists of arguments you have to pass in and you can't remember which one's which and like the arguments are true true true false true true and I can't remember if that's which one of those is doing what with named arguments you pass in your arguments by name so that's one of the things that the invoker interface gives us and the other thing is that sometimes the thing I'm calling has dependencies and it's a real pain for me to know how to instantiate all the dependencies for the thing that I'm trying to call so the invoker can be aware of my dependency injection container so I can just call my thing and if it needs dependencies the invoker can deal with instantiating it and I pass my arguments in by name so I know exactly what it's getting okay, does everyone get that any questions so far I haven't got my notes so I can't see which slides next but it's this one okay so this is an example kind of simplified from a real project that is really just doing some very basic applying some very basic business logic on top of a data store so there's not really a lot going on in this particular app but still splitting it into layers means that well A I could reuse components that are already available on packages so I had to implement about maybe 100 lines of code for the whole thing but also each of those individual layers can be testable and particularly when you get into the middle of here you can actually build that bit first so I can actually build the core of my app without having to think about any of those outer layers and so those outer layers are going to be things like how am I dealing with authentication how am I dealing with generating requests and this kind of thing so you can actually if you're into domain driven design you can actually build some actual objects that just have the logic of your domain and you don't have to think about any of these sort of environment that you're working in so I've got a bit of distracted there yeah so this is just I think showing that the each of these layers here implements this thing on the left here this process where they get called and you get the request and you get the next thing that's inside you so you can do what you need to do pass the request on to the delegate and then you get a response from the delegate and if you want you can again do some further munking around with it and then you return that response so this creates that sort of going down and coming back out again so there's a lot of different ways of doing this there's some whole frameworks based around this slim, express there's stack, relay relay is another popular one for very simple things just use a simple object like this and I basically when I can construct this object you pass in an array which is which defines the stack so I'll show you what that looks like in a minute you pass in the invoker interface so this is the thing that is like my replacement to callUserFong this is the thing that takes the things on my stack and knows how to invoke them and you take the response factory because there are as you see within here sometimes I need to create a response so the process function and you can see this implements the delegate interface and that's important because to the outside world my thing that's running my middleware is also a middleware so basically at the outer level you'll call process and it will check the first thing on the stack it will increment its counter to point to the next thing in the stack and then pass itself in as the delegate does that make sense it's kind of weird isn't it so this thing sort of yeah this thing has the pointer to the first thing in the stack it gets that reference points to the second thing in the stack and then passes itself in as the delegate so it can take itself down the chain and then when it gets to the bottom of the stack you return all the way back out again so that's that bit in the middle and then the last thing on this slide is showing this idea of using the invoker so you see I'm passing in using the square bracket callable syntax in PHP where I'm passing the middleware which is the current thing that I got off the top of the stack with the word process to say call the process function on there and then I'm naming my arguments saying request is the request that I got and the delegate is this okay hopefully that's not too weird I'll show you some more examples of using the invoker in a bit because it's quite nice because this doesn't need to be aware of any of the dependencies of the middleware the invoker can use the dependency injection container to do that so this is just showing that the middleware is an array of things that the invoker knows how to invoke so if you look here the middleware is used it's passed to the invoker with the process word so each of these things here must be instantiatable into an object that has the process method basically so yeah this is using the syntax of PHPDI which is the dependency injection container I'm using okay yeah so that gets us into the core of our app and what's happening in the core of our app we commonly think of dividing this up using MVC so the other thing I want to talk about today is that perhaps MVC isn't the right thing that we should be doing and this is the webby kind of version of MVC where we've got the front controller which is like our router that dispatches the request to the right controller and then you've got the view and you've got the model but also the view to the model and so thinking about like is this the right thing well quite often in PHP framework you'll see the view is a template whereas actually when we're thinking about our application the presentation layer we're not presenting to the world a template that's the body what we're actually presenting is a response so the response is actually a lot more than just the body of the response there might be other things in there as well so there's this alternative kind of view of things which is the action domain responder where, oh and the other thing is that also in the controller we tend to put all our actions in one controller and then you have to instantiate that whole controller just to call one action so we split out the controller into separate actions and also we combine the some of these things and we get action domain responder so all of your domain logic goes into the domain bit and the action knows basically how to call that and also how to respond to the incoming request and so yeah and then I wrap that in a resolver which is just the router which just takes an incoming path and decides which of these action domain responders to rip that to which of these actions I should say so I've been playing around with some ideas with this and there's a few links to like some experiments I've been doing on GitHub this is kind of how my implementation of the idea of action works in that it has an input it has a domain and it has a responder so when you define an action you define how to map the input basically encapsulates all the knowledge about how to take the request and generate the parameters we need for our domain so I've written down name mobs there again to remind me that we want to be thinking about extracting named arguments so when we call our domain we're calling with specific arguments not just passing in a request and I've also put down data transfer objects because when we're thinking about domain and entities we want to allow an entity to be invalid from the point of creation an entity should always stay a valid thing so to get around the fact that sometimes we have a form state coming in we use a data transfer object which is basically what it says it's an object that's used to transfer some data and at the point where that's validated then that can become an entity but we don't want to let invalid data slip into our domain because then we could end up with it persisting into the ORM and it's a lot of problems so the input will deal with generating, taking the request and turning it into some input parameters then we've got the domain which is just very basic simple PHP that describes your business logic and then what comes out of that is a payload which I'm still not entirely sure of the best way to do this at the moment I'm just using a simple object that kind of wraps an array and I think there's probably better ways to do this but that payload goes to a responder which that knows how to generate the response so that may be formatting it into JSON that may be taking your object that comes out and wrapping it with a twig template or something that is contained in there so we've got the separation of concerns but I think I think this is a bit more webby, a bit more API than MVC so this is the bit where it's all going to go wrong shall I try the demo what time is it up we've got 15 minutes you are screen sharing can you see that how do I get out of it how do you get out of presentation mode here we go now because it thinks I'm selecting text that's not valid here to be anymore let's exit that and let's go back to presentation actually this is on GitHub so I may not have committed the changes I made this morning but I'll just show you the code instead of trying to do a live demo this was all going to be amazing and you were going to see a few lines of code doing all of this amazing stuff but you just have to use your imagination instead I use this in this example I've used this is that actually legible so instead of using YAML here in PHPDI we're using actual PHP so I'm saying that my middleware is this array and all I've got in there at the moment is this action thing I've got my roots has anyone seen the fast root router anyone worked with that check that out because it's awesome but this is the syntax for that so it's pretty obvious what it's doing in the resolver basically this is saying respond to get method this is the path and then this string here is just something that the dependency injection container is aware of so if it resolves it resolves to something and pulls it out of the container and that thing is this action class here so I've created an instance of that action class there I've set the domain to be this get all lists class and I've also I've got this obviously it's got to be a to do list app that's what everyone demonstrates for some reason so I've got this to do repository interface which defines how to get and store to do lists and I've got an implementation of it here which just persists things to a file that could be switched out for a database or whatever and so so this is the this is the interface it's just list to do's returns an array save items takes a string of a list name and an array of items and get items takes a string the list name and returns some items okay so that's to be straightforward I can show you the implementation of that this is using fly system which someone talked about earlier so this gives me a file system interface and allows me to plug in different file systems depending on whether I want to use a local file system or S3 or something like that and like my list to do list here is just listing all the files and then out of that array of objects plucking out the file name property out of all of those so oh yeah I use this I use this functional PHP library which is brilliant saves so much boilerplate code dealing with arrays of things and stuff so then you get into the actual domain of the application and so this is where right in the middle of your ball of mud where you normally have quite complicated code I'll show you the get or list action first so the dependency injection container when it's resolved to this will have dealt with passing in the to do repository as a dependency and the invoke method which is the thing that makes this callable just calls the list to do creates a payload and returns it so I'll show you another example that takes in an argument there so this is getting an actual list where my invoke method takes a name and so this is where it gets interesting because I'm using named arguments this all links together so in my in my root for that which is here commented out can you still see it is that too hard to see you can see that in my root I've defined a placeholder there called name and my I talked about that input handler that takes a response that will convert that name into a name parameter for when it calls by action so yeah sorry I haven't been able to do a proper demo of that but feel free to look at this and have a look let me try yeah so this is the this is the action so in the you saw in the phpdi config where I created an action object and I called the method domain and set my actual domain class this is the this basically allows me to override and set the domain the input or the responder for a particular action so what I tend to do is have a default input handler that just takes all the get parameters the pass body whatever it can find and turn those into named arguments to pass to the invoker and I tend to use just the default responder that just takes whatever it's given and jason encode it and deliver it but you can do you can override those for specific roots so one specific root maybe you just want to format the output differently or maybe you want to wrap your application with a content negotiation middleware which will deal with content negotiation you could then use that in your responder to decide how to respond so this is it all put together action equals new action and passing in invoker because that's a dependency there setting the input to default input domain to register user and responder to default jason responder so yeah this is kind of an idea of what those stages might look like as I mentioned the input handler will just create an array of named arguments the domain method then your domain that's the bit where you're actually using those arguments to actually do something and you're returning a payload which then the responder knows how to convert that payload into an actual response and I'm just creating a jason object there but you probably use a factory just to make sure that you're fully abstracted so yeah so that's creating the action and this is what those bits might look like this is actually how the action actually works when it's called so in the core of the ADR pattern when a root has been resolved to a specific action these are the steps it goes through so it takes the invoker and it calls its input handler passing in the request so you can see that here it's calling input handler and the array of named arguments is just the request then it calls out your actual domain passing whatever the input handler created from the request to your domain and from that it gets the payload and then it calls the response handler passing in the payload and the request and then yes your this final stage here the response handler will generate an instance of a response so there was going to be a bit in the demo where I showed you the different steps of the like adding some different middleware in so if you look at the example code you'll see there's I wrap that domain, I wrap that domain with a jason payload middleware which takes the body of the request and jason decodes it passes that in as name parameters and then in the next step I wrap that with the HTTP authentication middleware which deals with authenticating but you can look at this repository and there's a whole load of middlewares that are just ready to to use and that's it um yeah onion to request to get through the but when you show the ADR pattern it looks like there's not an onion it's like there's any action that takes control and then you've done anything to do okay so if you can stop the traversing of any code so um so I'm presenting two things I guess there one is that is the idea of the middleware um decorating your app with new functionality without having to change what's in the middle um the ADR is actually a solution for then the ADR is a solution for what do you do when you get to the core of your app what's the simplest way that we can create our business logic um without any dependency on the framework or the ORM or anything that we're depending yeah yeah yeah yeah so in this example here I've got um I've got a cause a jason payload um a jason web token middleware and then in the middle I've got this router and and that's actually um invoking that's configured to invoke actions depending on the root so the ADR is the thing in the middle so yeah you're right this this is less of an onion and more of a pipeline um and actually for more complicated things um one of the projects I'm going to talk about tomorrow in the talk on elastic search this domain actually does become a processing pipeline so I've got examples of that tomorrow more questions? no that's either a good or a bad thing thanks everyone