 I'm Micah Wood. I'm known as WP Scholar on Twitter and my website, et cetera, et cetera. So what I do is I work on enterprise WordPress projects. And I do a lot of teaching and mentoring within WordPress and JavaScript. And so I live just east of Atlanta, and one of the things I've just started doing recently is actually posting WordPress development tips on my website. So if you're interested in daily or weekday development tips, be sure to check that out. So but today, I'm going to be talking about debugging in PHP. So the point of today's talk is to encourage you, if you do not do debugging in PHP, at least interactive debugging, to encourage you to do so. And to show you how you can get that set up quickly and hopefully as easily as possible. So how many people in here actually do interactive debugging in PHP? A few. OK. So for those of you that already do this, you may learn something, you may not. So first thing we're going to go through is just kind of the basic mental process, obviously, of taking a look at a bug, what kinds of things are involved. And obviously, the first step is to figure out what you're dealing with. You've got to identify the issue and understand what is going on. So obviously, to understand the issue, you'll have to know what steps you have to, what the steps are to reproduce the issue. So obviously, if this is a web issue, you're going to want to have a URL. And typically, you click here, click there, do this, do that. And then what were your expected results? So you go through these steps. What is it that you were expecting to happen as opposed to your actual results? So the interesting thing about expected results is I have a plugin in the WordPress.org repository. And it is designed for a specific purpose. And I've had people come to me and say, well, your plugin doesn't do this. It's not working. It's broken. But the reality of it is that their expectation of what the plugin did did not match what the plugin was intended to do. So expressing what you're expecting to happen is very insightful, because sometimes it's just a matter of, oh, it doesn't do that. So make sure that you get that information as well as what actually is going on. Kind of a quick and easy way of remembering the information that you need for a bug is, I did, I saw, I expected. So if you can remember that little phrase, I did, I saw, I expected. I did, ABC, I saw, DEF, I expected XYZ. Then you can easily report a bug and remember what all goes along with it. So another thing that's important to know is what workarounds there are. Sometimes knowing what the workarounds are will actually give you a lot of insight into what the issue is. So that's important. Obviously, any error messages that you run into, it's important to capture those. And of course, any environmental information. So browser, device, all of those different kinds of things, operating system, WordPress versions, plugin versions, et cetera, et cetera. So once you've identified the issue, the next step is to obviously be able to duplicate it. It's kind of hard to fix things that you can't replicate. So sometimes in the attempt to duplicate an issue, you realize that you don't have all the information. And you have to go back and really evaluate what's going on. So for example, I've had some issues lately where something's not working. Okay, well, it's related to caching. And well, we have caching on the production server and the staging server, but not on our local development environment. So duplicating this issue locally is going to require setting up caching, so on. So the next step is to isolate the issue. And this is where the true skill lies, right? So you want to be able to first of all have the domain knowledge and understanding of how WordPress works, how the plugins or themes that you're trying to work with operate, whatever it is that those things are trying to accomplish. So one of the things I've learned about debugging is you have to think like a kid. So when you come across an issue, you look at it and you say, why? And then you figure out, it's because of this. Why? You just keep asking why and why and why and why until you get no more answers. And then chances are you'll get to the true cause of the problem much faster. So be a kid, ask why a lot. So one of the things I do to try to isolate the issue and really get down to the bottom of it is determine what type of issue you're dealing with, right? So there's a bunch of different classifications that an issue could fall under. So there's the visual aspects where you've got HTML or CSS problems. You've got interactive, usually a JavaScript problem. You've got functionality issues where something's probably gone wrong with PHP. You've got data issues. A lot of times these are user issues, but sometimes they're related to MySQL. Environmental issues with the server, performance issues, security issues, caching issues. So if you can kind of classify where your issue falls, chances are you'll be able to understand much quicker where you need to go look. One of the other things you wanna do is try to determine the source of the issue, so in determining the source of the issue, I don't mean necessarily finding the exact line of code. But in kind of a first step of determining the source, you wanna figure out, well, is this actually in the theme I'm using? Is it in the plug-in? Is this a data issue? Is this something with the web host? Is it a third party API? Is this something that is actually a problem with WordPress core? So you wanna identify in a general sense where that issue's coming from. And obviously there are some debugging steps and things that you can do. Or I shouldn't say debugging, I should say troubleshooting steps, right? That you can do to kind of figure out where you should be looking. And then you wanna think about it very methodically, right? So typically, if you can figure out that the issue's coming from, let's say a plug-in, the next thing you wanna do is to if you don't have interactive debugging, typically what you would do is you would just kind of half it, right? Like you'd say, well, I think that this is happening before this point in the code, or maybe after that point in the code. And you could do a few tests and see if maybe you're still running the issue, if you just split things in half. So for example, there's a tool called get bisect. So it's a great tool, especially when you're dealing with who changed what and broke this thing. So if you use get, you do all your commits. And you can basically mark commit as bad and the commit is good. You say, this one works, this one doesn't. And then you can use get bisect and systematically go through and figure out exactly which commit the issue happened in. So that can really help you narrow down where the actual code changes were made and maybe what they relate to. But ultimately, one way or another, you can't beat actually jumping into the code and going line by line by line and looking at it and inspecting the variables and doing those kinds of things. And that's really what this talk is about, right? So we wanna use the scientific method, right? So you make an educated guess, you form a hypothesis, you figure out what you're gonna have to do to prove or disprove that. And then if you prove it, then you found the issue. If you disprove it, then you have to figure out what other possible causes there are. So as far as interactive debugging, kind of the standard tool, there are other ones, but this is the one that I use, it's called xDbug. It's a PHP debugging extension by Derek Rethans. And the URL there is actually for their install wizard. So the wizard is nice because what you can do is you can take your PHP info file or output, I guess, and you can just paste it in there. And it will tell you exactly what you need to do for your specific operating system distribution configuration to set xDbug up. However, if you follow my steps here. I didn't mention the link for the slides is on Twitter. So if you look right before this talk started, I posted those. So you'll have a link, all the links and things will be on the page where the slides are. So yeah, so it's got the install wizard, you can easily get that set up. But ultimately, if the process that I'm gonna explain, you won't actually have to go and set this up, hopefully. So one of the things that xDbug does at a very surface level, so if you just got it set up, it would do things like take your var dumps, which a lot of people have started, when they start PHP, they start with var dump, and that's their debugging. I call it the poor man's debugger. So you end up with something like this, it's kind of messy, kind of hard to read. And it'll take it and turn it into something different, right? It's a little easier to read, and that is not the full benefit of xDbug by any stretch, but it's a start, right? So when you do use var dump, you at least get a better output. The other thing that it'll do is if you have an error, something like this, you get a little bit of information. And if you have a background that's black, you won't actually see this. So xDbug will turn into this. So it adds the call stack, it makes it bright orange, you can't miss it. And then, so it gives you enough information that if the error here at the top doesn't really make sense, or says it's related WordPress core, and you look through the call stack and realize it's related to a plugin, saves you a lot of time. So xDbug is nice, but when you pair it with PHP Storm, which if you don't have it, you should go download it. It's a great tool about, there was a survey done of this. I think it was like, it was somewhere between four and 8,000 just PHP developers, not necessarily WordPress developers. And about 38% of them were using PHP Storm, which was the majority in the survey that they did. So it's a really good tool, and a lot of people use it, and there's a reason for that. So if you use PHP Storm, you can go to this URL, and you can set up some debugger bookmarklets. So they have a little bookmarklet. You just drag it up to your browser bookmark bar, and you can click start debugger, and stop debugger, and it'll turn it on and off. Which basically sets and unsets a cookie in your browser for debugging. And then on the PHP Storm side, there's just a little button that looks like a telephone. You click that, and it'll start listening for debugger connections, right? And so this is their zero configuration debugging set up. So that's really all you have to do to get PHP Storms or something. So you have to have obviously a project open and running in PHP Storm. But then you have those bookmarklets that set the cookie, and then you push that button. And you go back to the browser and reload your page, and it'll start debugging, as long as the code is local, if it's not, and there's more set up. You can do remote debugging, but I won't go into that. So the benefits of having debugging in PHP Storm, and again, you can do this in other tools. Sublime, you can set it up. Sublime isn't so much an IDE as a glorified text editor. So PHP Storm is a full-fledged IDE. But what you can do is you can just set a break point, right? So wherever you want to pause the code, you just click over here off to the left, or to the right of the number on the line of code. And what it'll do is it will set a break point, and when you start the debugging, wherever you end up, it'll highlight it in blue, and you can step through line by line and go through the code. And so one of the things that you can do as you go through is you can view all the variables that are in the current scope. So if you're in a function and you have very specific variables that are available, you have those, but you also have access to the globals. So for example, if you submit a form, like save a post in WordPress, you can actually inspect all of the post variables that were submitted right there in the debugger, which technically you could do that in Chrome development tools, but when you're debugging, it's nice to have all this in one place. And you can also watch variables and functions. So you can say, I want to watch this very specific thing, or run this function and tell me what the value or output of it is, and it will do that. So here you can see an example of fetching a key or a value from an array, running a function, and running a method from a class instance that is currently in scope. So the other thing it lets you do is, aside from if you have an error, it gives you a call stack, well obviously if you don't have an error and you're just running through the code, you can still inspect the call stack and see what files and functions you've run up to that point. So if you realize that I think I see what the issue is, but I've already passed wherever that happened, you can kind of look back and see what functions are there. So that's PHPStorm and Xdebug. So one of the things that you can do to get up and running relatively quickly is to use VVV. And no, that is not the VVV logo. They don't actually have one, but I found something that looked good and put it up there. So with VVV, you use a tool essentially called Vagrant, and it creates a virtual machine and allows you to have a local development environment. So if no one has used that before, it's a great, easy way of setting up a local development environment. And what it allows you to do is also share that environment with other people. So everyone can have the same thing that they're working from. But the cool thing about VVV is that it actually has Xdebug already set up and ready to go. The only thing you have to do is turn it on. So all you have to do is vagrant SSH into the VVV instance. You run Xdebug on, and it turns Xdebug on. You run Xdebug off, and it turns it off. And of course, the benefits of being able to turn it on and off is that if it's running, it will make things run a little slower. Although, on my machine, it's so minimal I usually don't even notice, but you can turn it off to make things a little bit more performant when you're not debugging. But it is important to know how to turn it on, because every time you shut down and reboot your VM, it will require you to turn it on. But one of the other things that you get from VVV, besides just the fact that Xdebug is there, is a tool called Webgrind. So when you use Xdebug, it can create these code profiles. And Webgrind actually allows you to view these code profiles in a nice format. And this is just a code profile. They actually have what they call code graphs. So it's a visual representation of all the functions that were called during a page load, and how many times, and in what order. So you see a box that represents the function that was called, and you see arrows that point to where that thing went from one function to the next. And you can see, I mean, it's usually massive. So it's not something you want to profile every page load that you do locally. But if you're trying to get to the bottom of a performance issue that is within PHP, it's a great way to go. So the next thing that you want to do is after you've kind of jumped into your debugger, you've stepped through the code, maybe found the issue. Obviously the next thing you want to do is fix it. So a few things related to fixing the issue. You want to make sure that you have truly isolated it. So you want to make sure that if you go to fix the issue in the way that you're thinking about fixing, you don't cause collateral damage. So if there's a way that you can refactor it so that it goes by the single responsibility principle that your function or method has got one thing that it's trying to do, it will help you in fixing this and or future bugs, but also setting up a regression test. So if you have the ability to do some sort of testing, whether it's PHP unit or maybe it's more of a front end bug and you want to do an acceptance test or something with code deception, you can do that. And that way, if somebody makes a change and breaks it again, you at least would pick it up automatically. And then finally, you want to make sure, obviously, that you've fixed the issue. So you want to go back and test it after you've made your fix and see that the issue is resolved. If it's obviously if it's not, then you'll want to go back and try again. So that is a very quick introduction. And I'm expecting probably more questions than I actually have a live demo. So I'm going to try for the live demo here and hopefully get some feedback from you guys in this debugging session here. So I'm going to see if I can switch screens real quick. Let's see. So I think I just need to turn off mirroring. There's my mouse. OK. Green just got real small. OK. So here is a, this is WP.com, so obviously. This is just my local development. WP.com technically redirects to WordPress.com, so I just decided to hijack it for local dev because it's short. So I use it, that's where my VVV primary development area lives. So basically, as you can see, there are two bugs. They could be the same bug. They could be different bugs. But nonetheless, there are bugs here that shouldn't be. So let's start by getting some input. If you were to start and figure out why this says bug and trying to get rid of it, where would you start? Edit post, hey, we got a bright one here. And lo and behold, we do have one bug in the post itself. You always got to weed out the user errors first. So we'll get rid of that one. Excellent. So now we only have one bug left. That was an easy one, data issue. And one thing that I've found with data issues is that if you ever find that you have a bug but it only is kind of isolated to one section or page on the site, a lot of times it's a data issue. Sometimes it's related to people entering in the wrong data and sometimes it's related to some weird processing or failure to migrate certain data. But that's usually a good indicator that you're dealing with a data issue as opposed to an actual code issue. So for example, if we left that in there, you'd find that Hello World has that in it. It would have two bugs, right? But if you go to any other posts, it would only have one bug. So that's how you know that would be a data issue. But now what we've got is a bug that we need to go and figure out. So if you were to step through the code line by line, where would be the best place to start? The template. So this is 2015. So I'm going to switch over to now just so you know, I've already technically clicked the start debugger in here. So it's actually the cookie is set. So we'll debug everything for us. So this is PHPStorm. And as of right now, we have the debugger not on. So this little button right here, if you just click that, it goes from red to green. And now it's actually listening for debugger connections. So what we're going to do is we're going to happen to WordPress content themes 2015. And if you know anything about 2015, ultimately the content is in these files here that are prefixed with content. And given that we are currently on a post, I believe. Yes, a post. So it's not a page. It's not a no content. It's not a link. It's not search. So it's got to be the fallback, which is content right here. So we're going to pop that open. And so when you take a look at this file, all we want to do is find where the content's output. So obviously this is where your domain knowledge, if you don't really understand enough about WordPress or the template hierarchy, and those kinds of things to be able to find where your starting point is, you want to make sure you learn enough about it to do that. But what we've got here is the content. So we can click right there. And that's going to set our break point on the content so we can step into that and see what's going on. So I'm going to switch back over here. I'm just going to reload this page. And now it's going to pause us right here in the code. So as you can see, the call stack over here is on the left. And it is actually going to show us all the files and functions that we've stepped through already. In the center, you've got your variables. So you can see the variables that are currently in scope. And since we're actually in a template, there's a bunch of global variables that are available. And then on the right over here, we're going to get rid of that, and that's not supposed to be there yet. There's watches, right? You can set watches. So at this point, what we really want to do is just step into the content function and figure out what's going on. So I've got my little shortcuts here. So I can step into that. So the first thing it's going to do is it's going to step us into the translation function because there are some things passed into the content that need to be translated. So I'm actually going to just step over that. So I could step into the translate, but I'm just going to skip by it. And then so there's the title. I don't really want to be in that, so I'm just going to get back out of that. So now we're in the content, right? So that's the function that's going to take place. And there's the get the content. And so this doesn't take forever. I'm going to nudge the movement through code towards the direction where I know the error is. But in this case, you could step through every single line and figure out what's going on. A lot of times when you do have bugs in WordPress is related to the fact that there are actions and filters. And when people use those or use those incorrectly, weird things can happen. So if you're in WordPress core, chances are, and you're stepping through that code, chances are that the problem actually isn't in WordPress core. Well, it is possible. If you're doing custom development and the issue came because of things that you created or other people on your team has created, chances are the issue is not in WordPress. So the most likely answer is to step in through the code and find places where you can tap into WordPress functionality via filters and actions and such. So we're going to intelligently step into this apply filters. So we're going to step into that. And so apply filters, being able to kind of debug through apply filters is kind of an art form to itself, I guess. There's a lot of stuff going on. I mean, hundreds and hundreds of actions and filters get registered. And at any given time, you could be looping through a lot. So what you can do, you can step through the code until you get to a point where you get into this do loop. And so right here, where it says callUserFunkArray, it's right before it executes some custom callback. So the callbacks that you normally register with addAction or addFilter, those are going to be called via this method here. So we can see that we're on the content tag. So it tells us what the name of the action or filter is that we're working with. And then, as you can see here, it's going to actually call the function, which is the callback function. So there's this v underscore array, which has the callback function and the number of accepted arguments. So what we're going to do is we're just going to take this function here. And we're just going to pull that on over here. So that's our callback function. We can span that out over there. So now we can actually see what our function is that's about to execute. And we can decide whether we really want to step into that or not. So run shortcode, and we'll step over that one. And then, so now we're in auto embed. So a lot of these are things that WordPress does, WP texturize, convert, smileys. So these are things that WordPress will do out of the box. So a lot of times, you don't want to step into those because, again, WordPress core chances are your problem doesn't necessarily lie with that. So we'll step through until we see something that looks suspicious. Aha, closure. There we go. So we have a callback here. That's a closure, accepts a parameter. Our debugger's not going to show it to us. So we're going to step into it. So we're going to step in. Ah, there we go. Content adds a bug at the beginning. So we found the issue. Now, what I'm actually going to do is figure out what I can do to get rid of this bug. So be nice if we could test to see if there's a way to get rid of the bug without actually having to change any code. So being able to test your hypothesis without actually changing code is a good way to go. No point in changing anything or in breaking anything unless you know for sure it'll work, right? So what I'm going to do is I'm going to set a break point right here on this if is true. Now, obviously we can tell that we have a callback here that's adding content, but we're going to pretend that the issue's a little bit more involved and just see what we can do to, you know, is there, is it really this thing, right? Like if we set is true to false, would the bug go away, right? So, and that should be the case. So what we're going to do is we're going to stop the debugger. We'll come back over here and reload the page. And so now, yeah, now we're at the point where it's actually doing this if is true. So one of the nice things about the debugger is that not only can you watch things, not only can you view the variables, but you can also actually edit the variables. So what I'm going to do is I'm going to find the variable is true, which is right here. And it's actually going to allow me to set the value, which I'm going to actually set to false. So when I do that, and then I step into the next line of code, it's actually not taking me into that if statement. So I'm just going to allow the code to finish running through, and I'm going to get rid of this, so it'll run all the way. And so now we can test and see, ah, our bug is gone, right? So we've managed to alter the flow of the code without actually editing the code to prove that our bug is now no longer there. So now, we know exactly what we need to do. Close all these files we don't need. So this is our bug, and if we could just change the value of is true to something else, our bug would go away. So we can set it to false, there we go. And then we can turn off our debugger and reload, and voila, so it's fixed. So that is some of the cool things that you can do with PHP debugging. So hopefully if you've not experienced this before, I would encourage you to go get this set up to where you can do that. And I am more than happy to help you get these things set up, whether it's your local dev environment, configuring X debug, setting up VVV, working with PHP Storm, actually debugging stuff. More than happy to do it, so if you catch me at any time, feel free to ask me about that. But, so we've got some time here, probably about 15 minutes or so I guess for questions or so. And then, so if, any questions? Yeah. So when you change it, as long as that variable is in scope, it will be set to whatever you set it to. So if it's a global variable like post, and you change the post ID, then you've changed it for essentially till something else comes along and overrides that. So, and one of the cool features that I did not demonstrate is that you can actually, let's say we have, so okay, well, we should probably set this to is false, right? So that the variable name matches up to this true value. And I'm gonna type in one hand here. There we go. So the cool thing that you can do here is that you also have the ability, let's say instead of actually changing the value of this, you wanted to actually force this code to run. So one of the things that you could do is you could come right here, get your debugger on, reload the page, okay? So you're at this point, and there's actually the ability to force step into a conditional. So I'm at this if clause, right? And false is false is false, so it's not gonna step in there if the value is false. But if you do a force step into, oops, it will actually jump you into that conditional, which it should have done. Let me see, make sure I have the right button. Force step into, yeah, so that one should, well, it worked earlier. Right, yeah, you can set the value so that the conditional matches and it goes into the code. And you should also be able to force it to go into that conditional regardless of the values. Right, exactly, yeah, so. Not quickly is it, can you commit those changes you made in that panel to files? Yeah, yeah, yeah, so PHP Storm, now technically I don't really use the version control capabilities of PHP Storm in PHP Storm. I actually use an external tool for that, just personal preference, but it will absolutely allow you to do that kind of thing. Why don't necessarily mean versioning, I just mean just quick command to like, you set that to false, if you wanted to commit that change to false, not necessarily commit like, you just wanted to change it, do you go and find the files and change it? When you say find the files and change it. You're changing it. So yeah, I mean, in this case, you know, Debugger spits me out into this file, right? As I step through it, it takes me to where that is. So I can change it here if I want to. I guess I meant when you changed the variable down at the bottom to at the beginning. Oh, down here. I got you, I got you. You would change that and that variable was set. You can change it from right there. So normally, yeah, normally the variables down there are all generated during runtime, so they could be completely different. At any given page load. Right. So it's not really smart enough to go back. Right, so it won't really do that, but yeah, typically, I mean, you could easily go to declaration, and I'll jump you to where that was originally defined, and then you could change it, but yeah. So any other questions? You said before the compute was already set in your browser. Right, yeah, yeah. So, yeah, so with the Ajax, as long as your debugger is running and you have a breakpoint set up, it doesn't matter whether it's an Ajax request, post a git, or whatever. Do you just have that set always listen first? Yeah, I mean, I generally, I generally when I'm working, I have some debugging I'm gonna end up doing at some point, and like I said, for me on my machine, it doesn't slow me down at all. So I usually just leave it on, but usually in the browser bar here, you know, you can hit stop debugger and it'll unset the cookie. So you can stop it from the browser side or from the PHP storm side. And those browser requests you got from the page? Right, from that webpage. So, but yeah, usually just once I click start debugger, that cookie is just kind of permanently set until I turn it off. And since it's just a cookie, I mean the cookie's not slowing anything down. So I usually just leave it on and then when I wanna turn off the debugger, got a little shortcut that'll turn it on and off up there. So, makes it real quick. Yeah, I'm just curious a little bit about the VVV cluster, what's the, what are that? Right, so VVV kind of started out as a 10-up project where they were creating a virtual machine for WordPress development. So, now it's kind of a standalone project and it is kind of maintained by a lot of people within WordPress because that's what it does. Yeah, it actually comes with, I think, four different copies of WordPress out of the box. Three of them are more if you're gonna be doing like WordPress core type development. And one is for general use, you know, throw a plugin, throw a theme in there, start creating and do whatever you want. So you could, yeah, there is, I think, it's a local.wordpress.dev, so you can actually go to that. Matter of fact, once you get VVV set up, it creates this really simple shortcut, VVV.dev, which gives you links to all the things that WordPress has, or that VVV has out of the box. So this local.wordpress.dev is, you know, the most recent stable version of WordPress, which I threw some stuff that doesn't work on there. So yeah, you get that out of the box and a few other copies, so if you wanted to do some WordPress core work, you could as well and have some of the built systems and things that go with that. But it does have a link to the VVV repository. It comes with PHP MyAdmin out of the box, so you can jump into that. It's got PHP MIMcachedAdmin, UpcachedStatus, things that you might be less likely to use, but the Webgrind, which is that tool I was telling you about, where it will allow you to take your code profiles and view them, and also potentially view them as call graphs, and then it also has your PHP Info here as well. So again, if you're not using VVV and you have to go set up Xdebug manually, let's say you're using WAMP or something like that, you could just get your PHP Info file, copy that into the Xdebug wizard, it'll give you step-by-step instructions on setting it up, and then usually it works pretty well without too much confusion, so. Any other questions? There's another add-on. Yeah, yeah, yeah. So yeah, yeah, the nice thing is with VVV, there's, if you drop in a few configuration files and you were to essentially create a new directory in the WWW directory in the NVVV, it'll allow you to actually add your own projects, right? So you could add as many projects as you need to, but there's, you can manually set it up or there's other tools that you can use that will allow you to quickly spin up a new project in VVV, and then the nice thing is what you can do is you can have a separate repository for that project, and those configuration files for VVV, which is like three files. They'll actually live in that repository, and so then you can just say clone this into VVV to anybody, and they can actually have the exact same setup that you've got without any hassle, so. Besides your debugging, is that one that you wrote? You saw it pretty, that thing that you wrote. One with two bugs on it, so. Oh, this thing here, which is, yeah. Yeah, hello world, that's something that you wrote. So, well, no, this is actually, this is default WordPress content, technically, so it's just the, say what? You put the two bugs in it. Yeah, I put the, yeah, I added it and added the bug. I guess what I'm getting at now, this is a remote site, just like you was looking at for the browser, can you get into the PHP code on a site that you do not code? You can. With the debugger. You can. There is a prerequisite that you actually need to have XD bug on the remote server to be able to do that, but you can do remote debugging, so you can actually, if you have a production server with XD bug on it, then you can actually use PHP Storm to remote debug through your code. Doesn't that serve to be your server? No. Unless somebody stuck it on there for you. Right, exactly. Which is, you know. Yeah, that's a great question for you. So it's, yeah, it's nice. So being able to do remote debugging is pretty cool, but. So you can't look at Facebook code or anything? No, no, no, yeah. I mean, they would obviously have to, have to have some of these things set up, and you would have to have SSH access to whatever it is that you wanted to work with, but with those two things, yeah, you can, you can remote debug, so. Any other questions? So, yeah, so the question being, is there a good tool or way of doing debugging performance issues with MySQL, basically, right? So, or I guess, MariaDB or whatever it is you're using. So, yeah, there is. So, at the simple to get started level, there's a few plugins, and actually if the link for the slides that I sent out on Twitter right before the talk, that actually takes you to my website, and it has not just the slideshow, but some additional links as well. So, there's a couple of plugins there that will actually surface within WordPress, the queries, and allow you to kind of analyze them on any given page load. It just kind of will always log them if you have that plugin in there. But you can, I use a tool for, I guess it's, they may have a Windows version, I don't know, but at least on Mac, I use a tool called Navicat for MySQL. And so, what this allows me to do is to, for example, if I go into VVV, I can see all the databases that I have in there, and then I can pop open any one of those and actually look at everything, but it also allows me to actually write a query. Yep, there we go. So, I can create a new query, and actually I can actually write my own query and run it, and it will tell me how long it took to run and all that kind of stuff. The thing you have to be aware of when you're doing database performance. So, tools like this, and you run a query, and you run that same query again, MySQL will actually cache the query, so you have to flush the cache to actually get results that aren't skewed. So, you have to be careful about that, but yeah, tools like this can allow you to play around with the query and add an explain or whatever to it and allow you to debug through that. But yeah, a lot of times, if you have a WP query or something where the SQL is generated and you don't necessarily know what that is, what I'll do is I'll take the debugger and I'll step through the code until I get to a point where that query is now available as a variable value, and I'll copy that, put it in here, and see what's actually happening and how if I change this or add that, will my results be different? Or maybe if I, you know, if there's a way I could optimize the query somehow, then I can go back and add a filter in WP query that would optimize it or change the outcome. So. And you plug it in here, do you have to clear your cache after this? So, well, MySQL itself has a cache, right? So you actually have, there's a function in MySQL that allow you to flush the cache, so. I'd have to Google it, I can't remember off the top of my head, but. I hope I have a very useful. So, but yeah, it's an actual MySQL query that you would run to flush the cache, so. So this is, yeah, if you're on Windows, there's something called Heidi SQL, which is free, and it does basically the same thing. There's MySQL tool bench, there's a bunch of them, some of them are open source, some of them are paid. So, so yeah, this is one that I found that works well for me, so. For Windows, yeah, it was Heidi SQL. H, I'm really bad at spelling, especially in front of people. I could write it down, no problem. Yeah, H-E-I-D-I, right, yeah. So, any other questions? So, yeah, if anybody wants help getting set up with actual interactive debugging, just let me know. I'll be around, so I'm always happy to answer questions or help out. So, appreciate it.