 Cool. Well, thank you so much for coming out today. If you are looking for zero to API with Lumen, you're in the right place. If you're not, feel free to stick around. Maybe Lumen will be interesting to you. So today, I'm going to talk a little bit about creating an API with Lumen. And as I'm speaking, feel free to tweet at me with questions. I put my Twitter handle down there at the bottom. It's Ambassador Awesome. And I'll get back to you after the talk, or we'll have a little bit of time for Q&A after the talk is over with as well. So a little bit about me. My name is Amanda Folson. I do developer relations at Nexmo. We have a booth here. So stop by and say hi to us. That's basically a fancy title for a professional conference attendees. So I travel a lot. I give a lot of talks just like this one. And I've been dabbling in open source and working with APIs for a number of years now. And I kind of stumbled onto the API scene completely on accident. I discovered this wonderful world of APIs because I needed to get data from one thing to another and scraping HTML really, really sucked at the time. So that's kind of my story and how I got into that. But enough about me. Let's get into Lumen here for a sec. So if you're not familiar, Lumen was released by the wonderful people who do Laravel. In 2015, it was a micro framework. And micro framework is just a nice little way of saying it's a much smaller version of something else, a larger framework, or its own self-contained framework. So it's just a slimmed-down version of Laravel for all intents and purposes, it really is. And the nice thing about Lumen being from the Laravel family is that there's an easy migration path between the two. So if you are using Laravel and realize, like, maybe I don't need all these bells and whistles, then you can look at Lumen as an option. And it's not exactly drag and drop into either one of those. There is a little bit of legwork you have to do, but I'll discuss some of the differences here in this talk. And it's relatively straightforward to go from one to the other. Views get a little bit hairy, but we'll talk about that in a second. But basically, if you're using Lumen and decide, I really need full-bone Laravel instead, it's pretty trivial to switch, and vice versa as well. That's not working. So if Lumen is really just a trimmed-down version of Laravel, why would you want to use it? If you're familiar with Laravel, you're familiar with it pretty much just allowing you to spin things up pretty quickly. Lumen is very, very similar in that regard. You can split up an API very, very quickly. I will add a disclaimer, though, that Lumen is really not intended to be used as a replacement for Laravel. And if you're looking to move from Laravel to Lumen or something like it just to speed up your Laravel site, it's maybe not the best thing for you. But switching to Lumen or starting a new project with Lumen is definitely the right approach in some situations. So let's talk about that a little bit. So some of the reasons you might want to look at something like this. You might be looking to create a microservice or looking to migrate a monolithic application into a series of microservices. And what exactly is a microservice? It's mostly just people define this a few different ways. Mostly just a way, a thing responsible for one specific function. So think of a microservice as a module within a larger system that's responsible for a single thing. So for example, you might have a service that sends emails and another thing that's tasked with rendering graphs. I run a blacklist that actually has a few services like this. A lot of them are Lumen-backed. And then I actually do have a Laravel front end that hooks into the Lumen backend. These are all services that talk to an API in the center, which is a Lumen thing. And basically the API is just tasked with presenting data to various aspects of this. So there's a little service to build DNS zones for people to consume and put into their own applications. There's a Honeypot or basically just a fake server that I have that I want people to break into so that I can see what they're doing and work around it and prevent it from happening in the future. And it's actually an entire subsystem within the system, but that's diving a little too far down the rabbit hole. But I would love to talk to you about Honeypots later on, if that's your thing. Another thing exists simply to restart services thing and restart it down here. There's actually a memory leak and a daemon that I run and nobody has really prioritized fixing it, including me. So for now, Thing Restarter is just tasked with restarting that thing at a specific interval or as it notices things like memory consumption starting to creep up. There's also a scheduler that handles queues and messages and that's also another subsystem. But the point is that there's always one entry point into these things via this API here in the middle. And Lumen has actually been a really great thing for running these things because it's relatively lightweight. So put simply, what the heck is an API? It's just a way for two pieces of software to talk to each other over a shared interface. Most people are probably familiar with APIs, but just in case you're not, there are many different types of them. Anybody familiar with like SOAP or XML or PC? Yeah, I've got a few hands. I saw a few grimaces, too. So Win32, C++ Standard Library, those are all examples of APIs. And these APIs really just define a set of rules for communication within systems and things like what the interface looks like, defining different endpoints. And it also defines things like the format of requests and responses, whether you're doing XML or JSON. Basically, the API creates a definition for all that and creates a blueprint. But today, we're going to talk about REST. Anybody using REST APIs? Yeah, lots of people. More hands this time, that's good. So in the context of Lumen, if you use Laravel, you're probably familiar with this. There's a lot of other frameworks that have a RESTful architecture as well. Maybe without even realizing it, you're kind of doing these things. But don't worry, we're going to dive a little bit into what's under the hood if you're not familiar with these things, just to kind of level set everybody. REST really just stands for Representational State Transfer. And that's a lot of words, but it's a fancy way of saying that we're working with representations of data rather than the actual data itself. So for example, if you have an image and you want to grab an image from a server, loading that image up doesn't actually take that image off that server. You get a representation of that image instead. So it's a great way to not mangle all of your data. And so you're working with representations instead of the actual thing. And to work with these representations and these transfers of state, we typically use HTTP-based methods. That's not an absolute. REST doesn't necessarily mandate that you do that. But a lot of what you're going to come in contact with is going to be HTTP-based. So we're going to use methods such as git, post, delete, and so on. You're probably familiar with these things. And since it's our API, we can define exactly how we want to work with these representations, whether we want to do XML or JSON. I'm actually seeing a lot of YAML lately. There's a lot of people that are working with YAML and sending and receiving YAML to different things, or even markdown. I've seen a few markdown things, people getting content. They pull a markdown, just a blob of markdown, and incorporate that into their templates and things. So there's a whole bunch of ways you can work with this. And actually, the weirdest thing I think I've ever seen is somebody returned generated C++ in an API. And that was fun, but a little scary to work with. So like I mentioned, they're often HTTP-based. That's not an absolute. They don't always need to be. Again, most of the ones you're going to encounter are going to be. But an important thing to note, if you're coming from XML, RPC sorts of things, or SOAP APIs, REST APIs are stateless, meaning that each request needs to be authenticated, and each request needs to be fully formed. So the server is not responsible for keeping track of the state of things. That is the client's job. That is the user's job. The server is not making sure, oh, are you logged in first? No, each request is getting authenticated. And that rests solely on the client. And then there's also this concept of Hadeos. And people pronounce that differently. Really debated. Pronunciation isn't super important here. But it stands for hypermedia as the engine of application state, which is akin to using links to allow an API client to browse the API similar to how you would in a website. It's really great for self-discovering APIs, allowing people to kind of choose their own adventure as to where they want to go, whether they want to delete something, whether they want to add another thing, whether they've created a thing and want to view this newly created thing. Hadeos is really good for stuff like that. So I mentioned using HTTP methods before. You use these every day just as you're browsing the web, whether or not you realize it. And they're usually happening behind the scenes. So if you're not familiar, here's just a small list of them. And you'll recognize some of these things from either Laravel's routing, or if you've used Lumen before, you've seen this before. There are a bunch of other frameworks that also do something similar. The routing kind of matches the method that you would expect. This talk, obviously not about HTTP methods, but you'll find that understanding them will help you a lot when you're working to create a REST API. So get, obviously, if you're getting data from a resource, Post allows you to, you're sending a message body, you want the server to do something with it for processing. You'll see this a lot when you're creating records or working with forms and things like that. Put, obviously, allows you to put things up to update a resource. You should be aware that it will overwrite the existing content that's there. So you might want to use Patch, which will only update the properties that you give to it, provided in the call. And delete, pretty self-explanatory. It deletes things. I don't know why that happened, but pretend that that says Patch instead of PatchCH. Options is one that many people are not familiar with and basically it's really useful for just telling clients like, hey, these are the things that are actually available to you. These are the things that you can take. So for example, a lot of people disable put in favor of always using Patch because they don't want people to clobber their data on accident, which is very easy to do. So it's just a way of saying like, hey, you can patch this, but you can't actually put anything here or this is an entire collection of things. I don't want you to be able to delete it. So you can't actually use the delete method. So if you're setting out to create an API, adding options or considering adding the options header is great. So if you're coming from Laravel, which I have spoken to a few people here, they are coming from Laravel and they want to know more about Lumen. Lumen still has many of the bells and whistles that you're used to inside of the Laravel framework. So first, you'll be happy to know that you can still use Homestead, if that's your thing with Lumen to help you get up and running very, very quickly. It's very trivial to get started with that. It's just a vagrant environment or VM that you can run all of your Laravel sites and it's pre-configured with a bunch of things for you. So if you're not using it, definitely check it out. And if you're already using Laravel or really let's be real PHP in general, you're very familiar with this process. This process should look pretty familiar. There's nothing new here. So there are several ways you can install Lumen. You can use the Lumen installer, which I've shown here, or you can use Composer Create Project and that works just as well. So both of these installation methods work like they would in Laravel or with other projects as well. So you really shouldn't have too many issues getting up and running quickly. And if you're familiar with .mv, that is available. In previous versions, you actually had to specifically enable this, but now it's enabled by default for you. You're welcome to comment it out or use something else, figure out how you wanna manage your environment variables. But this is here. It's worth noting that it is available to you and you don't have to use it. So note that this app key here is not set for you. So you'll have to generate that manually. It's just a 32 character string of random stuff. Not a huge deal for you to generate that yourself. And that's because if you're familiar with Laravel, there's this Artisan command that allows you to generate keys and things and the like that's not available to you in Lumen. And Lumen actually has a very trimmed down version of Artisan because it is a trimmed down version of Laravel as you'd expect. But again, fairly trivial to generate a 32 character string of random stuff. So facades and eloquent are also both still available to you. Your project may not need them and there is some overhead with using these things, but if you're coming from Laravel or if you're trying to port a Laravel thing into a Lumen thing, it's worth noting these are commented out by default, but they are available to you. So for the sake of simplicity, my example code uses these, but since a lot of people here are probably familiar with seeing code like that, but it's good to know that you don't have to do it this way. And Lumen is very, very flexible in that regard. So if you want either of these, you enable these in your app config. They're very obviously commented out. And you can find the app config in your bootstrap folder. So out of the box, routing might look a little strange, but it is restful like Laravel's, like many other frameworks and is still defined in the routes file. If you're coming from Laravel, everything is kind of in your routes file. So these are both just default routes. This is a default Laravel one, and this is actually a default Lumen one, and you could easily swap these around and have Laravel returning a version and Lumen return a view. The views, again, they get a little crazy, so we'll talk about that in a second. But routes can still be bound to controllers. If that's something that you're doing, you can still do closures. This app variable just gets loaded via bootstrap.php. Super, super simple to inject things into that if you need to. So again, if you've been using Laravel, you'll also be happy to know that Artisan is still available to you to help make life a little bit easier, but again, not a full-fledged version. So if you are using Laravel and you go to look at Artisan, you're gonna be like, why are all these things missing? And the reality is, it's just to keep Lumen as tiny as you possibly can. There are a few key differences. Let's talk about those. So first and foremost, there is no serve command. Not a deal breaker, but in talking to people who are switching to Lumen, that's one of the things that trips them up the most. There is no PHP Artisan serve. You can use PHP's built-in web server, and actually the docs do recommend that you do that, or Homestead, or a web server if you're choosing. When I'm just messing around locally, I just use PHP's built-in web server, but I know plenty of people who prefer to use Homestead or people who are doing all sorts of lamp things in their testing environment. I mentioned that there's no key generate command, so you are responsible for generating your own 32-character string of random stuff. Super easy. The tinker command is also absent. If you've used Laravel, tinker is very useful for going in and doing what it says on the tin, tinkering with the data that you're actually sending into Laravel, but there is no such thing in Lumen. However, you can use something like Postman, which used to be a Chrome plugin, is now an actual standalone application to inspect things and work with your data and schlep things back and forth. There is no down command, so if you want to make changes, and Laravel makes it really easy for you to take a site down, do maintenance, and then bring it back up for Lumen, no such luck, but it is relatively easy to send people a 503 and say like, hey, this is down for now, but if you come back later, something should be here for you. Hopefully something's there for you. There's no vendor publish either. Someone has written a plugin to add this functionality back into Lumen, and if you're using packages that are written for Laravel, some of them are interchangeable, some of them are very Laravel-specific, some of them are very Lumen-specific, so if you do need something that's very Laravel-specific that has configurations that get published, you can add that command back in. There's a package for that. There are a few other things missing. Again, that's to be expected, because Lumen is tiny. You still have access to migrations, and this is really exciting. If I had to pick one thing to keep in Artisan, it would be migrations, just creating these, it's painless, so you can install, refresh, reset, roll back, similar to how you do that in Laravel or other frameworks, and we still have access to DBC'd, so we can actually seed our database with random stuff that we've generated. Once you write your seeders, that's where DBC'd comes into play, and these seeds can also use the Faker Library if you wish. You can still create model factories to generate this dummy data if you're familiar with that process as well. So creating migrations via command line, you'll end up with something similar to this, so here migrations look pretty similar to what you'd expect in Laravel and other frameworks. Lumen's documentation actually even points you to Laravel's migration documentation, so these are virtually drag and drop. If you have existing migrations, you'll likely just, yeah, be able to drag and drop them into your Lumen project and be able to run your seeders and things, so that is relatively straightforward if you're coming from Lumen or if you're coming from Laravel to Lumen. Lumen's make is also missing a number of things that make getting started in Laravel easier, so only have make migration and make seeder to make migrations and seed fake data into those. There's no way to generate a model, so you have to do that yourself. You're missing the ability to make controllers via command line. The authentication scaffolding is not present. There is authentication middleware, I will say that, but you're missing the login forms and the automatic JWT generation. Despite these things not being in the framework though, there are great examples in the documentation to help you get started, so you don't necessarily need to worry about these, but they are jarring if you're coming from Laravel into Lumen. So, you may have noticed a theme in the examples that I've shown you so far. When I originally gave this talk at Laricon, Pokemon Go had just come out and that was like the new exciting thing, but I really like these little characters, so I chose to keep them. And I've created a very, very basic Pokedex API just to help me keep track of things that I've caught and just keep tabs on those things. We briefly walked through creating a project here and it happens much the same way as you'd create any other project, but let's dive into something a bit more interesting than boilerplate here. So, as we're sitting down to talk about our API, let's figure out what resources we might actually need. So, a resource really is just a gateway into part of your application. So, you have things like users, you'll have things like places and messages and so on. So, CRUD actions, CRUD style actions can be performed on all of these and we can use them to get a single resource or a collection of resources here. So, we know that we want to display a list of Pokemon and we know that at a minimum we're going to need a Pokemon resource here. I'll share the slides later too. So, we should keep in mind that we may want to use this resource to return a collection. So, instead of just returning one thing here, which I've done, we might actually want to return multiple things as I've done here. So, we should also keep in mind that there are times we might want to modify all or none of these things. So, I mentioned working with APIs that allowed you to delete entire collections. There are cases like this where you may not want to let people do that. So, it's just something to be mindful as you're designing your resources. Now, as a side note, I have put two different ID numbers in here. If you've never played Pokemon, each Pokemon has its own number that corresponds to an entry and basically a private journal. But I've also kept my own internal IDs just to make things play nicely with Eloquent. I'm using the Eloquent ORM. In the real world, I would hide that ID and just rely on people using that number. But just for the sake of simplicity, I wanted to point that out, that there are, in fact, two IDs and you're welcome to use either one of them with this API. So, now that we kind of know how we want this resource to look, we can figure out our routes. And again, the routing is a little different from what you might be used to in Laravel or other frameworks, but it's pretty straightforward once you understand it. So, as we start to think about routing for this, there are a few things to keep in mind here. So, remember that we're using HTTP methods instead of named procedures. So, we're using a get method instead of something like getPokemon for this example. I tend to suggest that people use plural nouns when they're designing their endpoints just because you never know when you're going to be working with a single thing or an entire collection of things and it just keeps things simple in people's minds. It lessens that cognitive load a little bit. You typically have more than one record for these endpoints that you want to access anyway. That's not an absolute, but it is pretty standard. So, we know that we'll want to get a list of Pokemon or a collection of them, so here's what that get looks like. And the index here will actually just show you a list of Pokemon. And then if we wanted to look at a specific one, we can get a specific Pokemon via its ID. And we also know that we'll want to add some new ones. So, we've got post set up here. And again, all of this is just happening in the store method in our Pokemon controller. We might want to put things if we want to edit things and that's just talking to our update method in our Pokemon controller. And we might actually want to delete things. So, we'll have post, put and delete. And you can see here that we're making use of a named route as well. So, we have this Pokemon.show. And also just tying these routes to controller actions. So, controller, our index method and our controller, our store method, update and so on. So, let's talk about views for a second. I mentioned that views get a little hairy if you're coming from any really MVC framework to Lumen or something similar to it. We don't really have views. So, views in Lumen, views like standard HTML views were previously included in Lumen, but as a 5.2 are not included. So, you may in fact run across projects. 5.2 was not that long ago where you will see HTML views and you'll be like, this looks very Laravel-ish and you're right about that, which is why they are now gone. You can add them back in if you need them. But if you're really relying on a lot of HTML or very heavy on the front end things, maybe Lumen's actually not the thing that you want. So, it's just something to keep in mind. So, what do we do about views in Lumen? Well, you've already seen it. This is our view. This is our JSON. It's out there for you, the user to consume and really we just want to stuff the logic that translates things from the database into JSON and then we can decide what we wanna do with this JSON later or our end user can decide what they wanna do with that. And this is all right. You can just spit out raw JSON. Just by default, Lumen will allow you to do that and just construct JSON responses. But we could be providing a more consistent interface for ourselves and also our end users. So, how would we go about doing something like that? We can import this library called Fractal. Anybody use Fractal before? A few, a few. So, it's a library made by Phil Sturgeon. It's put out there by the PHP League. And Fractal really just helps us provide a consistent interface for presenting this output. So, making our JSON just look a little bit prettier. You can kinda see how we're building this. So, we will always return things in this particular order and that's not necessary for a REST API in a lot of cases but it is nice to just provide that. You always, it's very easy to see at a glance what might be missing from looking at that. And this code here is just called a transformer and it does what it's called. It's transforming data from our database or into something that we can easily consume. So, this is how we're setting up our JSON right here. And actually, you can kind of see evidence of that. So, you see ID, name, number, description and then our timestamps, ID, name, number, description and our timestamps right there and they're in the same exact order. So, let's move on to our controller. A little bit more meaty. So, here's an index method and also our store method and our index method is really just returning a list or a collection of all the Pokemon that we have available to us. In the real world, I would paginate this just so we're not hammering our database like that. For the sake of this example, it's a pokedex. You're only gonna get, the purists will tell you you'll only ever get 151 entries. So, taking a look at the store request, here we have some validation code here. We're validating that this is correct, that we have everything, that name is less than 255 characters. It is required, numbers required, descriptions required. And if we're not getting any of that then we tell people like, hey, you need to fill out this attribute and that's just within the body of the response. We then create a new Pokemon record down here. So, very, very straightforward to just stuff all of those fields into our database. And when we create a new Pokemon record, we're just returning 201 created and then setting a location header to where that thing now lives based on the ID. And we're doing all of this but you'll note that there's actually not a lot of code here. Like, really the validation stuff takes up way more space than the actual part that we're interested in. So, this one is really underwhelming in terms of the code. It's a one-liner. So, if we want to see a specific Pokemon, that's how we do it. So, we're using finder fail to find an ID. So, if we find it, great. If we don't, then we're just gonna return an error and that happens under the hood. We don't even need to worry about that. So, this will throw a 404 not found if it can't find that. And again, Lumen just takes care of all that stuff for you so you don't even have to worry about specifying it. Like, we did here with 201. If you wanna take control over your status codes just manually, you're welcome to do that and it's nice to know that the option's available to you. But then, coming over here, 404 is gonna happen regardless. So, what if we wanted to update an existing Pokemon? Again, you'll see that the validation code takes up a majority of this. And this is just a try-catch. So, we'll try and find it. If we can't find it, then we're just returning an error message and again, we're managing these status codes manually here so we're returning a 404 because we haven't found it. You can't update a thing that doesn't exist, right? So, if all is well, we'll save it. We'll run it through the transformer. Again, at the bottom, you'll see the Pokemon transformer and then we're good to go. So, this one is actually extremely underwhelming so it's not even worth showing you a screenshot of it in action. But here, we're deleting something. So, again, using find or fail. If we're not finding it, then we'll do a 404. And if we do find it, then we just delete it and then we'll return a 204. And I do want to call attention to that response. So, we're returning 204, which means no content and we're not returning any message body to the client. And you can optionally display a message here to the client if you want, ideally not using the 204 status code. Just to say like, hey, this thing was deleted, but there's no real standard for this and there are plenty of opinions on it. And it's also worth noting, again, that you might not want your users to be able to delete an entire collection of things. So, be very, very careful with this. If you're letting people delete things, make sure that you're okay with them deleting an entire collection or if you don't want them to do that and make sure that that option is not available to them. Make sure that they can only delete one thing at a time. And of course, even if you let people delete one thing at a time, someone will inevitably script it so that they can delete everything at the same time because that's what people do. And our model is not very complicated either and really this protected table right here is just because Eloquent tries to be clever and will pluralize things for you but the plural of Pokemon is actually Pokemon. And the first time I gave this talk, somebody actually opened a pull request to fix that within Laravel and Lumen. So, that might be fixed for you but I think someone also opened a pull request to take it out because they thought it was ridiculous. Yeah, it's very, very dramatic. But anyway, not important. We've also filled this array here with things that are fillable and if you're not familiar with that, it's just things that we wanna protect from mass assignment, right? So these are the things that we want users to be able to manipulate. So really just the name, the number and the description. So this model, not very complicated at all. Now that we've created a basic API, we're obviously probably going to want some sort of authentication layer, right? That's generally good. And realistically, authentication could be a talk all on its own but just to briefly cover this, it's relatively easy to implement your authentication flavor of choice whether it's JWT or Stormpath or anything like that. So there is an auth service provider that kind of allows you a lot of flexibility into what you wanna do there. Since Lumen is designed with APIs in mind, the auth service provider does not keep track of sessions or state. You'll need to authenticate users every single time they make a request and that's one of the largest things that people get confused about when they're switching from Laravel to Lumen. The auth service provider behaves a little bit differently. So there are several options when it comes to adding authentication that I mentioned. So here I'm doing something with JWT. You could easily do OAuth2 or Stormpath or any of those, whatever your flavor is. So here I've just created a JSON web token method of authenticating users. I've put creating and updating and deleting behind authentication whereas anybody can come by and view a list of Pokemon or view a specific Pokemon's record in the database. So I'll allow any unauthenticated users to view those. And again, authentication, very, very widely debated in the tech community. I probably don't have to tell you that. I'm sure everybody in this room has differing opinions on authentication. So you start to build out this authentication layer. There are a few things that you should keep in mind. Even though this is an API, common thing that I hear about is that people are not worried about SQL injection and you absolutely need to be concerned with SQL injection. People are like, oh, well, we're not working with forms or web forms. Like, I don't need to be worried about that and you absolutely do. So please, if you're making an API, that's something to consider. We should give considerable care to how we're storing or user information, GDPRs coming up. So that's something that now needs to be considered in your APIs. And we should be making sure that we're using SSL to secure our applications as well, to secure requests and responses. Also, 2018, who's not using SSL right now? Like, 2018, come on. So we have made a very, very simple API and that's all good and well. And you see, it really did not take us a lot of code to actually get a thing working. There's not a whole lot of code here. This was actually under an hour of work to put all this together. So if you're coming from Laravel, you'll be happy to know that the things that you love about testing in Laravel are also available to you in Lumen. And if you don't want to use any of Laravel slash Lumen's helpers, then you don't have to, you're welcome to manage all of that stuff manually. I actually wrote these tests before writing the code just to run the app, but you can write them afterwards too. I'm really not here to evangelize testing methodologies to you. Everybody's got their own flavor. So this is just a snippet from a very, very simple test. Here we're just testing that when we post to our Pokemon endpoint that our record gets stored and we can see the data when we actually call that. And additionally, we're just asserting that the created app exists in the JSON that we get back as well, here at the bottom. So realistically, I could talk about this stuff all day, but unfortunately, there isn't enough time, and I'm also very, very sick right now, so please bear with me. And as you're building out your API, there's some other things that you really probably want to look into that I wasn't able to go over in this talk. And the list is not exhaustive, but I will put it online later today. And these are some other things to consider. If you're familiar with Laravel, again, easy to get started with, to get your API up and running. But if you're not, there's some, even still some great information in some of these resources. So if you'd like to know more, I encourage you to check a few of these out and I'll tweet them out again later today, so don't worry about copying this list. In particular, I want to call attention to the Lumen documentation, which is great. The Laravel documentation also great. Paul Redmond also put out a book relatively recently that walks you through creating an API with Lumen using TDD. So that's actually a great resource to learn a bit more about TDD if that's something you're interested in, but also walking you through creating a Lumen API. Phil Sturgeon wrote a book, Build APIs You Won't Hate, that's a little out of date using Laravel 4 right now, but still a great resource for a lot of the restful architecture and restful theory. He goes into a little bit of service-oriented architecture and how you can get components to talk to each other. Mike Stowe wrote a book called Undisturbed Rest, and it's basically a book where he's taken the rest spec and put it into terms that regular people can understand. If you've ever tried to read the rest spec, it's very, very long and very, very boring, and Mike makes it very, very short and very, very fun. So that's definitely a great resource to check out, even if you are already familiar with REST APIs. There's no code samples in it, which I think is actually part of the magic of it all. And then you can also find me. I'll be around. I'm honestly probably gonna go lay down a little bit after this, but we'll see. I'll be around. And you're always welcome to tweet at me or send me an email as well.