 Hey, everybody, that was a great introduction that I wrote. So, you know, I am David Dashifin-Kees. My pronouns are they and them. Georgetown University, all that was said. I'm also the president of the board for the WP campus organization, a professional organization for people in higher education that are also working with WordPress. So if I know a few folks here that I've seen from WP campus. So if you are in higher ed and you haven't bumped into us before, feel free to track me down afterwards. I didn't plan it, but I'm actually repping with our official backpack. So we're here to talk about Composer. Composer is a dependency management tool for PHP. How many people have used dependency managers, whether they're like NPM, Bundler for Ruby, Composer just by show of hands? Cool, if you're listening to the talk, that was about the entirety of the room. How many people have used Composer specifically? All right, that's about the same, maybe about 10% less, but still most of the room. How about Composer with WordPress? Okay, so that's a little bit of an, even more of a drop off, maybe 50 to 60% of the room. And now the last question is, how many people here are doing that, but also using an additional boiler plate solution, something like Bedrock? All right, so that's the last question there was maybe 10 people. So it sounds like we might have a lot of expertise in the room and that's cool. I will try to move through the rest slides as rapidly as I can while also trying to be conscious of the fact that something like 40 to 50% of the room doesn't really know it, maybe as much as some of the rest of us. I mentioned the keyword Bedrock. I don't wanna call you up, but is Gary McPherson in the room? Yeah, I thought I recognized you from the photograph, but I didn't wanna be like that guy. Tomorrow, Saturday afternoon, modern WordPress development as a workshop. Bedrock was a keyword in your description, right? Yeah, so if you see this talk and you're like, oh, that sounds really interesting, but like this was a half an hour, how do I do this? Go to the workshop tomorrow and you'll learn. Yeah. So some basic statistics. Why did we at Georgetown University decide to try to do something with Composer? As you can see from the screen, and I got a look because my tiny little notes are very small and that's much bigger. We have two code bases, one we call DP, the other one we call NG. The DP code base is much bigger. It clocks in at orders of magnitude larger than NextGen. Almost 19,000 files, but like almost 90% of those files are third party code. Their WordPress core, their plugins, their themes, well, not really themes. They're custom, the whole thing's a custom theme, but like their plugins like advanced custom fields, Yoast plugins, things like that, they just get all bundled up into that one repo and then they have to just be there. On the upside, it does mean that updating plugins and things of that sort is very straightforward because you just log in to the site on a local environment, update them through the dashboard and then get, add, commit and push back to, to the repository and you've updated your plugins. It's very straightforward, but it means you've got to maintain a whole bunch of other people's code. Just this week, we were testing and practicing the upgrade to 6.3 for WordPress and it was a couple of thousand files that got tweaked in the repo and GitHub was like, no, you don't get to look at this PR. It's, you don't have enough RAM in the world to load this on your machine. And so I just was like, yeah, it's not my code approved. It's like, it's, I mean, it's fine, but it's not great. So when a couple of years ago, we decided to work on getting a different sort of process going and we wanted to use Composer because Composer, which is Next Gen, can see NG as for Next Gen, which you can, you could read on the screen or on the slides later, if you're just listening, the much smaller, there's like 30 something files and only one of them is not ours. And that one is a pro plugin that just doesn't really quite work with Composer. And we can talk a little bit about that in a minute. Much easier to maintain. If we have to make a change to our build, suddenly you can read and code review the PR as opposed to the other one where GitHub's just like, you get to see the first couple thousand files and then that's it. Thanks though. And yeah, it's worked out really well for us. So let's talk about how I did it. This is an example of what you might have in such a repo. This is for dashiff.com, my own website. I didn't want to try to figure out if or how I could get the approval from Georgetown to make sure I could show our own repos. But my own stuff, I can just make them public. So eventually there will be links to all of this in the slides and on the screen via QR code. But that's it. That is the whole repo. And realistically, the get ignore is just a get ignore. It's important, but it's not maybe really necessary when you've only got two other files in your repo. And the .lock file, if you've used PacketManager and most people in the room did indicate they've used them, you almost always get a lock file of some kind. It may not always be called that, but the goal of that file is to say, these are the versions that are currently set up for this installation. And so until you update that lock file, you will lock in specific versions. So I committed mine. Sometimes you don't, if you just wanna be constantly at the most recent bleeding edge, you don't really need it. And so get ignore in composer lock, maybe not as important. The one file to rule them all is that composer JSON. And that's more or less where we're gonna be focusing on for the next 15 or 20 minutes. The QR code on this screen, or if you are listening later or have the slides there, you can actually click. I think you can click the QR code, I set it up. So that will take you to the full schema for composer JSON. Just like NPM, there is a structure to how you put together your composer JSON file. There is a lot of options to composer, many of which I have no idea what they do, because I haven't had to figure it out yet. But the ones that I summarized on the screen here are the ones that are more important for us at Georgetown. And they're the ones that I have more frequently encountered while doing this sort of work under other circumstances. So basic information, name, description type, license authors, and rarely version. Because most of the time we're gonna be putting this back into some kind of version control system in the currently frequently get. Composer will look at the tags on that repo or the released version numbers on the repo and figure out what version it should be from the repository itself. That's usually better only because if you put the version in your composer JSON, my understanding is that's the version it's going to use even if your tags and other parts of your repository are different. So just don't put a version in the file. Then it will rely on the tags for the repo and when you release 6.3.1 for a plugin and yet you forget to go back to your composer JSON and update the version number there. Oh no you didn't, it's not there at all. You can just worry about the tags. And since I hope, I suspect that many of us are using some kind of tagging, probably semantic versioning of some kind to do that work, well then it's already in our workflow. There's not another step to remember. The dependencies that we'll install are separated into require and require dev. If you're more familiar with this world from JavaScript and tools like NPM, most, in my experience at least, most of the things that we require there are actually in the require dev category because we're bundling them up with Webpack or Gulp or Parcel or whatever tool you wanna use to build your installable browser ready JavaScript assets. PHP works differently. PHP is gonna need probably all of that code to go to the server if your site's relying on it, which means you're gonna see a lot more things are in require in a composer JSON than are in require dev. What ends up in require dev for meme is most likely debugging. This or that thing that I wanna use to lexically analyze my PHP to make sure I'm not making a very simple syntactical error or a very simple logic error that my IDE might not have found, maybe this other tool does. Those are the sorts of things that as a project, you don't need that code for production. You need that code in your local environment. That's what you'll see in require dev. And then the last four there, three, four, five, and six, non-standard repositories. Composer has its own standard repository. It's at packageist.org, P-A-C-K-I-G-S-T, something like that, I can't spell. Packagist.org is there automatically. And that's a public resource that anybody can submit things to, even things like WordPress plugins if you wanted to. And then people can just install them without needing a non-standard repository. But if you wanna plug in or a theme from the WordPress.org repository, that's not gonna be there. Luckily, I'll show you in a second how you can get those in as well. Config information, there's gonna be a variety of things that you might need to set up to configure the site in the way that you want to. And so that all goes there. Custom scripts, I almost always have a reset script that deletes everything except for the one file to rule them all, just like something's weird, delete it all, start from a fresh install and keep going from there. And then I put extra in quotes down to number six, because for our purposes today, it's not extra. Composer calls it extra, it's not. And you'll see why in a second. There's also the possibility that you might wanna use the auto-loader. This is a PHP object-oriented piece of technology in Composer. It's not frequently needed in WordPress, except suddenly you might find it useful. So I recommend checking it out. If you haven't used the PSR4 is the acronym. I don't remember what PSR stands for off the top of my head. They are, there's a PHP interoperability group that is out there working on standards for PHP and the auto-loader is one of them. And that's baked into Composer. So if you're in a world where you're like, I really am tired of writing a whole bunch of require statements into a single file to grab all of my objects and all of my other stuff and put them into the memory for my application, for my WordPress site, the auto-loader might help you out, but it's beyond the scope of the rest of the talk. All right, where's my mouse? Where it is, there we go. It's code time, well, JSON time. The three QR codes on the screen will lead you to the Composer JSON for the site that was just on the screen in a screenshot, the Composer JSON for a theme and one for a plugin. They will also be on the screen in the slides so that we can talk about them here today. But if you want to find them again later, feel free to scan the QR codes. I just checked and they're all public repos in GitHub. So you can look at them and take a look at what's going on there. The theme is a playground theme. It does nothing. I don't even think I'm using it on an actual site. It's just my sort of like, let's mess around with the theme theme. And the plugin is one I wrote a while ago, so it's not probably really in use anymore, but it was a good example. I mentioned basic information. This is what it might look like. Just like the package JSON for NPM, you're gonna see a big opening bracket and then followed by properties in a JSON object. So name, field, value pairs. They can be kind of anything. There's a bunch of, the one to talk about here though is type. In this case, type is WordPress project. Composer has four built-in types. They are library project, meta project, and Composer plugin. And I have no idea what a meta project is, but the other three are a little bit easier to understand. Anything other than that, Composer at its baseline level has no idea what you're talking about. So I just put WordPress project on my sort of like root project level Composer install file because that helps me remember what this is. If I get here and I'm like, what is this random JSON file on my computer, I can look at the type and see it. Oh, it's a WordPress project. That helps. Because Composer doesn't know that as a keyword, it won't do anything special. So we will eventually have to get it to understand things like a theme and a plugin. And that's where we get to that quote unquote extra property. And that's where we're gonna tell it, how to know what a theme and a plugin are. Requirements, since almost everybody in the room raised their hands, this probably looks somewhat familiar. It's just a list of things that you can install into a website. Many of them are mine because this is my website. But other things aren't. This is not the exact list. If anybody brought up the Composer JSON file, you will notice that this is a little different. And that's because Advanced Custom Fields was too long to fit into one of the columns on the screen. So I just removed that one, so they fit. But in under normal circumstances, so this is actually a non-installable list of packages, but that's okay. If you're familiar with semantic versioning, the values for these object properties look probably pretty similar to you. The one I want you to keep your eye on real quick, although actually since most of you in the room, the most of you in the room probably will get this, but just in case you're listening later on, keep your eye on that timber library version number. We'll talk about that again in a second. Here's where things get a little bit more interesting. Repositories. You'll remember that I mentioned packages.org. There's also wpackages.org. And you can see on this screen or you can read it on the slide that the first one there is wpackages.org as a composer repository. That repository regularly, I think hourly, scans the .org themes and plugins, grabs them, sticks them elsewhere, and adds a composer JSON file for them. If you're gonna need or want to install standard themes and plugins this way, that's how you do it. You add wpackages.org and then on the requirements page, the list at the bottom of the second column all begin with wpackages plugin or wpackages theme as the vendor of the dependency followed by the name of the theme or the plugin. And so if without specifying that these are gonna be found at wpackages, composer won't find them. So do that. Add wpackages to your composer file. The other three examples on the repository screens are just an example of how you could specify a repository on GitHub. Some of the things that I've added to the requirements page are actually on packages.org because I use them in a bunch of different places. So it's easier to just be able to install them without having to list them all by hand. But if you're installing something that's not frequently used or it's a package just for this site, you can just specify the git address for your information and it will happily install it. Composer will just hit that link and say, oh, okay, this must be important. And when it finds a name it doesn't recognize, it will look for the composer JSON file at all of these links and use that to discover packages that it otherwise couldn't. Custom scripts I mentioned, these are up to you. My example on the screen, there are, or the QR code on the screen links to the composer list of hooks that you can use by default, like run this right after you install or run this right after you clear cache. There's a couple of maybe eight or nine, I think different hooks that you can use right out of the bat. You can also specify something custom. So reset is what I mentioned earlier. It's literally just RM-RF, public HTML and the lock file. That way everything that this installs gets blown away and I get to start fresh and grab everything else. But the first one, the post update command will automatically run that copy. That's just a command line copy to move something out of a folder and into the MU plugins area to load the rest of my MU plugins. So you can put a lot of stuff down here that can just sort of help do repetitive tasks. Initial configuration, this is a slide that I'm gonna move on from relatively rapidly. It's here so that you all can review it later. Two that I like to call out are the optimize auto loader. If you're using the auto loader, why not get an optimized one? Maybe it only saves a couple of nanoseconds, but like sure, it feels better to have an optimized one. It's nice, it's pleasant. The other one that I really like is sort packages. If you're installing things from the command line, they do not show up in alphabetical order unless you have that in your file. I don't know why. Why should I have to write that everywhere just to get my packages in alphabetical order? I don't know, but you do. So sort packages, true. Then if you install something from the command line, it shows up in the right place and you can find it again later without having to up and down look through your whole list. The other one to call out right here is vendor. Vendor is composer's version of node modules. The node modules folder, I suspect, although I never have, I suspect you can configure where it goes if you wanted to in npm. For composer, you can absolutely move your vendor folder. In this case, I like, although I realized while I was working on these slides that it's probably unnecessary, I kind of like just sticking it in WP content. It's polite. It seems like this is stuff, it's not gonna be the plugins and themes. We'll see how those go into the right place in a second. But the other stuff that they might rely on, it feels right to put it there. But you could specify that it should go into WP includes. You could specify that it goes right at the root of the site or even one level above the site because PHP will happily include the files from wherever you have access to if you're in like a shared hosting environment. You don't have to put it even inside the discoverable public website area. And here's the important one. The quote unquote extra information. Here is where you specify how WordPress gets set up. The top WordPress installer, public HTML for me. Like I said, I wanna sort of, I guess Cpanel has a new name that I learned today at lunch, but I don't know what it is yet because I just learned it at lunch. But I'm on a Cpanel sort of shared hosting environment for my own personal website. And so public HTML is just the folder into which the web files go. So I tell it to put WordPress in the folder to which the web files go. But then after that, you can specify the paths for plugins, themes, drop-ins and MU plugins. And you can specify the locations just like you usually would. So plugins go in the plugins folder, themes go into themes folder. It feels fantastic. This is a big difference between what we did at Georgetown and something like Bedrock. Bedrock wanted to create a structure for the WordPress ecosystem in that build, in that boilerplate that appeared a little bit closer to other PHP frameworks. So when you use Bedrock, you don't get the exact same folder structure that you get if you just download the .org zip and unzip it. Or at least that was the case in 2019, which was sadly the last time I really looked at Bedrock. So I could be wrong there. I don't know, we'll learn from Gary. But the goal we had was to let somebody hit the site and see it as if it were the .org zip file. And so you can, if you've used the .org zip file, and I suspect many of us have, you'll recognize those paths. Prior to Composer 2, this didn't work. So if you install Composer, make sure you're using Composer 2. I don't even know if they let you install version one anymore, because it's been about 2019 or 2020 was when version two came out. Prior to version two, it might delete folders if it hit matches. And so things like boilerplate moved things around so that you wouldn't delete the WP content folder when you then came by and installed WordPress, which already had a WP content folder in its zip file. Composer 2, the current version of Composer, doesn't do that. So this structure here, whether Composer grabs a plugin first or WordPress core flirts first, you will not delete the folders when you encounter a copy. It just merges the data in the same way that copy process by the operating file systems usually do. Very quickly, this is the way a theme looks, very familiar, except look at the type. It's a WordPress theme. If you don't tell Composer this type or WordPress plugin or WordPress drop-in, you can see what those types are on the extra slide, in the green on the screen or in the array of data underneath the properties. The type of WordPress plugin is listed. The Composer installer plugin that will happen when you specify that you want to install WordPress, and I'll specify that link in two slides. The will tell Composer what to do here. If you're trying to install a theme that you've written yourself and you don't put the type of WordPress theme in your file, it won't be a theme. It'll just show up in your vendor folder so it'll happily download, but it won't be in the right place. And so when you go to the Appearances tab in the dashboard, it won't be listed there. Similarly, oh, actually, I told you to look at the Timber library. Just like Node, if you have a semantic version here in the file, it specifies it once Timber of something equivalent to 1.19. The other file wanted 1.22 something. Those are compatible. There's still no one branch, 1.19 versus 1.22, that's okay. Composer will do the same thing that NPM does in that case to figure out the best version to install based on the requirements that it receives, not just from the root level Composer JSON, but from all of the JSON files for each of the dependencies that it installs. Finally, a plugin, same idea. The only difference here being that the type is now WordPress plugin. Again, same rule. If you have a plugin that you want to install, if you don't tell it that it's a plugin, it'll go into the wrong place. So the summary of all of that. Specify the location for core plugins and themes in the extra property. The extra property is not extra for us. You want to include wpackages.org in the repository from which to pull plugins and themes. And this is the key one. I forgot to mention this back in the repository slides, but if you look back to that slide later on, if you read it out to yourself later on, you will see, in this case, I use a repository maintained by John P. Block, which is conveniently called WordPress. I don't remember the frequency with which that repo is updated. I think it's 15 minutes or an hour or something. But essentially, on a fairly regular basis, that repo uses a script to go out and look at the .org repository and see if there is an update. And if there is an update, it just gets pulled into GitHub. And then you can just list WordPress itself as a dependency for your project. That way, you don't have to download the zip file anymore and unzip it into a folder. You don't have to worry about it. All you have to do is go to your composer JSON file and update from, say, 6.2.2 to 6.3 and run an install. And it'll kind of just make the installation. So by specifying WordPress as a dependency, it allows you to not even have to worry about maintaining any copy of WordPress Core in your own repos. There are other ways to get this done. You can write a script that hits the web and W gets the zip file and unzips it into the right location. You can do all of that. But let composer do it for you. And then finally, the big takeaway is remember to specify your types. If you don't specify types, you don't, in the end of it all, get a website. Upsides and downsides. The real upside is if you're in a world where you're not really using something like Docker or other sort of virtualized containers, this is a good way to maintain the same site across multiple machines. At Georgetown, we half intentionally and half just based on preference don't all use the same stack for our local development environments. On the one hand, it's annoying. On the other hand, it also means that like I'm on Apache, someone else is on Nginx. And we get a really, we get an opportunity to test our sites in a couple of different, slightly different local environments before it ends up online. And we can maybe catch a few things that otherwise we wouldn't. You can't tell because my laptop is sort of hidden. And if of course you're just listening to this, you wouldn't know it as well. But I'm on a PC, some of the other devs, both of the other devs are on Macs. So we get a little bit of cross-platform testing that way as well. So we need to have the same website across all of those environments, even if the environments themselves might be slightly different. Composer lets us do that. As long as we're all using the same JSON file and we're all running Composer install to get the code when we build the site, the site's the same. Semantic versioning is really nice. We've run into a limited number of cases where we've wanted to continue development on a theme or a plugin at Georgetown. But we weren't ready to send it to prod for one reason or another. So we can leave the version number in the roots Composer file at, just making one up like, I don't know, 5.0. There might already be a 5.1 or a 5.2 located on GitHub. But as long as we specify 5.0 in the JSON file, it won't bother to install the newer versions until we're ready to deliver those newer versions to the web, especially if there's some sort of a requirement that we've got a date on which it's gonna be released or something along those lines. This is a really good way to be able to not halt development on a dependency just because you're not ready to send it to prod. Smaller repos, like I said, we chunked out. We went from 18,440 files in our repo to 36. It's a slight reduction. And at Georgetown, at least, we separated our repos. The different plugins that we write, there's about 30 different repos. Three themes in the rest, I think, are plugins, or MU or otherwise. That allows us to have really small, self-contained, focused chunks of code in those repositories. We don't have to have one giant repository with 19,000 files in it and search in the right folders to find the plugin we need to update. We can just go to the repository for that plugin and update it in its own repository. And that's really, really nice. There are some downsides. It's another tool to maintain. You gotta update Composer. You are grabbing packages from the internet, which means you're open to supply chain attacks. We've bumped into them a couple of times through NPM where somebody does like a typo squatting attack where they name their malicious package so similar to the name of a non-malicious package that somebody goofs and installs the wrong one. And that quick, there's some kind of malicious code that starts to sort of circulate until the node folks realize the problem and solve it. You could run into the same thing here. Off the top of my head, don't remember that happening for Composer, but you do have to be careful to not spell things wrong. You'd have to be careful to vet the things you wanna install, et cetera, et cetera. You can run into some tight binding relationships between repos. If you install a bunch of plugins and themes, but not WordPress, it won't work. If you control WordPress without the themes and plugins, it kinda works, but there's some really tight connections between these different repositories that you're installing. And so on some level, cognitively, it might be better to have them all in one shared repo because then you at least know that if you pass around that repo, you've got everything. Whereas in this case, if you, for some reason, forget to install something or if you have the wrong version of something in your local Composer file, maybe you haven't merged from the main branch in a little while, something could go wrong when you install, when you get a little mixed up. Luckily, you're in Git, so just merge the main branch and you're probably gonna solve the problem. The last problem, though, is just like sometimes Git gets confused, Composer does as well, but luckily clearing the Composer cache usually, usually solves it. So we're gonna try really quickly. Let me make this a little bit larger. And I need to move it over here. If you're just listening, oh, no, no. Oh, you know what I can do? I can try to duplicate. So I'm not gonna be able to look over my shoulder at the screen over there and type at the same time. But if I make the two screens the same, look at that. So if you're just listening to this, this will not be very impressive, I apologize. On the screen now, though, is my IDE. I'm a JetBrains user personally, so that is what we're looking at. And you can see that I've already run ComposerReset and that was just for convenience. All I'm gonna do real quick is type Composer, install. And when I click Enter, it's gonna start doing things and hopefully this works. It's always fun when you run a demo in the middle of a room. I'm also, this is basically it. Once this is, this can do its own thing. Oh, look at that, it's already doing it. That was pretty fast, actually. So on the screen now, it's installing a bunch of things, downloading a bunch of things, installing from WPackagist. Composer goes by fast enough that it is probably not useful for me to read it to you all, I apologize. We have one person who uses a screen reader in the office. He has tried this once and said that Composer's output is accessible in that it is all read to you from a screen reader. However, it is all read to you from the screen reader. So it's usually too much information very rapidly, especially the little progress bar, just keeps saying percentages over and over again, which is not super useful. But yeah, it's already done. And the proof that it's already done is that in the project window here in the IDE, if I open up the public HTML folder, which did not previously exist, you see WordPress core. It's that simple. Once you get it all set up and hopefully the example in the slide and the workshop tomorrow will help you get it set up if this looked intriguing to you, you just get a website at the end of it and all you need is one file. Let me get IDE out of the way, switch to questions, slide and find. There we go. Now that I'm duplicating, it's harder to switch from slide to slide. So questions, any thoughts, concerns, ideas? There is a microphone here in the middle of the room. I've got one as well and did you still have one? Oh, hold on. Okay, I think we're gonna try to move around the room a little bit. I got this guy over here. I saw this hand first. I'm just gonna run around and I'm off the camera. It's fun. Just quickly, just wondering if it's possible to restrict plugins to require a certain version of WordPress. So I was trying to figure out, trying to imagine how that would work. That's a good question. I don't know the answer to it. I do know that composer will respect a PHP specification. So in some of those composer JSONs, I think I said PHP greater than seven four or a PHP greater than or equal to eight. So there is a way in the world of composer to do that. What I don't know is if the composer plugin that will automatically be installed when you specify that John P. Block WordPress repo, the first time you want to install it will ask you, are you sure you wanna install WordPress? And then you say yes, because it's what we're here for. I don't know if that plugin though has the way to say like WordPress greater than or equal to 6.2. I'll try to find out and it'll be an experience. Yeah. Saw the gentleman back here next. Might have missed something. Where's the data? The data? Yeah. All of that stuff because you're not hitting the database. Correct. This is just PHP code. If you have a database that you need to install as well, you'll need to have like a dot SQL file or some sort of database dump that you can then import. So like at Georgetown, we have our development team. We just sort of go to one of the websites that we're currently working with and just export its database and then pull it into our local database. You're correct. That part, the data for the site won't be there. However, if it's just like a hobby project or if you're installing a fresh version of WordPress, once you've got everything installed, you can just go to the normal five minute install for WordPress and it will create the databases and all that jazz like it normally would. There's also not a WP config file in any of the repos because you don't want your database passwords and things like that to end up in GitHub. That would be bad. So we've probably all done it but usually GitHub's good. Like a couple of times when I've really messed up and put an API key in GitHub, it's like, oh, you put an API key, we've deleted your repo or whatever it does. So yeah, so there are a few things left over as an exercise for others to set up the config file, to set up your database, those sorts of things are outside the scope of what composer can handle. Theoretically, you could put a database dump of like testing data in the repo and then you'd have two files and then the title wouldn't work. So yeah. Hey, oh, go ahead. First of all, great talk though, I appreciate it. Quick question. So when you manage WordPress plugins in the composer file as opposed to directly adding them in the admin, how do you make sure the team members don't accidentally log into WP admin and update the plugins there as opposed to in the composer file? That's a roles and capabilities question. The easiest way to do it is to say, just to take away the managed plugins capability from all of your users and then they can't. Is that something that you recommend? I definitely recommend that. I recommend that nobody gets, I recommend you take away all capabilities from all users. That's the only way to be sure. No, it's the nuke the site from orbit solution. No, seriously though, at a prior job, we used to install all WordPress as multi sites. They only ran one site, but multi site moves the managed plugins and themes capability up to super user. And so all you can make people admins then and then they can't do plugins anyway. So that is another solution. So you don't actually have to write code to take away the capability, just make it a multi site of one site. And again, they don't get to do it. For Georgetown, our hosting service doesn't allow the hosting provider blocks the ability to write files on prod, so they also can't. Now theoretically, they could still do it at non-prod staging sites, but we just, we don't advertise that capability. And then even if somebody did it for us in a professional environment, the next time we built and pushed the next version of the sites, whatever they changed would be overwritten anyway. Coming to you again. Over here, okay, go ahead. Yes, so I noticed that your composer JSON file, you're dropping a one root above the WordPress core root. And I've also seen ones where composer JSON was at the same level as say the WP content. I've also seen them with composer JSON in the WP content folder. I was just wondering how you decided that was where you wanted to go? I like putting files that might reveal possible security breaches in a place that the web won't find them. And the easiest way to do that is to make sure they're not on the web. So the same way that WordPress can put WP config one level up from the index.php and it'll just find it. I usually put like my composer JSON there as well. While I was doing these slides, I realized I should put the whole vendor folder there too. Cause theoretically there's probably a readme file in almost all of those packages. And if somebody's really, really savvy and somehow guesses where I've put the vendor folder and then just checks for all of these readme files, they would then suddenly know what I've installed. And if there's a known vulnerability, it's like, all right, okay, so it's a lot of ifs. But if I wanted to be really sure, and I think I'm gonna start doing this, I'm just gonna put the vendor folder up there too. PHP will happily include it. PHP doesn't care as long as the interpreter has access to it, which in this case would be, it's in the home directory for my account on my shared hosting service. It'll be a little bit different depending on the host for a professional environment. On, for our host, the folder is named web instead of public HTML. But we could probably put that stuff next to the web folder and PHP will include it. But the, a person browsing the website will no longer be able to guess a URL to a readme file or a changelog file and somehow get data that I don't want them to. Hey, so actually let's ask a question around how you're handling your deployment. So obviously with Composer, there are a change in how we push. If you wanna know how to do it tomorrow, there's a session tomorrow where you might learn about it. But I'm curious about how you manage it at Georgetown handling deployments to your production environment. Yeah, we have scripted that ourselves, more or less. So we utilize a hosting provider that provides a command line environment that we can install and utilize for most of our deployment needs. So for Georgetown, it's very scripted, very routinized. And that's because we're pushing to 25 or 30 actual web accounts, one of which is then a multi-site that has 400 plus sites on it. So like we need to get this to a science so that we don't have to do it by hand. For my own site, I have to pee. For a while I was doing get push hooks, so I would push to a remote repo on my shared hosting environment, which would have a post-receive hook that would check the repo out and put it in the right place. But then I kept deleting things that weren't in the repo and that's annoying for the folks that I was building demos for and stuff like that. It's been a long time since I did any sort of freelancing or site hustling, so it's not as important to me anymore for my own personal website. So I usually just build locally and then FTP because it's dashfin.com. It's got like four pages and like three of them are about my shadow run games on Sundays, so it's really not that important. I think we have time for one more, time check. Are we good for one more? Three minutes, cool. Thank you. You said that you're updating the plugins from Composer, right? But what I experienced in the past when I updated the plugin in the dashboard, especially WooCommerce, is ask me the question if I would like to update the database because a new version has some new tables for new structure. How does it happen when you update the plugins through the Composer? How to recognize that it's need to update the database as well? Yeah, that actually happens the exact same way. When you update the PHP code, when the next time you log into the WordPress dashboard, you'll see the same notice at the top of the screen that says you want to update the database. That'll happen. I think the 6.3 release for WordPress required a database upgrade. I don't know for sure because we haven't done it yet at work. It's on the clock. We're testing everything and going through the process of making sure that the new version doesn't cause any problems. And part of that process will eventually be clicking the button at the top to update the database, that sort of thing. Sounds good. Thank you so much. Short one from the last group over here maybe? We got every other part of the room except way over here. Anybody? No, come on. Somebody asked a general question, not about the topic at hand. Anything? Yes! You know me. What is your favorite game? It's giving you something fun. Tabletop game, video games. Any game? Pick one of each category. Tabletop game is Shadowrun. I mentioned it earlier. I've been running the same game of Shadowrun within the same sort of shard of the Shadowrun meta plot since 2001. I've had the same players at my table since 2008. And somehow we've made this work. We don't know how. I did cancel Sunday though because I'm gonna be really tired. But so yeah, Shadowrun for me is a tabletop experience. Video games harder. As I mentioned in my bio, I'm for the Alliance. I've been a World of Warcraft player and I have the honor of it one time being a computer programmer who was in their 30s living in their mother's placement playing World of Warcraft. And so I am the stereotype they warned you about. So that's probably still my favorite. I've gotten sort of sucked into Diablo 4 though. So I'm basically a Blizzard fan person at this point, I think. So yeah, cool. I think that's all the time we have. I saw one hand go up here from over here in the peripheral vision. So I'll be wandering about in the hallways. You can find me. I think I'm the only person in a vest and a tie. So I'm pretty easy to find. Thank you all for coming. I hope this was useful.