The Laravel Podcast

You may not know it, but the service container — also known as the container, the IOC container, the DI container, or just "the application" — is that the core of every Laravel application. It's the glue that holds it all together! In this episode, author of Laravel Core Adventures Christoph Rumpel helps us dig deeply into what the container is and why it's good for you to know about it.

 
-----
Editing sponsored by Tighten; transcript sponsored by Larajobs.

Creators & Guests

Host
Matt Stauffer
CEO Tighten, where we write Laravel and more w/some of the best devs alive. "Worst twerker ever, best Dad ever" –My daughter

What is The Laravel Podcast?

The Laravel Podcast brings you Laravel and PHP development news and discussion.

Matt Stauffer:
Welcome back to the Laravel Podcast season four. Today we're talking to Samantha Geitz about everything. This is the grab bag of all the different topics, and she's going to handle it because she's a boss. Stay tuned.
All right. Welcome back to the Laravel Podcast season four, where every single episode is about a different topic. Today I have a returning guest, which I don't think this is the first returning guest. No, it's not, but this guest is from Laravel Podcast season three, and we're going to talk about all sorts of good stuff, and this is another one of those where I didn't say, "Hey, here's just a single topic." There's actually a whole bunch of topics we're going to talk about.
Before we get to all the topics we're talking about, let's talk about the person. Ms. Samantha Geitz, there's no Esquire. What's the female version of Esquire? Anyway. The ineffable Samantha Geitz. Samantha, can you say hi to the people and tell them when you meet someone in the grocery store, or because it's COVID, whatever meeting people in the age of COVID actually looks like, what do you do?

Samantha Geitz:
I think I said this the last time I was on the podcast too, but I generally like to tell people I'm a software engineer because it sounds very impressive to people who don't really know much about programming and then it makes actual engineers super, super angry, so it's kind of a win-win for me, but currently I'm doing consultant web development work. I have a client and I do kind of a Laravel view stack.

Matt Stauffer:
All right. So, today we're not actually talking about the life history of Samantha Geitz like last time, but if you have not listened, go check out the season three episode. I'll link it in the show notes. We're talking about cache, session, middleware and request. Everybody else got this well organized topic, where it's like, "Oh, I'm just going to talk about the container today, or about databases." I was like, "You know what, if I'm going to throw this one, which is kind of like the grab bag of all the ones that didn't make sense as their own one, I'm going to throw it to Samantha. She's going to kill it."
We have four individual things. They are somewhat related, especially when you talk about middlewares and requests, but cache and session are really just their own beasts. So, I know that you have at least thought ahead of time a little bit, so I'm going to ask you to do the five year old test on all four of them. I do think that maybe requests should come before middleware, and if they're one, request and middle, that's fine. Whatever makes sense to you.
So, let's start with the easy one, easy quote unquote. If you were to describe caching in a web application... Oh, my God. There's a fly in my face. If you were to describe caching in a web application to a five year old, how would you do it?

Samantha Geitz:
So, can I start with requests? I think that's actually going to be... Okay, so requests are when you are asking your app basically to do something. So, you might be saying, "Hey app, give me a webpage," or "Hey app..." If you're a five year old, "I want to submit this form on Roblox to get Roblox..." It's like a thing.

Matt Stauffer:
Roblox? Yeah, I think so.

Samantha Geitz:
The things that my roommate's kid talk about, but basically a request is when you are going to an app and saying, "Hey, do something." You could also be theoretically doing in that in a console, but we'll stick to HTTP with what I got going on today. So, caching then... So, request has to go all the way into your app and actually do some stuff under the hood, and caching is kind of a layer in front of that where the app says, "Hey, I kind of know what I'm giving you back, so I'm just going to kind of throw it your way and not have to go do all this stuff under the hood," which is really nice if you have something like say, on your website, you have a footer at the bottom where you're loading blog posts from an external site or something.
So, it doesn't have to go hit that every single time a page is loaded. It can just kind of say, "Yup! These aren't changing enough that we have to do this every single time. I'll just put them right back up without having to go make another request, or talk to a database or anything." It tends to be just a lot faster and a lot easier on your server and on your users.

Matt Stauffer:
Okay. So, we got requests and caching out of the way, so request... Yeah, I know. Right. So, request was when you're asking your application to do something. Right now, we're going to stick primarily to the HTTP layer. You're just saying, "Hey, do this thing," and do might be send something, or might be get something, but you're kind of interacting with it mainly through URLs, right? Everything is really through HTTP requests through URLs.

Samantha Geitz:
Mainly through URLs, yeah, and also you might be saying, "Give me a file back," or "I'm trying to do something I shouldn't be doing," and then the server might just return an error code, might return a download, might send you to a different place, but at its most basic, a lot of times it's just, "Give me this webpage," and then it goes and loads a view or, "Submit this form. Here's the data," and the request would just basically have the information about what you were trying to submit. Also, it has stuff like, "Who are you? Where are you doing this from? What kind of... Is this like you are trying to get data or just send some data?" So, that's all kind of contained in that object.

Matt Stauffer:
That's great, and then the cache. So, the cache example you gave really tied into requests because one of the most common things we're going to do with cache is to cache a piece of the response. You mentioned the footer, or something like that. Let's imagine cache... And this is my fault because I grouped them together. If we were talking about cache a little bit outside of the context of a web request, and more just talking about caches in programming in general, do you have a simple explanation for what that is, for a five year old? What's a cache just in general, not even in terms of HTTP requests?

Samantha Geitz:
So in general, a cache is basically... I don't know if a five year old would understand key value stores. I'd imagine most also listening to the episode would... So, they're not like a database, which is like a relational thing. It's just like a NoSQL key value thing depending on what kind of cache backend you're using. It might just be stored in files on your applications, so you don't have to go all the way to the database. It might be in the database itself. It might be on something like Redis or Memcached, which will kind of live in its own process, but a lot of times, like with Memcached for example, just kind of have a serialized string of whatever data.
Like a database, you can kind of be updating that data, but it's not quite as memory-intensive or slow as a usual database with hundreds of thousands of records, and then most of the time too with caches, you're going to have that be an application-wide thing compared to sessions, which I imagine we're talking about right after this, which will be user-specific things that you're storing for the application versus every user for the most part, unless there's some little bit of business logic, will be seeing those same footer posts.

Matt Stauffer:
I love that. I normally am not the one coming up with the five year olds, but there's four of these for you, and actually what you just said popped into my mind something that Jonathan Rennick had said about his kids about... I forget exactly what his example, but it was about like, "Hey, five year old. Do you know how you want to do this?" So I'm thinking about my four year old, and when I watch her use her iPad, especially this PBS Games app, the loading time that they have to deal with, they're so aware of loading time, and their fingers are like hovering ready for whatever it's going to show up.
So, they know about loading time. I can imagine something like, "Do you remember how every time you're using the PBS Kids Games app, and you're waiting for all your favorite games to load? Wouldn't it be nice if the second time you used it, it didn't have to load them again, it just had them there because it loaded them last time. That's sort of like a cache, right? It loads it the first time and then the second time it's just able to pull out really, really quick. Doesn't have to go re-get it every time," and so you described all the mechanisms that we might use to do that, so that's good too.

Samantha Geitz:
Because a lot of times with websites, if you're not doing a separate deploy for example, your JavaScript code might not have changed under the hood, so why would you have to re-serve that to the user every single time when you can basically just say like, "Yep. Here's the code. You already loaded it." So, a lot of times you'll hear about cache busting. You'll have app that JS, and then a whole bunch of letters and numbers appended to it, so if that hasn't changed those letters and numbers, you know that it's the same JavaScript file, and then if they have, the browser knows like, "Okay, so the one I have cached is old. I need to dump that and then go get the new one." It's pretty important for the performance of an application, or any sort of scale to kind of understand how caching works and the best ways to be implementing it because it's definitely a rabbit hole you can get down.

Matt Stauffer:
It's multiple rabbit holes too because you just pointed out that there's server-side cache and browser-side cache, and I was like, "I didn't even think that when I named this episode," so I gave you more than four things. I'm sorry. I feel a little bad right now.

Samantha Geitz:
No, it's all good. I saw the spreadsheet-

Matt Stauffer:
It's because I trust you.

Samantha Geitz:
There was a spreadsheet of all the topics and Matt was like, "What do you want to talk about?" I'm like, "Oh, I don't know. The one no one else wants to talk about. Just let me know when you need me." He was like, "All right. We'll do everything." All right, cool. I've been doing this for long enough. I'm sure I can talk about.

Matt Stauffer:
Yeah, you could figure it out.

Samantha Geitz:
If I can't, I probably shouldn't be calling myself a software engineer. I should go back to being a webmaster.

Matt Stauffer:
Okay, so that's the test. So John Bonaccorsi said if he did a good job and people laughed at him that he would get to keep his job, so for you the test is if you do a good job in this episode then you get to keep calling yourself an engineer. I like that.

Samantha Geitz:
I already quit Tighten, so.

Matt Stauffer:
That's true. I don't actually have any impact on what you get to... But I'm just saying it's your contract with the people.

Samantha Geitz:
With the people?

Matt Stauffer:
With the people.

Samantha Geitz:
All right people of the internet, I'll try not to let you down.

Matt Stauffer:
All right. So, we have done requests. We have done cache multiple times, thank you for your patience there. Tell me about session.

Samantha Geitz:
So, let's say you have, your browser and you're trying to talk to your application via the website, or whatever. Inherently, when you make a request, it's just data in, data out. That's what's called stateless. So if you say log into a website, you have to go through this whole mechanism and then you want to go to a page. So you're on Facebook. You want to see your profile, You want to go to a friend's profile, and Facebook makes you be logged in. So session is a way that basically the application can keep track of groups of requests. So it'll be a user-specific thing, has a session ID, and kind of like caching, you can store it in a database, as a cookie, there's a bunch of different ways.
Basically, a session is tied specifically to you. That's how it knows that you're authenticated. You can also be putting data into a session. You'll also sometimes use sessions for things like, "Okay. This form was submitted and I got redirected to this other page," but I want to show a little success pop-up saying, "Cool! Your form was submitted. Good job." So you a lot of times would store something like that in the session because you wouldn't really want to store that in a database. You're using a database driver, I guess, but that's not something you would go fetch. It's just something tied to the user temporarily. Yeah, basically, it's just a way for applications to keep track of who a user is during a set of requests if they're logged in.

Matt Stauffer:
I love it. That's fantastic. So, transitioning, I know that one of the most common ways that you would use sessions and modern applications is through a session middleware. Can you tell us a little bit about what a middleware is?

Samantha Geitz:
Oh, middleware. We're going to run through the whole life cycle of Laravel.

Matt Stauffer:
Yes. You know how much I love that.

Samantha Geitz:
Okay. So, you have a website and you are making a request to a server. So, you send the request. Middleware, basically... I know you like to use the onion metaphor.

Matt Stauffer:
Yes. It's okay. Use whatever you want.

Samantha Geitz:
No, because it's a good metaphor. So if you imagine the little onion kernel, seed thing at the center is your application, there's layers around kind of both sides, or surrounding it. So, you make the request and then you have a series of middleware listed. You might have say middleware A, middleware B, middleware C. The request gets passed to each middleware in the order they're listed, so the request would go through middleware A, middleware A would do stuff, and we can go into what that stuff is in a second, and hand it off to B, then hand it off to C, then to the actual application, which would go do stuff, and then when it sends a response, it goes back through in reverse order. So, it'd be C would hand it to B to A and then to the user.
That just gives you a place to just handle whatever business logic and that might be things like, "Is the user logged in? Is the user trying to do something malicious? Is this user an admin trying to access an admin route?" It sets some session stuff. It just basically gives you an opportunity before whatever the requests is that hits your app just to do things to it, make sure it's good, and then just hand it off to the next thing. Yeah, but it's really important to know that it's passed through in a specific order, hits the app, and then in the reverse order back out.

Matt Stauffer:
Yeah. Which is, I think, the hardest part to understand at first, right? So I really appreciate how you simplified that down. A request comes in, it goes through all the middleware, hits the application, and then back out in reverse order to the end user.

Samantha Geitz:
Yeah, and then you have a lot of times different middleware that... You have kind of like your global middleware for both web and API routes, which do totally separate things because you have to worry about stuff like cross-site request forgery in web and then pores in API, so there's kind of that global middleware-

Matt Stauffer:
Rate limiting and stuff, yeah.

Samantha Geitz:
Mm-hmm (affirmative). Rate limiting, yeah, which Laravel has some pretty cool stuff with the rate limiting that makes it a lot easier to manage, and then yeah, back on the way out for each and then you can also read your register middleware for groups of routes. So, if you have some routes that are just admin routes, you can have some sort of is admin middleware that will check those things to make sure that anything happening is actually an admin.

Matt Stauffer:
That's fantastic, and I think that's a perfect time to transition. We're just going to start with middleware because we were there already. When is the last time you built a custom middleware? Because we have the when's the last time you used the system? Well, every Laravel app uses middleware, right? When is the last time you remember building a custom middleware?

Samantha Geitz:
I am actually in the process of building a middleware right now for my current clients. They want to track referrals from another website. Basically, what you would do is have a request with a get query parameter of some sort, like ?referral=otherwebsite. So, then the middleware has access to the request object. Basically, you can go in and check if that query parameter is on there. If so, you can also check if there's any sort of referral cookie already set. Set the referral cookie, and it'll go through the app and do all sorts of stuff and then if the user goes to visit other pages, that cookie'll be set.
Before anything else happens in the application, I can redirect them, I can do whatever. The browser is going to have some sort of cookie saying that this referral came through, so if they actually sign up for the website or purchase something, or whatever, we know that they did that. So, this basically grabs them as soon as they come in and says, "Yup! I'm going to do that because we don't necessarily know what page they're coming in through."

Matt Stauffer:
Perfect. Yeah. So, I love that example, and so that's one really common example of middleware where you look at the incoming request and you do something that really is not related to the route they're heading, right? It's just related to some functionality you want to check all the time. You do that work and then you're like, "Okay. Hey, rest of the app, you can have it. I did what I needed to do. I checked for the query parameter. I acted on it if it existed and I moved on." Have you ever written one custom where you're either modifying the request, or you're rejecting the request based on stuff, based on query status?

Samantha Geitz:
I've done a lot with kind of things like, "Is this user an admin?" User types thumb.

Matt Stauffer:
So, that'd be like a redirect, or an unauthorized, or something like that?

Samantha Geitz:
Yeah. In terms of actually modifying the request, I'm trying to...

Matt Stauffer:
I couldn't remember either. I'm sure I have, but I was just like, "I don't actually know when it would have been."

Samantha Geitz:
I feel like that's the kind of thing where I'd have some extremely weird edge-use case and I'd be thinking about it, and I'd probably go plug it into Stack Overflow and someone would suggest this middleware, I'd be like, "Oh. Duh!" And then just not actually store it. I feel like all these topics are very frequent Stack Overflow topics.

Matt Stauffer:
Yes, and that's the thing. That's why these are the weird ones. They're very important and useful when you need them, but they're not as much a part of your everyday work, but anyway. Note to everybody: You can read, edit and also you can basically return a response right out of middleware if you want, so you can read the request and do stuff with it. You can edit the request and then have it keep passing on, so in theory, you could actually say, "Oh, it's actually coming from a different IP address," but then you can also return responses right out of it. I had a middleware for a while that said, "If someone comes from a certain range of IP addresses, boot them right out before the app even spins up," and so that was able to save the whole rest of my application from spinning up, and also from hitting the users table and looking up the user, all this kind of stuff that would've normally happened. It just booted them right out. So, it was a really light kind of like outer wall that you couldn't even hit.

Samantha Geitz:
I have a problem in this current client I'm doing right now where they've been running Facebook ads, and we're tracking all the page views and stuff. I kind of built my own little custom activity logging thing, and we had all of a sudden this huge surge of thousands of hits a day and they were like, "Where are all these coming from? We are running these ads." It's Facebook's bots because they are not caching. Shame on you Facebook. Basically, they're going through every single time anyone does anything, scraping the website and driving up the page views.

Matt Stauffer:
Really?

Samantha Geitz:
Yeah, and I was looking into how to get around that, and apparently Facebook just likes to give the middle finger and say, "We're Facebook. What are you going to do? Not run ads on us?" So, I was thinking about writing custom middleware, because you can track everything that's stored in the request a lot of times is is this a bot?

Matt Stauffer:
The agent, or whatever it is, yeah.

Samantha Geitz:
And they have various packages and stuff you can use to kind of figure out if the IP address is a common bot address. So, I might at some point do something like grab the request, check if it's a bot, which I am logging now, but either not log it or log it somewhere else, or just do something with it because it's a bot, and they're hitting us at lots of times.

Matt Stauffer:
Is your page tracking happening in the middleware right now?

Samantha Geitz:
The page tracking is a-

Matt Stauffer:
Is a service provider maybe?

Samantha Geitz:
Yeah, it's just events that I'm firing.

Matt Stauffer:
Oh, got it. Okay. So, you've got to somehow say, "Globally turn off all these events if the middleware's set blah, blah, blah to be bot." Something like that.

Samantha Geitz:
Or return a cached result of some sort to just be like, "All right. Well, whatever data you're trying to grab to make your ads work, I can just cache that because we're not changing it and we don't need to go have you hit our server every single time and go fetch everything from the database and load whatever." So like, "All right. Here's the-"

Matt Stauffer:
Here's the dummy version of whatever you're looking for, yeah. Okay, cool.

Samantha Geitz:
So, that's probably what I'll end up doing, and that would be in the middleware and caching.

Matt Stauffer:
Yeah. Oh, look at that. All these are... And we just talked about requests like 100 times already. I was curious, do you have a rule, and after this we'll move away from middleware, of when you build something in the controller versus a service provider versus a middleware?

Samantha Geitz:
I probably will tend to put things in... I mean, obviously it's very depending on what I'm doing. My first line of defense is often going to be controllers because I feel like that would be the first place I would look for stuff. If there was some sort of... I try to think about if it's me six months from now, and what...Yeah, why is this weird bug happening? I feel like middleware's a little harder to test, so I would probably-

Matt Stauffer:
Harder to discover too, yeah.

Samantha Geitz:
Yeah, because it might be like, "Oh, yeah. I registered this random middleware and attached it to this route." I tend to, yeah, put business logic in controllers. If I need to reuse it in any way, that would definitely probably be a candidate for either middleware, or something I'd register on a service provider. As a personal preference, when I'm listing whatever routes, I try to do group, like route group, and then have the middleware in there and group them together.
I'll have like, "These are the admin routes. These are whatever," because if I'm trying to look in the controller constructor, in a route group and route definition. You might have some route resource. It gets way harder to figure out what the hell's going on. That's my little Samantha Geitz convention, but...

Matt Stauffer:
I love that. I think that's very similar to mine, which is that everything starts in the controller just because you start with the simplest way to do it and it's the most discoverable and whatever. I think that often for me, moving it up to a service provider is when it does an application level concern, which is kind of a handwavey definition, but I think the app generally tends to need this run in order to do its job. Service providers are things that I think are a little bit more global. Like you said, if I'm doing this in more than one controller, the first question I ask is, "Should this be in a service provider?"
The line between service provider and middleware is a little bit wonkier. I think the more it feels like the outside of the app, or almost like a decoration I put in the app that I could potentially put on other apps, that's when I start thinking about middleware. So, often things like page tracking. I'm like, "Man, if I could just copy this exact same middleware. Pop off that part of the onion and put it on another thing and have it work almost exactly the same," that's when it's more probably middleware than service provider.

Samantha Geitz:
Yeah. Once you start thinking about stuff like, "Okay, so I've got this piece of business logic, but might I be using it in a Laravel Nova action? Might I be using this in an API and in the web?" Yeah, if it feels something that's super tight to requests and more like just actual core application business logic, I would definitely go for a service provider over a middleware because you don't know where those requests are coming from and that's where you hit the bugs because it's expecting to be tied to this specific route groups and oops, now users can do admin things.

Matt Stauffer:
Yeah. Oops! No, I love that. I think it's a great delineation and a lot of people don't know this, but there was a big kind of movement in the PHP world that kind of died out where they wanted everybody to be building middleware that were completely compatible across all PHP frameworks and the idea that just like we share packages, people would be sharing middleware, and I mean, they're relatively compatible between frameworks these days, but yeah, I think that's a really good way to think about it. If it's business logic that maybe called multiple different contents from the app, probably it's not going to end up in a middleware. It's probably end up in a service provider, and if it is a generic request related to this particular business logic, that's more likely to be in a middleware. I like it.
All right. I'm going to let you move on. We're going to talk now about the most recent time that you worked with sessions. You already mentioned the fact that we're dealing with sessions anytime we're dealing with authentication, the users who are authenticated and saved in the session. When have you done more kind of like custom work? Oh, you also mentioned flashing messages from request to another. When's the last time you did something else in the session other than user authentication, other than flashing messages?

Samantha Geitz:
One of the kind of interesting challenges we had with session stuff: So my main client right now, they were originally a WordPress site and then wanted to build all sorts of actual application functionality that was not posting pages, so they brought me on to be building that out, but they still have their WordPress site. There's the top navigation bar that we want if they're logged in on the Laravel side to also be able to have that they're logged in on the WordPress site. That kind of comes then to the question... I know this is still kind of authentication tied, but how do you know that? How do you know who that user is? That was right around the time Laravel Sanctum came out. I was like, "Yes!"

Matt Stauffer:
Nice!

Samantha Geitz:
I think someone talked about Sanctum at least a little bit before, but basically it's storing the session then in a cookie, so if you have sites on the same domain, you can then share that session, which is pretty cool. One of the things that I'm doing with sessions... So, I mentioned I have this kind of event tracking I'm doing. So, I'm storing a bunch of just various pieces of meta information on every single event, so that might be a page that was viewed, this user... Because there's a couple different paths for them to sign up, so I have an event before they completed this step of the thing. It's a ton of data. I know there's at this point a couple hundred thousand records, but I'm storing the session ID on every single one of those, which is nice.
I know we'll talk about the gotchas, but one of the gotchas is that when you log in, Laravel will scrap and regenerate the session. A session is generated as soon as you hit the website, even if you're not logged in, but if you have that session ID, you can still track that unauthenticated user was doing stuff. So, one of the things I'm doing is when a user logs, before they actually log in, I'm grabbing the session ID of all the-

Matt Stauffer:
So, you can match what they did before they logged in with what they did after. That's clever.

Samantha Geitz:
And then backfill that they were that user.

Matt Stauffer:
I like that.

Samantha Geitz:
Yeah, but it's basically... For session, a good way to think about it is just that there's some piece of data that you're not necessarily worried if it persists after a user logs out, but it's not something that you really want to go store in a database. A lot of times, that's a good thing to store in the session. Something that will trip you up though if you're hitting stuff from an API, it's dateless, so you won't have access to a session. I guess if you're using something like Sanctum, but it gets a little dicier, so you have to kind of be thinking about web requests specifically and that's why a lot of times, if I am trying to persist data, it's not... I a lot of times try to not be working... If it's a hybrid, there's some API stuff because I'm using Vue, there's some backend stuff. Yes, Vue. I know. Team, I'm so sorry.
A lot of times, I'll be a little bit more trying to lean away from using the session just because I don't want to be tracking frontend states and then also backend state, and if you are changing business logic and you want to change that, you want to rely on it. A lot of times if you want to store something that needs to persist beyond a couple of requests, it's not a great idea to use sessions. I've seen that definitely.

Matt Stauffer:
Yeah. I appreciate that too, but I think the biggest thing we say with clients or new developers is when they log out and log back in later, or if they get kicked out, or if they whatever, do you still want that information to be saved, and if so, then session is not the case, and that's going to be more like a user settings table or something like that. I'm with you. As a result of that, I use sessions all the time because there's so many convenient session tools, but I don't do a lot of custom session work as a result of that.

Samantha Geitz:
Yeah. Yeah, it'll be... We're getting ready to build a kind of shopping cart type functionality thing in this app. They have basically classes there. This app is it's called AMAVA. I don't think they would mind if I said their name on a podcast. So, it's a site for people who are retired to connect with each other. They originally hired us to build what's called Go Local, which is for retired people to connect with other ones in their area, and we launched April 1st. Right when COVID hit, with the most vulnerable COVID population. Oh, cool.
Now, they're doing kind of some online learning classes, and apparently it's being going great. So, we're trying to build some shopping cart functionality, which that then becomes do you store that in a browser state, do you store that in the session because you don't necessarily want to track that when they log out, do you store it in a database and then try to reconcile that if they're bouncing around, doing other stuff? There's a good chance I'll end up doing that server side session, and have some sort of tracking on it still, but that would be a good candidate for, "All right. They logged out. We can clear that they were looking at this thing and trying to buy it."
I've had way more trouble with browser sessions, trying to store stuff in local storage. That becomes a nightmare. I've never been able to pull that off in a way that I was happy with. I've used various libraries and stuff.

Matt Stauffer:
For those who don't know, Samantha knows frontend. She's not a backend programmer who just doesn't want to deal with it. She's a very talented frontend programmer. It's a monster. If you can get it in the backend session without kind of like... What are the biggest problems we run into when we try to handle more meaningful state happening in the backend session is that you get that same situation where every person who visits the site spins up something in the sessions table, and so sometimes you end up getting way more records in whatever, your shopping carts, whatever that you're expecting, but once you know that's the case and you're already doing things like you're talking what to plan around then you're fine.
Sorry. I wanted to go back because something you'd said I forgot to ask you. You mentioned connecting WordPress and Sanctum. Did you make a WordPress plugin that reads your Sanctum cookie to log you into WordPress when you're logged into Sanctum, or how does that work?

Samantha Geitz:
I actually did not touch the WordPress site. My brother, Chris, is-

Matt Stauffer:
But did he do that though?

Samantha Geitz:
I don't know if he actually did an open-source plugin, but he definitely wrote code to do it.

Matt Stauffer:
But he wrote code to do that? Okay, cool. That's why I was just curious. So, they wrote code to have WordPress read a Sanctum cookie, and if you're authenticated via Sanctum then you're now automatically authenticated via WordPress. It is possible. That is cool.

Samantha Geitz:
It is possible to at least know that the user is logged in. Yeah, you're not doing anything crazy with it, but yes, a way to kind of store... Yeah. It was definitely not super... especially because Sanctum was new and there wasn't a lot of issue tracking. It might be way easier now, but it was interesting one to figure out, but that's how we managed to pull that one off.

Matt Stauffer:
I love it. I mean, people will be surprised to hear this, but I actually have multiple times recommended that a client use WordPress for their primary blogging platform because nobody compares. Not even the best CMSs in the world compare to WordPress' blogging experience out of the box. So, a lot of people are like, "Look, I need this blogging experience for cheap," and I'm like, "Well, we can recreate it in one of the amazing CMSs and it's going to cost you a whole bunch of money, or you can get it for free with WordPress and then we can do WordPress integrations," and a lot of times, that's what happens.

Samantha Geitz:
Yeah. As a blogging platform it's great. As soon as you want to do any sort of relational data, anything that's not posting pages, it's awful. I used to do nothing but WordPress in the first couple of years in my career, and it was on specifically the wordpress.com server, so you couldn't even make custom labels. So, you had a giant post-meta table, and that's where you had to try to do things like relationships and oh, my God.
I don't know if it's still this way, but at the time, there was one database for all wordpress.com, everything. So, you were writing this on just a table with a bajillion records, and oh, my God.

Matt Stauffer:
ExpressionEngine and Craft used to be that way too. I don't know if they still are, but it was like we would try to write eloquent queries against ExpressionEngine data and the first project I did with EE, and it's like, "Well, good luck because of all your different schemes all live in a single table." No, I feel you on that.
Yeah, it's a great plugin platform and it's cool when we can build these more complicated interactions with it because if somebody needs a blogging platform that is robust and we can build integrations because now there's a WordPress API, and now you're saying we could potentially even hook it up to Sanctum or stuff like that, not perfectly, but at least to authentication proof. That's really cool.

Samantha Geitz:
Anyone out there is wanting someone to do some consulting work on that.

Matt Stauffer:
There you go. That's samanthageitz.com. Leave it in the show notes. There you go. I love that.

Samantha Geitz:
The process of actually branding ourselves as a thing. I'm working right now with my brother and one other super talented developer named Ellen Shimada. She's great, and another one of our friends out in Hawaii, Mike Han. So, we're actually trying to form a little actual thing and name ourselves and do stuff. Oh, my God. My mic just fell over as I'm giving my pitch, but yeah, we've done some WordPress Laravel integration, so if you want to know how to do session sharing-

Matt Stauffer:
These are the people. Yes, I love that. I mean, honestly, I might have to give you a call at some point if we're going to do another one of these. Alright, so before we get to the common challenges and gotchas, I don't think I actually asked you the last time you use cache. So, you mentioned briefly one of the things that you might do is more like a page cache, or a cache of a certain section page, like the footer. The footer is really expensive and so you're going to cache the rendered HTML, which is one way to do it. Have you often found yourself caching more database requests or API requests, or is that not something you do that much?

Samantha Geitz:
Definitely some of both. If it's any sort of API requests. So, I'm using this one site as an example. So, we have our WordPress site that has the various news articles and stuff, and then the Laravel app will hit that to grab the footer posts and stuff, so I can put that example. So, we just cached that. The WordPress site doesn't change enough that we have to worry about that, but we have a lot of these sort of classes, a lot of kind of nested resources, and I can definitely notice more and more the performance starting to get a little slower. So, I tend to kind of just try to keep an eye on something like Telescope maybe and just see how long are some of these requests taking. Are there other nested resources? Is this data changing?
If it's something that we know is not going to change a ton, or even if it is changing every couple of days, or whatever, and you just notice that some of your stuff is just being a little slow, a lot of times just caching those database queries that you have in your controller or a service file or whatever, you can have some pretty complicated queries that you don't have to go do every time, and you don't have to worry... Those weird query loops, where if you're trying to grab a nested resource that also is tied to a resource that's tied to the first resource. I've run into that. So, just so you know you have a certain set of data, you can return it as a giant blob, and just kind of figure out what that is going to be.

Matt Stauffer:
Yeah, cache the blob.

Samantha Geitz:
And then obviously, if you are at all the responsible developer, you're probably hopefully caching your static stuff, so if you have CSS, JavaScript, any of that stuff, Laravel Mix has some really great stuff built in for that. If you want to get really crazy with it, you can do something like CloudFront, but really, it helps the performance of your site so, so, so much if you want to do caching, especially if you have a ton of records. You can start off like fairly easy with it and then build it out as you need it. One of the mistakes I've definitely seen developers make is just always want to cache everything.

Matt Stauffer:
Yeah, a little too heavy.

Samantha Geitz:
I want that couple of extra milliseconds, but that site is getting 100 visitors a day.

Matt Stauffer:
Yeah, premature optimization is the root of most evil. That is definitely the truth. One of the things just as a totally random question that I don't hear people talk about very much. So let's imagine a really common pattern is I've got a database query on my homepage and because it's on the homepage, it's not just like a simple paginated list, it's actually this really complicated calculation that gives me the one of this that has the most points over the last seven days and then the one of those that has received the most views times seven plus the number of points, which comes across five different tables, and you just got the super complicated query, and you're just going to have to say, "There's no optimization left in this query. It's going to be slow."
So you wrap the query in a cache remember, and for anybody who doesn't know, there's this thing called the cache remember, I'll link it in the show notes, and you basically say, "Whatever comes out of this closure," so an anonymous function, "Cache it until X amount of time has passed." So you give it an amount of time. Let's say you give it six hours, and then here's the key to cache it under. That's all you have to do. You just wrap all your existing code with that and now, not only is your code being defined, but it's also being cached instantly as soon as it runs. So that first time it runs, just to be extreme, let's say it's a query that takes 30 seconds and then every single person after that for the next six hours, they're going to get the cached version, which is going to take 50 milliseconds. So, that's cool.
What about that first person? Do you ever warm your caches? Is that something you're into yet, or have you not gotten to that level? This is a premature optimization question for sure because most of us don't have 30 second long queries. Are you in a place right now where you're doing that thing where you're having some kind of automated system warming the cache for you, or do you allow yourself mainly just rely on, "Hey, you know what? Every once in a while somebody's going to get a little bit of slow requests, but then every person gets that same request for the next 24 hours is going to be fast again."

Samantha Geitz:
I definitely at this point I'm not doing that. I think if you wanted to do that, I would potentially do something like dispatch a job in a queue to do that, or maybe you have a cron that runs in the background, so your server's actually just doing it and just setting... Because once it has that key, it's not tied to any specific user, it would be in say, a session. Also, if you had the level of traffic where you are really worried about doing that kind of thing. If you have one user out of 1000, you might have an extra second load time, is that something that you really want to spend an hour building a process for? Maybe.

Matt Stauffer:
And a lot of people who have that level of traffic are also using some kind of static caching in front of their site anyway. They're using a Varnish, or something like that, so they're not even having that problem.

Samantha Geitz:
Yeah. Definitely. Yeah, you would want something like Varnish, or I think CloudFront, you can do full stack caching now.

Matt Stauffer:
Yeah, and CloudFlare does a lot of that stuff too.

Samantha Geitz:
So, I think if I were really worried about that, yeah, I would reach for some DevOpsy kind of solutions rather than... Yeah, the more kind of like weird business logic crons, I would have under the hood. That's just that much more I guess, oh my gosh, DevOps. That's true too. I'm sure we've all been there where we were making changes and refreshing the page and like, "Why is it not changing?" It's like, "Oh. I didn't clear my damn cache."

Matt Stauffer:
No, but I agree, and and I love that metric as well because for example, you can imagine a system where every time you've got one of those cache remembers, instead of it being called in the controller, there's something else somewhere that is responsible for defining that cache remember and then keeping it warm all the time, so your controller only has to reach for that key in the cache, but that's one more system that you're not going to be quite sure where it came from, your request where that error happens is no longer going to show that error in the stack trace, it's going to be totally disconnected, and so it's just one more area of obfuscation.
I thought of these systems a lot and never implemented them and usually when I get to the point where that one person being slowed down for the next 24 hours, that's when I'm like, "Okay. Let's look at a static cache because I can't imagine building a system that way." So anyway, if somebody else has built one of those and has a magic answer for us, let us know, but Samantha and I are not doing it that way.

Samantha Geitz:
Yeah. I would much rather have that one person be slower than be trying to dig through like Horizon logs, or have everybody have something weird and broken because I...

Matt Stauffer:
Yeah. Yeah, exactly.

Samantha Geitz:
In fire, or whatever.

Matt Stauffer:
So, I realized we haven't actually talked technically and specifically about requests yet, so one of the things I wanted just to ask is day-to-day, I think I have one most common use for requests, but I want to ask you: If you were to reach for the request object in your average Laravel app, what would you be doing?

Samantha Geitz:
If I were reaching for the request object, I almost certainly would be getting input in a controller. So, you can either do you dependency injection in the actual method itself. I love that little helper request function, and you have the option of just grabbing request all and it'll just show you everything the user submitted in the form. You can do request only, and then pass in the array and say, "I only want the form fields of first name, last name, email, if it turns an array," and then you could pass it into an update or whatever, or create. You can grab specific ones, so that would be like you can either do request input, or then just the request helper with whatever the name is in there. That almost always would be what I would be doing with it. You might be grabbing query parameters in a get request too if you're trying to do something, but yeah, I think for the most part, it would be on either a poster put patch.

Matt Stauffer:
Yeah, and it's an interesting point is that if you were to think about... Because often when people talk about the global helpers, there's a little bit of criticism about making them harder to test, but then something I just realized is that if you type hint your requests, or if you use the global helper, either way, you're probably going to be testing them using Laravel's integration testing, at which point, you're not building a mock request object manually anyway, you're still going to be using Laravel's request equals this get, or whatever. So, that's an interesting point is that in terms of testing in Laravel, the way you get your request has almost no difference at all because you're going to be generating the request using Laravel's helpers anyway because I tend to think dependency injection is a little bit safer for testing, but in this case, it's not actually any better. It's really just whatever works the best for you.

Samantha Geitz:
No, I almost exclusively... And if I'm testing something having to do with requests, it'd be an integration test where I'm passing in some sort of data and saying, "This post to this route, blah, blah, blah," and then checking that the response is returning the response code I expect, the JSON I expect potentially, and then maybe checking if assert database has asserted that this object's updated in this way. Yeah, I'm not actually checking that because if I had a typo and I'm trying to grab first neme instead of first name, or whatever. I would know because it's not saving it to that object and then returning it, or it'll throw a 500 or something. I've never run into any issues with that. I've never really had any reason to mock a request.

Matt Stauffer:
I was just going to say, I don't think I've ever either mocked a request or actually instantiated a fake request since Laravel had the integration testing built in. So, you don't need to do it anymore. I love that. Okay. So since we have four topics we are far in and we haven't even hit common challenges and gotchas. So I'm going to ask you now for all four of those. We're going to do them in a row in whatever order you pick. What are some common things that trip people up that you kind of think that... Or even if it just like what's one thing you wish that everybody knew of each of these systems?

Samantha Geitz:
I would say caching, the very obvious one is if you are using any sort of caching, and you are refreshing your page, and things are not updating, first make sure you're not on your staging site or production and think you're on your local because my stupid ass does that all the time.

Matt Stauffer:
Same.

Samantha Geitz:
But a lot of times, you need a cache bust in some way. You will save yourself some times just 15 minutes if you can just think, "Oh, caching."

Matt Stauffer:
So, if you were working locally, and you wanted to wipe your whole cache out, and we're not talking about busting a cache in terms of the frontend things like app.js, whatever, we're talking about your backend cache, what would it look like for you to wipe out all of your cache locally?

Samantha Geitz:
First thing I'd probably do is a php artisan cache clear.

Matt Stauffer:
Right. No matter what cache you're using, it just wipes it all out for you, right?

Samantha Geitz:
Yeah, wipes it out. You also have the option of using the array driver for testing because it's not persisted in any way. Especially if you're doing any sort of testing or running it as a suite. That's probably the way to go.

Matt Stauffer:
I love that, and I have used array driver sometimes to make sure it's working without the cache, but then I also have to remember that I do also want to make sure it works with the cache too. So, you got to check out both of those angles because there's so many things where you hit it to production for the first time. Your local setup is different than production in whatever way and then it works fine locally because you were using file cache or array cache, and then you push it up to your Redis production, and you're like, "Oh, something's broken. Maybe I should have tested that locally." All right, so let's talk about session. What are some common gotchas and challenges for sessions?

Samantha Geitz:
I think especially if you are new and hadn't really done a lot with web versus API, something that is going to really trip people up is that... And I mentioned this previously, but API requests are inherently states, so you do not have access to a session. So, the way that APIs instead of having a server session kind of get around that is you'll have whatever, say an auth token, and when you send the request, you'll have authorization header and you'll have a token in there, and then the server will grab that and be able to say, "Okay, this is the user and they are who they say they are," but you can't store things on a session. You can't flash things, you can't whatever. So, something like Sanctum, where you're storing session on a cookie will give you some ability to interact with session via JavaScript, but if you're trying to store something on a session and then access it via API, you're just not going to be able to do that.

Matt Stauffer:
No, that's really helpful.

Samantha Geitz:
The other thing with sessions that has definitely screwed me up some in controller constructors, sessions are not actually part of that request, originally controller constructors. So the way you can kind of work around that is actually via middleware. So, if you really need to do something in a controller constructor, you have the option of doing this middleware and then have whatever closure, and then just kind of do stuff. The other thing... God, I keep knocking this mic over. The other thing that you can do is if you look at your web middleware, like global lists, there's one that's called start session. You can create a middleware and list it below that and I mentioned that when you do middleware, it kind of like works its way down the list in order, so you have something after, it has to specifically be after start session, but then you can grab whatever session stuff you need. It might even just be something as simple as auth user.
If you're trying to just do an auth user in the controller, you just can't do that in the constructor, so that's something that I've definitely seen people trip up, but it has to be after a start session, or it won't...

Matt Stauffer:
Or the session won't actually be opened in PHP. Nice.

Samantha Geitz:
And then the other thing that could also potentially screw you up: So, I mentioned the array driver for sessions does not persist. So, if you're trying to do something with sessions in testing, you have the option, there's a with session method where you can kind of pass some stuff through, but if you're trying to test something like I was with how you have the session ID and you want to grab that when they log in and then grab the old session ID and do stuff. If there's a great way to test that, I really wasn't able to figure that out.

Matt Stauffer:
Makes sense. Yeah, because in testing, you're always using a session array driver, right?

Samantha Geitz:
Uh-huh (affirmative). Yeah, it's not going to be something where you can say, "Oh. These things happened and then I did this other thing and logged in, and I went back and grabbed the old sessions." It's not going to persist. I just wrote a lot of tests around the actual business logic to kind of do that, but the actual session part, I just kind of was like, "This isn't going to track with 100% accuracy. I'm not Google Analytics. I can for the most part figure out who did what. It's fine."

Matt Stauffer:
And when you have the vast majority of the application covered except for one little piece of glue, you know to pay attention to that piece of glue working.

Samantha Geitz:
If I'm not grabbing every single event that they did when they were not logged out, it's... Okay, sorry.

Matt Stauffer:
Yeah, not the end of the world.

Samantha Geitz:
That's definitely gotcha if you're using the array driver, or if it's not persisting for some weird reason, that would be something I would check is make sure you have whatever .env, that you have the right cache driver set.

Matt Stauffer:
Yeah, the number of times when something was inexplicably not working that came down to just go check your .env. Oh, my God. Alright, so middleware and requests, common challenges and gotchas.

Samantha Geitz:
For middleware, I would say definitely checking the order. If you have things listed in a weird order, that definitely... If you're trying to do something like check cores, or check that something's in a session before the session's actually instantiated, it's very easy to be installing a package and see that you have to put some sort of middleware in and just pop it somewhere in the list, and then that may not work. I think a lot of people when they run into cores issues have just the middleware literally in the wrong order.

Matt Stauffer:
Oh, interesting. So if all else fails, throw... Oh, yeah. You're right because your cores... Yeah, okay. When all else fails, if you're putting in a new middleware, just throw it at the bottom of the stack. That's the default because it'll have access to everything, right?

Samantha Geitz:
And I think a lot of times too making sure that you have web and API middleware in the right place just because API is not going to have that in a session, although there is the now ensure frontend requests are stateful sync to middleware. So I guess that's...

Matt Stauffer:
Depends on what type of API...

Samantha Geitz:
Yeah.

Matt Stauffer:
But if you're talking about API's accessed by a mobile app, or something like that, it still won't have the session.

Samantha Geitz:
Right, and then making sure that if you write middleware... So, you're passing in the request first, and then whatever, and then you have this closure, that's like $next, and that's what actually hands it off. Just making sure that you have both those things in there, and you're eventually returning a response, I think if you aren't doing the next or whatever, it's not going to know to pass it on to the next middleware in the stack, so I would definitely check that if just things are not passing around the way they should. So, I think that would be the big thing for middleware.
In terms of requests, I feel like the biggest issue I have with requests is just typos.

Matt Stauffer:
Yes, because it's strings, and we're not in Ruby, so we don't get magic strings.

Samantha Geitz:
Yeah. I feel like I'm just like, "Why is this one value in this form not coming through?" And I'll spend 20 minutes debugging it and then be like, "It's because I had the name totally wrong," or something.

Matt Stauffer:
Exactly.

Samantha Geitz:
Because I'm pretty quick to just title requests, and just be like, "What the hell is going on here?" I feel like other than that, requests tend to be... I guess, if you're trying to do any sort of IP tracking, you'll have to keep in mind if you are using something like CloudFront, or some sort of reverse HTTP proxy, it isn't going to necessarily show the IP the right way, so you have to do additional things to add that.

Matt Stauffer:
Yeah, quick note on that for anybody who doesn't know, if you have never dealt with this before: If you're using a proxy in front of your site, like CloudFlare, a lot of its fields are going to come through as the CloudFlare version of the fields, but then CloudFlare will add extra headers to your request that are like X underscore and then whatever their various things are. Laravel has a tool built by Chris Fidao for that called Trusted Proxies that allows you to do some of the aspects of that, where it basically says, "Hey, I trust that if CloudFlare is the one that added those C headers, then those X headers are correct," and so it's allowing CloudFlare...
It's saying, "I trust CloudFlare, whoever else, to do send me proxied headers," and which headers it trusts, but there's still other aspects of like that, like Samantha's talking about, where if you're getting every single IP address is exactly the same, first thing to look at is go dump the headers, or just ask yourself the question, "Do I have a proxy?" Because if so, things are going to behave a little bit different than you're expecting.

Samantha Geitz:
I think with load balancing too, you could probably get some kind of mess with that. I also imagine a lot of people who are using any sort of Varnish, or CloudFlare hopefully are not inheriting a site, but enough about DevOps. We can kind of at least know where to start on debugging that because it... Oh, my god, that kind of thing can just get super, super complicated on the backend even if you know a lot about it. I mean, I'm literally on a podcast talking about it and if you threw me at a Varnish saying it was broken, I'd have to do a lot of research to figure out why.

Matt Stauffer:
Same here, and I've worked with multiple very, very, very large Varnish sites and I would still Google. First thing I would do is Google. There's one other thing that I noticed people getting hung up on request, which is I would just say, "Don't use request-all, just period. Don't use it." Request-only is the only one you should use in actual production basically globally, and I'm trying to think of any time you should use request-all, and the reason is because request-all allows the user to pass any information they want to it and you're potentially getting fields that you don't want to be set, and this gets to the stuff we talked about in the database episode about protecting your database, but request-only is your friend.

Samantha Geitz:
Yeah. If you're doing a request-all and then you have a fillable empty array, oh, you are setting yourself up for a world of hurt on that one. Don't do that.

Matt Stauffer:
Yep, and especially if you've heard the people in the world, including myself, say, "All your models should be guarded equals ID, or fillable equals null, or whatever." Basically, the whole thing we're saying, you're getting rid of all that mass requesting. It's convenient, but you have now put the responsibility on yourself to limit the data that the fields that are coming back from the user, and you must do request-only in order to do that, and if you're not doing that, if you're ever going to use request-all in your app, then use mass assignment protection on your models. If you don't know what this means, just don't ever use request-all. The day one rule is never use request-all.

Samantha Geitz:
I sign off on that rule. It's a good rule.

Matt Stauffer:
I like it. Okay, so since we are going so late, usual disclaimer: I could talk to you for hours, you know this because it's happened before. Is there anything else you want to share with people before we start rolling up for today?

Samantha Geitz:
I think the one thing I would share and I know we mentioned this earlier is these are all very complicated topics. I'm literally on a podcast talking about it and I would probably have to go look all the time on any of these things on Stack Overflow. There's so much to know and it's different between different drivers, so if you find yourself getting really frustrated because you don't really understand entirely how you should be going about doing caching, or whatever else, you can always take baby steps, find the requests that are slow, just get a simple cache just for that. Same with middleware. Just start off having things in your controller and then if you're repeating that, you can move to middleware. Don't feel like you need to be a deep dive expert on any of these topics just because they exist. You don't have to reach for them unless they're the tools that makes sense. There's a lot there.

Matt Stauffer:
And that's one of the reasons why we did this one is because we want those tools to exist for you. You knowing caching exists hopefully will give you a one day where you go, "Oh, I can solve that with caching," but we don't want to go into such great depth in these because they're not as much of your day-to-day as for example databases, and so, I love what you just said. Just learn what you need to learn, get a familiarity, but don't put this pressure on yourself to be a deep expert in all these things. So, before we get to how people can follow you and pay you money, all that kind of stuff. Everybody's got their personal fun moment, and it was very hard to pick one for you, but I'm going to ask a question that is going to show you how good of a person I am and how humble I am, and I'm going to ask you who is the best science fiction author of all time?

Samantha Geitz:
Are we talking science fiction or-

Matt Stauffer:
Or fantasy, sorry. Fantasy and sci-fi.

Samantha Geitz:
So, some background on this question for everyone out there in Internet Land: It's not easy to get Matt Stauffer going about topics that aren't politics, and we got into it pretty hard at one of the Tighten off sites about... So, I'm a huge fan of this author Patrick Rothfuss. He wrote a book called Name of the Wind and The Wise Man's Fear, and I think he's a wonderful writer. I love his prose. I like the way that he plays with conventions and Matt is not a fan, and he likes this author called Brandon Sanderson, who I think writes books like he's playing a video game. Wait, so they have all these potions that they drink that give them various superpowers for a limited amount of time, and they have all these different fairy types running around? This might be good as a video game. So, we tend to-

Matt Stauffer:
We don't always see eye-to-eye on it, but it's a good conversation every time, right?

Samantha Geitz:
And Lin Manuel Miranda... There's going to be a show, and he's doing the music, so I think it's going to be wonderful.

Matt Stauffer:
See, Lin Manuel Miranda is doing a show based on this author who drives me nuts, but to give me a little credit. I read through the entire series because I think the stories were so good. I'm just so annoyed with how he writes. So, I'm hoping that Lin Manuel Miranda will see the gold in the stories and just get rid of the prose that drives me nuts and some of the character moments that drive me nuts, and he'll make it everything I wished it was when I was reading through it.

Samantha Geitz:
This is what happens when you have two English majors who spent an hour and a half talking about programming and then need something else. I think if you ask me to pick my absolute favorite fantasy-

Matt Stauffer:
Your actual, not just the joke.

Samantha Geitz:
Joe Abercrombie. Have you ever read anything by him?

Matt Stauffer:
Never.

Samantha Geitz:
Oh, it's good. Yeah. Start with, I think it's called The Blade Itself, it's first in the series. He is known as a quote unquote grim dark author. So, it'll be kind of like Lord of the Rings, but Aragon is a puppet king controlled by Gandalf, who is secretly an evil wizard, and the hobbits all get cancer from their proximity to the ring. It's really very gritty and dark. I feel like in 2020, he came out with a new book and I didn't read it because I was so depressed. I didn't want to get more depressed. Now that I'm married and happy, I actually have been meaning to do that. I got the new Kindle.

Matt Stauffer:
Hey! That's nice. That's the waterproof one too, right?

Samantha Geitz:
Yeah.

Matt Stauffer:
Yeah, that's the one you take on vacation with you and you take it anywhere and don't worry about it. Just get in the hot tub with a Kindle.

Samantha Geitz:
That's normally when I use the Kindle is when I'm by a beach or pool, because I can't read on my phone. Joe Abercrombie is... I don't think I've read a book of his that I don't use like. I think he's not quite as purple prosey as Rothfuss, so try him out.

Matt Stauffer:
I'll try it out. Actually, I'm more worried about the gram and given it being 2020, but I might try it anyway. Actually, I will just because I trust your recommendations.

Samantha Geitz:
It's a lot of very morally gray characters doing kind of shitty things to each other, but...

Matt Stauffer:
Now wait a minute, you like The Magicians though, didn't you?

Samantha Geitz:
I didn't read The Magicians.

Matt Stauffer:
Okay, so that we read this book with my book club years ago called The Magicians and I hated it because it was so negative, but it never redeemed itself. It just ended up with like, "Yeah, the world's terrible, People are terrible." I was like, "Ugh." So, I was going to say if you like The Magicians, maybe we're not on the same page, but you didn't, so we're good. Okay, cool.

Samantha Geitz:
Some characters get happy endings. It's not-

Matt Stauffer:
Okay, it's not all doom and gloom. Okay. All right. I got it. Okay. So, if the people think you're amazing and they want to follow you, if they want to pay you money for working on WordPress or other Laravel related things, how do they do it?

Samantha Geitz:
I'm on Twitter, @samanthageitz, G-E-I-T-Z. I feel like I have maybe dialed back on some of the political stuff lately.

Matt Stauffer:
Your bio still says what it says, but you're right, it's a little toned down.

Samantha Geitz:
Oh, my bio... There was a guy running for senate in Missouri who had this whole delightful quote about how he didn't want his daughters to work and grow up to be nail-biting manophobic hell-bent feminist she-devils who shriek from the top of a thousand tall buildings. Literally a politician said this, so of course I adapted that for my Twitter.

Matt Stauffer:
The funniest part of about it is that I remember that, but people have seen this as your thing that don't know that there's a reference for it, and I think it's lovely.

Samantha Geitz:
My banner is men are trash.

Matt Stauffer:
Which of course you believe, and you also think all men are terrible. Of course. There's no jokes here or anything. I am amused that it is an elephant just because of our proximity to PHP.

Samantha Geitz:
That's why it's an elephant.

Matt Stauffer:
Oh, is it really?

Samantha Geitz:
Someone made that specifically for me.

Matt Stauffer:
I didn't realize that. That's fantastic!

Samantha Geitz:
Yeah. I was like, "Of course that needs to go up," but yeah, that's the best way to reach me. I have a samanthageitz.com website that is not... Someone tried to rip it off, so I guess the design is literally more important.

Matt Stauffer:
So, if somebody wants to pay you money, your consultancy group does not have a website right now, but I would assume that... This is going to come out in a couple of weeks, like two or something like that, so that's going to be Thanksgiving-ish. Maybe around Thanksgiving-ish, maybe there's going to be a website, but if not, just set yourself a little reminder in your phone to go back to Samantha's Twitter or website. Which would be the more reliable one to point to your consultancy stuff?

Samantha Geitz:
My Twitter would definitely have it. Also, you should follow me on Twitter because I'm delightful, and it will just pop up when I-

Matt Stauffer:
There you go! That's the thing. If you want to hire eventually, follow her delightful Twitter self and then you'll see it when she announces it.

Samantha Geitz:
I'm going to get back into blogging again too once I'm done being married.

Matt Stauffer:
Yeah, done with the initial excitement and ceremony. Congratulations, by the way. I didn't say this on the air. Congratulations! That's wonderful.

Samantha Geitz:
Thank you so much.

Matt Stauffer:
Any other plugs, anything you want people to follow or do, or maybe just follow you on Twitter and hire you when time comes?

Samantha Geitz:
Well, we're pretty booked up with client stuff at the moment, so if you're looking for client work, you should definitely go follow and hire Tighten. They only hire the very best of the very best.

Matt Stauffer:
Yeah. The best people.

Samantha Geitz:
The best people.

Matt Stauffer:
Oh, my God. I love it.

Samantha Geitz:
But they do good work, so you should hire Tighten.

Matt Stauffer:
Thank you, Samantha.

Samantha Geitz:
Of course.

Matt Stauffer:
You know this was a total pleasure. I'd do it 100 times more. Thank you so much for sharing all this stuff with us. Is it okay if I volunteer that if people have questions about the things we talked about today, you're available on Twitter for answers?

Samantha Geitz:
Hit me up. Hit me up on Twitter.

Matt Stauffer:
I am too, but she's better, so go ask her if you have questions about any of these things. All right. Thank you so much. It was a pleasure and we'll see you all next time.