 Right, the lady has officially given us the go ahead to start. I've gotten so used to waiting to hear the recording in progress sound. So welcome everybody who is joining us today. While you are joining. If you would like to code along with me there is a plugin that we're going to be working on, as well as a theme that we're going to be working on some pasting those in the chat very quickly. The theme is actually just a child theme of the 2023 theme. So you will need the 2023 theme installed on your multi site install as well. If you want to follow along. I'm going to be trying to cover everything I have planned for today. It's quite a lot to cover in a short space of time but we'll chat about that as we go through. While you are joining us if you would like to please let us know in the chat we are joining us from. And maybe let me know. Let's think about an interesting question to us today. What is your favorite food. What is your comfort food. Comfort food is lasagna. I'm like Garfield. I love lasagna. Give me lasagna any day of the day or night or week. I'll eat cold for breakfast. I'll have it for lunch. I'll have it for dinner anytime in the day or night. So let us know where you're from and what your comfort food is. If you don't know what the term comfort food is, you know, the food that you is your go to. It reminds you maybe of home or it's just, you know, it gives you when you're feeling down. It's that food that just cheers you up and makes you feel great. Thelma is in Morocco. I didn't know you were in Morocco. Wow. You get all over the place, don't you? Thelma says hi from Morocco. My comfort food is anything with cheese. I'm with you there. Cheese is great. Marx says California, comfort food, Indian food, anything Indian. Interesting. Okay. Sega says from Nepal is comfort food is Momo. Sega, you're going to have to, maybe I should Google that. What's Momo? Let me see what Momo is. I'll do Momo food and see what it shows me. It's a type of, okay, Tibetan, Nepalese steamed full dumpling. Okay. That sounds very, very cool. Marx says Indian is good. Mark from Snohomish. I want to know where Snohomish is. I want to Google that as well today. And to expand my knowledge of the world and its foods. Okay, so it's a city in Washington state, Snohomish. Okay. Ilana says I'm from Greece. My comfort food is eggs with fries. Nice. That's a nice one. Great. Mike says from Ohio, my comfort food is calzones. Calzones is something that I've heard of. It has something to do with like a pizza type thing, I think. Yes, there we go. It's an Italian oven baked folded pizza. Okay, that's not a big thing here in South Africa, but it sounds very interesting. Jean says hi everyone from Brazil. A good old burger. I'm with you there Jean. Burgers are always good burgers. Burgers are my boys go to food. I've got two boys aged 7 and 11. And if you ask them, if we ever say we want to get some takeout or we want to have something comfortable, then they usually always go for burgers. My youngest is a chicken burger fan. Wherever we go for lunch. If there's a chicken burger on the menu then that's him. He's done and he's good and he's ready to go. Okay, excellent. I think everybody that is here is going to be here is here. I usually like to give five minutes for folks to join and have a bit of a chat. So lovely to meet you all today. I do see some familiar names there. So today we are going to be working on developing for multi sites. Specifically, we're going to be looking at the kind of considerations you need to make when you're developing a product for multi sites. We're talking specifically about themes and plugins today. And as I mentioned earlier, when we were joining it's it's a topic that is difficult to cover everything in an hour and a half. So I'm going to do my best to give you an overview of the kind of things you need to be aware of and some tips and tricks of where to go looking for information. And we'll see if there are any questions that come out of all of that. Before we get started a few announcements. Welcome again to everybody and thank you to Thelma who is co-hosting from Morocco today. The last time I spoke to her she was in somewhere in Europe and then before that she was back in Zimbabwe and she gets all over the place so awesome to have you here with us today Thelma thank you for co-hosting. If anybody, if anybody can't see this slide this announcement slide that's on screen right now please let me know. There is a little bit of a bug sometimes where the screen share doesn't work 100%. So if at any time you can't see the screen just let me know and then what I do is I disable the screen share and I re-enable this. And then and then you should be able to see things. So if you can't see what's on my screen, please do give me a shout. Thank you. Thank you Mike for letting me know there. And Mark as well. Okay. We are presenting in focus mode which means Thelma and I can see your videos but you can't see each others. But you are welcome to. I feel like I've got a sneeze coming on. I hate when this happens when I'm talking on a zoom. You're welcome to enable your video if you would like me and Thelma to see you, but you won't be able to see each other and that's just to prevent any kind of zoom bombing issues, which don't happen that much but they do unfortunately still happen. You are welcome as always to ask questions you're welcome to post questions in the chat or unmute to ask questions. Mark says Jonathan and I go to the same barber. Yes, he's very good at what he does. But he becomes costly over time. I, my, my haircut is a new set of clippers every couple of years. That's my haircut cost. I'm too lazy to keep mine sharp and clean them so I just buy a new set. As I was saying you are welcome to post questions in the chat you're also welcome to unmute to ask questions. If you prefer to post them in the chat but it's not quite clear to me I might ask you to unmute to kind of clarify your question. If you prefer to unmute to ask a question you're welcome to you're welcome just call my name and say Jonathan hold on I've got a question. The only thing that I do ask is to please if your question is not specifically related to what we're talking about today on screen. Maybe it's a slightly tangential question or related to something else. Keep those either for the breaks that I leave or towards the end. But if it's about something on screen or something we're talking about either I'm going too fast or you don't understand something that I'm presenting, then please feel free to stop me and let me know. Okay, then just a quick sanity check again I'm going to copy and paste the theme and plug in repose that we're going to be working with today into the chat. And the theme is a child theme of 2023 which is the current default theme for WordPress. So you will need that theme in your WordPress multi site setup. You will need a multi site setup so unfortunately I'm not going to have time to go through setting up a multi site again today. But if you are watching this later on, and you have never set up a multi site in store there is a workshop on WordPress dot TV that I did a couple of weeks ago that walks you through that process so if you don't have a multi site today, go through that video go find that video on WordPress dot TV set up a multi site locally and then you can work through today's content. Then very importantly, I do tend to talk very very fast. It's something I very much try and focus on, especially given what I do. But if I start going too fast and either you can't understand me or the automated captions are not keeping up please do let me know. You can send me a message in the chat or just say hey Jonathan slow down. As always, I will be posting this recording this is being recorded and will be posted to WordPress TV afterwards usually during the course of my day tomorrow. And then finally if you're looking for any more content around learning things about WordPress you can go to learn WordPress dot org. All of the workshops that I'm doing. Mostly this year I am turning into tutorials on WordPress. So if you don't want to sit through the workshop you can go and watch the tutorial as well and all the code samples and snippets and all of that are there as well. Okay. Then let's just look at our learning outcomes for today. I'm going to be looking at some useful resources to be aware of if you're developing for a multi site setup. I've actually gone and gone through and listed sort of some of the main functions you might need to work with some of the main hooks and filters you might need to be aware of. So if you I actually just remember today that it might be useful to also share the link to the slides in the chat, because all the functions are in the useful resources slide so that will be handy if anybody wants to download that. So that's what to consider when developing a theme or a child theme and if it's going to be used on a multi site network, and then what to consider when developing plugins that might get used on a multi site network. So those are the three main topics today that we're going to be covering. Okay, before we kick off. Are there any questions around anything does anybody need time to get anything set up grab a sip of water take a break whatever the case may be. I'm going to go off camera and blow my nose because there is a sneeze that's building so I apologize I'm going to unmute and go off camera for a second when I do that. I realized that I was talking after I muted myself so that was soft. Can you tell I haven't done these in about two weeks. Okay. We don't have any questions so let's let's take off. So the first thing I want to just cover is some sort of thoughts to think about when it comes to developing for multi site. And to give you a little bit of background history the first time I encountered the concept of multi site, I, I had started developing plugins for WordPress this was around 2016. I had used WordPress in the past I had built sites for clients with WordPress. I built custom solutions for WordPress installs at the companies I worked for, I built themes based on designs, but at that point I'd never discovered multi site it was never something that sort of, you know, came up in my requirements. And then I started building plugins to sell. And my first plugin that I built was for a very specific theme, and it was a plugin that enabled the owner of the plugin to install this on a site that had this theme installed and effectively white label the theme. So it removed any specific branding of the theme branding and replace it with your own name and there was an icon that you replace, and it sort of made the theme look like it was a custom developed theme as opposed to belonging to a theme company. And on the way in the process of selling this plug into clients, one support request I would get a lot of is, is this plugin multi site support in other words, if I install it on a multi site network with this theme installed, what it work. And I didn't even think of that I knew what multi site was. I don't know exactly how it worked, but I didn't think about the effect of developing a custom plugin for a multi site network might need to to worry about. And so I went and did a bit of research into, you know, developing for multi site and the first thing that I discovered is that a lot of the knowledge around developing for a multi site network is largely undocumented. The reason why that is if you go to I'm just going to hide something which is in my way here. That one. If you go to the developer documentation developer wordpress.org. First of all, there is nothing on this homepage that even talks about multi site as a concept. If you open let me let me share this link in case anybody wants to open this on their side. If you open for example the code reference. The code reference is effectively you can filter by functions hooks classes and methods. But there's nothing in there that you can say just show me the functions and hooks and methods and classes that are multi site specific. So you can't really find too much information there. So if you have a look at your common API is that that's somewhere where you might think something about multi site would exist. There's nothing in the menu that that talks about multi site. Mike before you go it'll be shared tomorrow sometimes during my day tomorrow. I share the link in the meetup event comments, and then you can also find it on WordPress TV WordPress dot TV and it'll be the same name as what today's session is so keep an out for it there. And then the common API is about about multi site. If you have a look at developing plugins for example the plugin developer handbook. There's no menu item if you look on the left here there's nothing related to developing for multi site there. And the same goes for the theme developer handbook there's nothing specifically there. Let me open that up in a new tab. There's nothing specifically there about developing for multi site so it's something that you kind of have to figure out on your own you have to kind of stumble across it. I'm hoping today that I will be able to give you some of the sort of knowledge around what to think about when you're developing a plugin or theme from multi site network. And help you dive into the areas that you need to go looking for information on. Another thing that I would recommend and I'm going to open up my my visual studio co studio now is there is a in the WP admin folder of a WordPress install. There is a network directory. And the network directory is effectively all of the admin functionality that powers the multi site part of the network. So, if you are going to switch over to my multi site network quickly so this is my multi site dashboard. So, if you're looking for multi site users themes plugin settings and all of this functionality. This all pretty much exists inside of the files inside of the network directory inside of WP admin. So a lot of the information that you can find out about multi site, what are the action hooks and filter hooks that are firing in the dashboard, you'll be able to find in these files. And so one of the things that I did yesterday was I just did a search let me find a good example. Let me open up the edit dot PHP page. I just did a search for any do action calls, which then helped me list out all of the, all of the action hooks that are being fired in the in the network admin dashboard. So that's one way to kind of dive into multi site and see what are the kind of things that are available there. When it comes to the front end. I thought I had a note here about that but I don't when it comes to the front end. It's not that easy to find information, but the one thing that you can do and we'll discuss this function in a second is if you do a search through the WordPress code base. I'm going to do a search here now for the is multi site function. This multi site is a very simple function that just checks is this a multi site network, and if it is returns true and if it's not returns false. And then you go through and you look for all the places where is multi site is being used, you can find the specific functionality that is being run or not run, depending on if it's a multi site network. So for example if we have a look at the WP activate PHP file which is the one I have open right now. It's just resides in the, it's just resides in the root of your WordPress install. Okay, someone says they can't see the screen okay thank you for mentioning that. Let me just disable screen share and then re enable it and that should fix the problem. If I can get my one second everybody if I can just get my zoom panels back. There we go. There's a specific button that I have to click so let me. Let's go stop share right we're stopping the share now. Let's go share screen and let's go desktop one. There we go okay my screen share is now loading. Right so now Ilana can you see my my code edits a window now. You just let us know in the chat if you can see that coded it's a screen. Okay Mike says the screen share looks good. Ilana if you can just confirm that for us. Sorry not Mike Mark. Okay, excellent great thank you for letting me know. That was that bug I told you about sometimes when folks join after I've shared the screen. It doesn't work 100% and I just need to re enable it so so we're back to that now so thank you for pointing that out. Okay so we were talking about let me hide this window again. Yeah. So this is the WP hyphen activate PHP file it sits in the root of a WordPress install. It's sort of the first PHP file at the top of that list. And you will see there is the is multi site function being called. It's doing is not multi sites in other words if this is not a multi site install, then it does some specific functionality. And so that's a great way to check what things are happening in a multi site environment versus not in a multi site environment. Unfortunately that does require you to do a little bit of work on your side. But there's a there's a that's a good way to sort of go through the WordPress code base and see what is specifically multi sites and what is specifically not. Okay, so that's one way that you can go about it. Let's go back to my slides. As I mentioned earlier, there is only so much that I can cover in a one and a half hour workshop so I'm going to try and cover some sort of top level items. But it does require you to do a little bit more sort of research if you are developing specifically for a multi site install. And those are two ways you can do it either looking in that that network folder. So let's just go back there. So that was in the WP admin network directory and just seeing what files are there and what they're doing. So you can search for any instances of is multi site function in your WordPress install and go through those. Then last but not least, if you want to know if your plugin or theme works on a multi site network, make sure you can set up a multi site network locally and test test test test. Install the theme install the plugin, make sure it does what you expected to do set up a couple of of local subsites using the sub domain, sorry the sub directory install which will be the easiest option and test as the plugin functionality work does the theme functionality work. Does it do what it needs to do. Okay. Any questions on all of that before we dive into some useful functions and things that are good to be aware of. While we talk about coffee I have the opportunity. I'm going to Greece in June to go to WordCamp Europe, and I can't wait to try Greek coffee. I believe it's very, very good. So I'm looking forward to that. Okay, so let's talk about some useful multi site related functions. I'm going to make I realized that this text on these is quite small so I'm going to make this a little bit bigger. So if I can, if I can navigate my own slides. There we go. Let's make it 26. There we go. Okay. So the first one is, whatever done, just sorry folks, I am busy breaking my own zoom setup. So the first one is the is multi site function. I'm not going to open up the handbook docs they are linked in the slides if you want to check them out later which can run through them very quickly but is multi site function we've already discussed. It basically checks is this a multi site network and if it is perform certain certain functionality and if it isn't done. So that's a great way you can develop your plugin or theme to have specific functionality for a multi site network. So there is the is main site function. So what this does is this checks as you might remember when we installed the multi site there's always the main site which is the first site that existed as a single site before it was converted into a multi site. That function just returns again true or false if you're in the main site or not. Then you have to admin related functions there's the is super admin function, which is the multi site equivalent of the is admin function. And you'll know that that basically checks sorry not not sorry I'm getting myself confused here sorry is network admin function is the multi site equivalent of the is admin function which checks are you is the request being made in the dashboard or is it a front end request. So there is network admin function which is the fourth one on this list basically says I'll be in the network dashboard and if we are then perform certain functionality or don't. The is super admin function is specific to the current user. So you can check if the current user is the super admin other words the network admin the person who set up the multi site or somebody who's been assigned network admin. And then you can allow specific functionality or not depending on that user. And the network admin URL is the multi site equivalent of the admin URL function, which is a function that you can use to retrieve the network admin URL and then append variables to it to redirect folks through the network. So let me talk about the network admin URL let me let me show you what I mean. It's it's effectively it's this URL here so in this case will be multi pressed test slash WP admin slash network. And if you want to redirect somebody to a page within the network not within the dash admin dashboard for the single site. That's the network admin URL that you would use. So things like get blogs of user. And you'll notice, when we look at some of these functions some of them use the keyword or the term site. Some of them use the keyword or the term block. And that's just a sort of offshoot of the fact that WordPress was originally a blogging platform. So what we know as sites today used to be known as blog so some of them are still using the old terminology of a blog. So basically the get blogs of user is a function that will return all of the sites, the sub sites or the even the main site on the network that this user has access to, or is an admin of. So if you have a user that is an admin across multiple sites and you need to perform certain functionality across those sites because of the user, you can use the get blogs of user functionality. The last one is the is network only plugin function. Now this one is very specific to plugin developers, and I'm going to open this one because it actually exposes something extra that I want to share with you. You'll see that at the top here it says it checks for the network true in the plugin header. And it says when you're developing I'm going to switch back over to my code is if you hear, when you're developing a plugin. As we as we know, no not a Kismet it's open up Hello Dolly for example, as we know plugins have a plugin header. Sorry, here it is, where you can define the plugin name the plugin you are either description the author the version those kind of things. You can also specify a network key, and you can set it to true. And what this effectively does when you go back to the documentation is it is that allows the plugin to only be activated as a network plugin. So in other words, somebody installing it on a single site wouldn't be able to activate it on a single site it's specifically network only. So that's great if you want to develop a plug in that specifically adds network functionality to a multi site network. So that's kind of a way that you can prevent that from happening and this this check basically checks for that header and returns true or false based on that. Okay, other functions that are useful. We've got the gets so these are a few that I'm going to mention all at the same time. Yes. I don't know if you've not seen Felicia's question or maybe I missed that. Felicia's question. No, I didn't see that thanks thanks for pointing that out. Felicia says, why do you prefer subdomains to subfolder Felicia that was just a reference to when you're setting up a local testing multi site. I mentioned that in the in the setting up a multi site workshop that unless you have. It's not a preference of mine it's just unless you have a local domain a local wildcard domain set up with domain mapping. You'll be able to set up a sub domain on a local development environment. So on your PC on your computer so it's just easier to set up a sub directory. So it wasn't really my preference it was just the sort of limitation of how domains work and subdomains with a multi site network. And I see Alanis says it's nothing like American coffee so that's interesting. Okay, great, we're all on board about okay. So then the next set of functions that I want to chat to you about kind of all work together. So there's the I'm going to run through them and explain how they work. So there's the get sites function, which you can kind of really think about what that might do. Then there's the switch to blog function. See we see now site versus blog. So think about site and blog is the same thing just bear that in mind. The restore current blog function. Then there's the update blog option function and the get current blog ID function. Okay. The sites effectively will get a list of all the sites on the network so it returns a list an array of all the sites and you can get the IDs and that kind of thing. Switch to blog effectively what that does is it switches the scope of the current site that you're accessing to a different site. So what do I mean by that. Now, because because your multi site shares the same WordPress core files, and the same plugin files so it's not multiple plugin files it's one plugin that works across different sites you actually your network activated and then you, and then you individually activate the plugin on the different sites, because that shared across the network. When you are in one of the subsites for example, if your plugin is querying the posts, then it's only going to get the posts in the scope of that site. It's only updating options and you're going to update the options for that site. But you might want to be able to switch to a different site and maybe pull data from that site or update an option in that site for whatever reason. That's where the switch to blog function comes in so you can switch the scope of what site you're in in your plugin or in your theme code to a different site on the network. Perform from some functionality there and then use restore current blog to switch back to the current site. For example of what's something like that might look like. One example I have is let's say you are in a plugin, and you want to create a function that updates an option on a specific site on the network so you've got some functionality happening. And on a certain trigger you want to call a function that let's say updates an option on site to, for example. I'm going to open up my my VS code now and just at the bottom of Hello Dolly here I'm going to scroll to the bottom and kind of show you what a function like that might look like using some of these functions we've just discussed. I'm going to copy and paste it and pop it on screen so you can all see it I will also share it in the chat if you want to copy that code, but effectively here's the function it's called updates site option, and we pass at the site ID. We switch to blog and we pass in the site ID so that means change the scope to whatever site we're changing. Then we can run the default update option function call which many plugin developers will know if you don't know it's basically just updates an option. And we tell it the option we want to update and the new value and it'll then update that option for that site. And then we call the record call restore current blog function to restore back to the existing blog that we were on. We're on site three, for example, and we wanted to update an option on site to we could call update site option passing the number two, and then it'll make that change as necessary for site to and then come back to the current scope. If you don't come back to the current scope, any other execution of your code will take place on the site that you switched to and that court could cause issues. So if you read the documentation for switch to blog it says you should always restore current blog when you've switched to blog and made the changes that you need to make. Now let's say, for example, you wanted to extend this function and you wanted to, for example, update an option across all sites based on some trigger. Let's say for example, you've got a piece of admin functionality. And when a super network admin say into some information and hit submit, they want that information to go across all sites in the network. Well then your function might look a little bit different it might look something like this. So let me talk you through that. So here we're passing in the option name and option value which will get maybe from the form or whatever the case may be. And then recalling the get sites function so this is similar to get posts, get post goes and retrieves all the post for a site, get sites retrieves all the sites on the network. Then that's an array of sites you can loop through that array and get each individual site. Each individual site in that array is an object. So you use the object notation to get the blog ID from the site object. You switch to that site using switch to blog, you run the update, the single update option because now we're in the scope of that site so we don't have to use the blog option one which I'll show you in a second. We use the single update option, the new option and value which I should actually be using these variables so let's do that. So I change my code here. This is what happens when you when you write example code that you never test. It's just meant to be an example. And again restore current blog. Now what I would like to highlight to you here is that I'm calling restore current blog inside of the loop. Because if I did this, if I switch to blog, and I called restore current blog outside of the loop restore current blog only restores the previously switched to sites and let me give an example. Let's say I've got five sites on my network my main site to site one and then I've got like two three four and five. I will get the sites so I'll get all the different sites I'll start with site one. So I'll switch to site one and I'll make the change. Then I'll switch to site two and I'll make the change to three to four. Then I then I was on five, and the last one was for so when I call restore current blog here. It'll restore back to four, not back to the previous one I wanted to be on. So you should always call restore current blog inside of here and that way always restore back the correct one and get you to the same place. The other way that you can do it. And this is another function in the list. So let me switch back to my slides is you can use the get current blog ID and store the current blog that you're on. So let's say you're actually accessing this in in in site ID for for example, and you want to always make sure you switch back to the scope before. So get current blog ID obviously gets the current sites ID or blog ID. That's always the confusion when things are different. So here for example, you could say something like this, you could say current site ID equals get current blog ID. So that'll be whatever the current site is. Then you can do your get sites. You can loop through and do the updates. And then over here right after the for each loop, then you can call switch to blog again and pass in what the current site ID was and that way you know you're always coming back to your current site. Now, what's interesting about this is I was doing some research on this while I was preparing for this workshop and apparently doing it this way is more performed. And let's think about that. In the previous way we were doing switch to blog update option and restore to current blog. So those are three actions. So multiply that by five sites that's 15 actions in total. Now what are we doing we're doing two actions inside of the loop. So that means 10 actions and then one action to switch back to the current blog and one action to get the current blog ID. So now we've gone from 15 to 12, which is only three less but imagine that on scale imagine that on 100 sites. So you would have gone from 100 times three actions 300 actions down to 100 times to 200 plus two so 202. So that's a 92 action decrease, meaning your your processing is that much faster almost a third faster. So depending on your scope and how you're running things and how you're making changes it's good to know both options exist. Okay. Jan says is there a way to add new fields when generating a new site I'm glad you asked that. Yeah and I'm going to get to that in a second so bear with me on that one. Lisa asked are you using notepad plus plus no Lisa I use so I use two editors I'll share them with you very quickly. The first one is VS code. And that is the one that I use in my in my workshops. The reason I use it is because it is free it is open source, and in most people can down can download it and use it. And it's also possible to set it up with a lot of functionality that my actual everyday editor users which is called PHP storm. PHP storm is a paid for ID that I'm actually going to bring it over here I use it for my writing for my coding. And it has a lot of building PHP functionality that I like. I'm going to share this with you today because I can't do this in VS code yet because I don't know how, but for example in PHP storm. This is completely unrelated to multi site I want to just share this with folks one of the things I love about PHP storm is you can do a find in files search. You can search where we were talking about searching for is multi site earlier. So I can do that I can say is multi site, I can search for it. And then I can do what's known as open in find window. And when I do that it pops up a fine window at the bottom of my screen. And it shows me the list of all the results, and I can literally just click through to every single one and see the code on the right hand side here. So that's a great way of digging into multi site and seeing where all those instances are I'm pretty sure probably is possible in VS code. It probably would require a plug in of some kind. But because it's by default in PHP storm I just keep using it in PHP storm so those are the two answers I use VS code for my workshops and PHP storm for my day to day. Okay. So, so that's how you would use get sites switch to blog restore current blog update blog all that kind of thing. So let's let's dive into the Sega says right click on folder you want to search and select find in folder so let's do that. So let's go. So the, so the problem with that Sega is I can't do that on the folder that I have open, which is where I want to do the searching. Let's let's do it so we can do find in folder. So there we can do is multi site so it gives us the same functionality, but I can't do it on the top level so if you can tell me I'll do on the top level that would also be cool. So inside, for example, the multi press folder, and I don't see a way there's no way to search in the multi press folder. So let me know if you know how to do that one. Okay. Then, use the sidebar switch off that that's that's the one I think that I was using. That's this one. Yes. So that's the sidebar search. Yeah. Okay. So you had the question that's right you had the question about where are we now where are my slides there we go. Yeah, and said, is there a way to add new fields when generating a new site. And I'm glad you mentioned that because there is a way. So there are also some useful multi site related hooks that I recommend you look into. And the one yen specificity to your question is there is a sign up log form hook, which let me open up that one quickly. So this fires after the site sign up form so you can add additional fields to that sign up form. And then there is the WP initialize site so this time they've gone from blog to site again. Which fires when the sites initialization room room routine should be executed. So you can set up additional fields on the sign up form. And then inside this action this initialize site action you can do something with those fields. A great example for that is for example if you wanted to allow multi site users that are signing up to select their own domain name and have some kind of API request that registers it for them and then points it to their subset that would be the perfect place to do it. I'm not going to dive into how one would do that today that's that's maybe a whole nother workshop or a live stream, but that is an example of how you could how you could do that. There's also related hooks there's the network admin menu hook, which is essentially the hook you use when you want to register network admin menu items. That's the same as the single site admin menu hook. There is a network admin notices hook which is the equivalence of the single site admin notices hook to register admin notices. We've spoken about the blog form and initialize sites. There's also a, and here you'll see the WPM you prefix. If you if you go and read about the history of WordPress WordPress multi site was originally developed as a project called WPM you so WordPress multi user, and some of those functions at the WPM you prefix and some of those functions still contain that prefix. But what that does is it filters the displayed means up the way to hide it. It filters the displayed site columns in the site list table. So what that means is if I go to my site list. I can add columns to this table using that that filter. And then there's the manage sites custom column, which allows me to fire for each registered custom column in the table. So if I register columns to the table I can use that and I can do certain things are. So there are these functionalities and these hooks and filters that you can use that you can dive into. There are a whole bunch more. I can't list them out today, unfortunately. But if you look through that network directory in the WP admin, you will see and you will find most of the hooks there and there's quite a few available to change how the admin works how to register admin menus. How to do specific things in the network admin, and then what to do when you're working on in your in your plugins and in your thieves. Okay, so those are the ones that I wanted to highlight today. Are there any questions around any of what we've just covered. Any of the example code we just looked at otherwise we're going to start diving into specifically what to think about when talking about plugins and what to think about when talking about themes. While we're doing that I'm going to close down some of these tabs that I have opened because otherwise I get myself lost. Okay, so the first thing that I want to chat about and I'm going to switch off from the slides now because now I'm going to work from from my notes and from coding. The first thing I want to chat about is themes. So if you want to see how this works along with me, I already have the 2023 child installed as the network admin. I have a really network enabled it. If we go to the code for this child theme. You'll see that it doesn't do anything very special. So I'm going to open up the 2023 child. It just has it's a block theme so it's based on the 2023 theme so it has a basic theme.json file. It has a style that CSS which just has the theme header. It has a pretty standard read me. It has an empty functions of PHP file. And then it has very specifically a footer default pattern that I've copied from the parent theme to the child theme. And that's what we're going to be working with today. So when it comes to how themes and child themes and that work across the network, the the the shortened version of it is most of your functionality will just work as is. So if you are calling template tags to get site names and if you're calling post related query querying posts querying pages querying whatever updating and deleting site options all those kind of things that's going to remain pretty much the same. The only time that you sorry I'm just going to pop my notes back over here so I can see what I'm talking about. The only time that you might need to worry about whether or not the theme runs on multi sites or not is if you wanted to specifically get some information about the sites across the network and include it in a specific site. So let me show you a rather simplified example. Let's say that in my child theme when I have the child theme installed instead of the. So let's have a look at what this looks like on the front end. So I'm going to go to my multi press sites and I'm just going to visit the sites. And if we have a look at the footer right at the bottom here it just says proudly powered by WordPress. And let's say as a very simplified example. I want my sites on the network to say proudly powered by the site name. For whatever reason that's my simple use case. So what I would typically then do is I would go into my in this case my block theme pattern for the footer, and I would simply change the code over yet so I would change this to do something. So it's this this anchor tag I'm just going to take that all out over there. And here I could just get the site name using a function called get blog info. So I could do something like this get log info it's a it's a WordPress function, and I can just pass in the value name. And that will then get the name of the site in question. Sorry, that's not supposed to be there. And once I've done that it's going to get the name of the current site and display it in the footer so let's test that. So if I switch back to my multi press sites I'm seeing I'm on multi press test which is the main sites and I do a refresh and there it is powered by multi press I'm happy that that works. Then I switch to my, my other sites and I've got Bob set up again I tend to use Bob as a default I apologize to any Bob's in the, in the, in the chat. And if I visit that sites I'm going to just visit that site from here I'm going to open this in a new tab. And I scroll to the bottom there it's proudly powered by Bob press so that's working the way I needed to work great happy days move on with my life. So that just works as per normal I didn't have to tell the blog info function that it was on a multi site network. It just it does what it needs to do because it knows the scope that it's in. However, let's say that I'm building a network of sites and I want folks to know that this site is part of a larger network so maybe it's a university site or it's a nonprofit site. And what I would rather this thing says proudly powered by the site name and then in brackets, part of the multi press network, for example, I would now need to build some kind of functionality to do that so let's dive into what that might look like. So I always like to keep these in a function. So I'm going to call this TT, so it's for 2023 C so TT 3 C for 2023 child. I forgot the function prefix there. So TT 3 C for the 2023 child is the prefix, and I'm going to say get site name that's going to be the name of my function. And I should also check if this function has or hasn't been defined somewhere else in case another plugin or theme defines this function. The chances of it are very small but it's a good idea to prevent any kind of areas or bugs or whatever. So a good practice is to say if not function exists. And then I pass in the function name you may have seen this many times on plugins or themes within the WordPress space. So I would make sure that only if the function doesn't exist that I want to create my custom function. Cool. So now in here, the first thing I'm going to use is I'm going to use the current site name. So this get blog info name. So we could say parent site is get blog info name. Perfect. So that'll give us whatever the current site name is. But now I also want to get the main site name. There's a couple of ways you can do this. But if you remember we spoke earlier about using we go back to the slides. We spoke about the get sites option we spoke about the switch to blog option. We spoke about the restore current blog option so we know we can use that functionality. So because I always want to get the main site name I can essentially then go switch to blog. So I'm going to pass in the idea of one because the first site is generally always idea of one unless something's gone wrong somewhere. Now how you could get that if it wasn't the main site that's a different example but let's just go with the fact that it is set up as the main site. So then I would get that sites names I could say main site name. And here I can just call get blog info again. And that's because we have switched to that scope. So when I recall when I call get blog info name in the scope of side one it'll get the name of side one. And then we need to restore. So we restore current log, which restores back to whatever our current site is. And that's effectively the function so I'm getting the main name for the site, switching to the to the first site getting the name there switching back to the current site. We need to return some information. So what I can do here is I can say echo our insight. And then I can append a string and I can say something like part of the, and then I can append that to the main site name, and then append another string and say network. Close the brackets. And then we get the semicolon. And there we go. And that's what our function in our functions are PHP file would look like I'm pasting it in the chat if anybody wants to grab that. And then in the footer, we can just call this function. So, I actually think I need to return not sorry I need to return not echo apologies. Echo means up to the screen I want to return it, not echo it. So let me update that function in the chat. So there's that there's our get site name. And now it's going to go and it's going to call that function switch to the main site get the name append the string and return it back so let's see what that's going to look like on the front end. So let me open up both sites so let's visit both multi multi press and Bob press so if we open multi press and we scroll to the bottom there we go, proudly powered by multi press which is part of the multi press network which is what we want. Or is it. And then for Bob press it says proudly powered by Bob press which is part of the multi site network. Now here's a good example. Do we want the main site to be powered by multi press which is part of the multi press network maybe we don't. We only want this to show on subsites. So that's where for example we can use and we mentioned this earlier we can use this is main site function. So this one checks if it's on the main site or not. So we can update this code so let's go back to our functions of PHP. And at the right at the top here we can say, if this is the main site. We just want to return the get blogging for now, we don't need the powered by and all of that. It is the main site. So we just returned that powered by multi press, or we could say powered by the multi press network or whatever the case maybe. So that's that. Otherwise if it isn't the multi site then do what it needs to do build up the name and and returns. So with that in place. Let's let's have a look at what that does. So multi press if you refresh the home parades just proudly proudly powered by multi press we could add the multi press network or whatever we wanted there. And then on Bob press we have the proudly powered by Bob press part of the multi site network multi press network. So that's the only time you might need to use some of this functionalities if you want specific information from the different sites in the network because you want to render it somewhere in your content. So if you're looking to pull posts from another site into a main site. I remember one of the early ideas that I had I had a couple of blogs that I was running one was to do was development. One was a personal blog one was to do with the sport that I was doing at the time. And I thought about building a multi site network for each one of those blogs and then pulling them all into the main site, which is kind of like the home for everything and then having it split off. Ultimately I scrapped all of that and just ended up putting it all on one blog anyway. So that's one way you could do it you could have one main site that has all the data and then all the subsites you can have individual information there. But otherwise, as I was saying, the rest of your plugin and theme functionality you don't have to make any huge changes. You don't have to make any major considerations. Your plugins and themes will just work. Sorry, your plugins and themes, your themes and your child themes will just work as they normally are on a site because they know that they're in the scope of that specific site. Okay, any questions around developing themes for a multi site network. Before we before we move on. I'm just going to make a note of that multi press updates because I didn't think of it until we literally did it now in the workshop. So I'm going to grab that code and update my notes so that when I record the tutorial for this, we can we can include that as well because it's a nice little way to look at it. Right, there don't seem to be any questions around around themes so let's move on to plugins. So the plugin that I have installed let's switch back to my site admin. The plugin that I have installed if you joined me for my learn plugin security workshop. You will remember that this is a plugin that sets up a short code that renders a form, and then saves form submissions into a database. I'm going to very quickly look at the code so we can understand and remind ourselves what the code does. I'm not going to dive into the actual functionality today, but essentially it has the success and error pages. There's an activation hook which creates a custom table called form submissions. There's some JavaScript that happens that does things. There's a short code which renders the form, and then users can submit the form and it's like a contact form for a website. And I use this when I did the plugin security workshop and we spoke about how you should sanitize data and all those kind of things. Don't worry too much about the actual functionality. The thing to remember when it comes to developing plugins and themes is sorry, I keep saying plugins and themes when it comes to developing plugins specifically. Like themes, most plugin functionality will work the same in a single site and on a multi site. So again, if you're doing things like register post type, get posts, update options, all those kind of things on a single site environment will work in a multi site because it is in the scope of that site. There are however two things to think about when developing a plugin. The first is that plugins will often have some kind of settings page. So you will have to register an admin menu item and maybe an admin submenu. And then you'll have some kind of page. There's some function that registers the callback. So, for example, if we look at this, if we look at this plugin, I'm going to go down to the bottom. There's an admin menu hook that I've hooked into. And it adds the learn admin page submenu. And then it renders a list of the submissions. Now, when you're developing your plugin for the multi site network, you need to think about does this settings page need to exist in the single sites admin, as well as or exclusively to the network admin. If it's a setting that is going to affect the entire network, then it needs to belong to the network admin and you need to register it using the network admin menu hook and do things accordingly. The rest of the functionality will be pretty much the same, but you need to register it in the right hook. And then the other thing that you need to think about is how your notices work. So if you're running admin notices, you need to use the network admin notices. If you're updating things, changing things, whatever the case may be, that's the one consideration. The other consideration is if your plugin is storing any kind of custom information. So in other words, you're not using custom post types. You're using, like we are in this instance, we're using a custom table. So let me show you what I mean when I talk about this. If we go and have a look at the activation hook, you will see that I'm using the WPDB prefix method on the WPDB object to create the form submissions table name. When I activate this plugin, I'm going to just deactivate it and then reactivate it. When I activate this plugin, when I network activate this plugin, the register activation hook will fire because that's when the plugin is activated on the network. So it doesn't fire when I activate the plugin on a single site, it fires when I activate it on the network. So if I switch over to my database for the site, let me show you that very quickly, going to go here to multi-press. You will see that it's created the WP underscore form underscore submissions table, which is great. The problem is, if I load the shortcode onto one of the subsites, because and let's scroll down to the function that saves the form data. So we'll go down here to maybe it's the maybe process form function. And you'll see here I'm getting the table name as prefix form submissions. As I said earlier, your core functionality will function in the scope of the site. So in the scope of site two, WPDB prefix will return WP underscore to underscore. And then you're appending form submissions to it. So it's going to look for a table that doesn't currently exist. Let me show you in the database. I've got WP two terms and term meta and posts and options and links and comments, but I don't have a form submissions. So because I'm using the core pre table prefix functionality of WordPress, which I should do, it's getting the table name that belongs to site two, which is WPDB underscore to and looking for submissions. It's not going to find it in that code is going to fail. So I as a plugin developer need to be aware of that. Now there are two ways that I can do this. Either I can update my process to always use the WP underscore form submissions table or use my own custom prefix. So I might use a prefix of LPS for learn plugin security or whatever the case may be. The problem with doing it that way is it's not sort of the WordPress way if you will, and it could cause you problems later on. So if you have a look at the, let's find the register activation hook documentation in the WordPress developer docs. I want to show you something to think about this. I'm going to share this with you if you want to scroll with me. And if we scroll down to the user, the user contributed notes, they call it. And you'll go down a little bit, a little bit, a little bit here. And this is what I was looking through when I was preparing for this. And there's a comment here by Mallory DXW old six years ago. I'm going to actually just copy that link and paste it in the chat so you can jump straight to that. And it says there according to Nathan a lead developer for WordPress you shouldn't use activation hooks, especially on multi site. Instead you should do and there's a whole thing and if you click through to the court ticket you can see the discussion and what they were talking about there. Effectively the comment below that answers the question. In a multi site network. There is an argument called network wide. Well, sorry, not in a multi site network in any WordPress install. There is an argument called network wide which is passed to the callback function for an activation hook. In the scope of a multi site network that network wide argument is always going to be true. So you can use that to perform specific functionality for your activation in your plugin if you're on a multi site network versus not. So you'll see what they're doing here is they're getting the sites looping through the sites running the my plugin install site custom functionality restoring the current blog and then continuing along from there. So what I'm going to do today is I'm going to show you how I need to change my plugin code to work with this information. So let's go back over here and have a look at the activation hook. So the first thing that I'm going to do is I'm going to take the code that creates the table. And I'm going to put it in a separate function just so that I can keep that code separate. So I'm going to take all of this in the learn setup table. And I'm going to create a new function called WP learn creates table. I could call it create form table I could call it create whatever I want. And I'm going to put that code in there because this code stays the same no matter what sites scope I'm in. I want that to stay the same use the prefix correctly create the form submissions table. Perfect. Then inside of the activation hook because I've copied this code out I can delete this now. And inside of my callback I'm going to pass in the network. Wide argument. I don't have to call it network wide but it makes it easier if I do. And then I can say if network wide in other words if this is being activated on a network. What I can also do to kind of make my life a little bit easier is I can also do a check before this to say if is multi sites and network wide. So this way it'll do the multi site check first if that fails it'll carry on like it's a single site. If it is a multi cycle check is this plug in being activated network wide in other words in the network admin dashboard. I'm network activating it. And then in that case what am I going to do. First of all I'm going to get my sites. And if you remember we did this in Hello Dolly earlier so what did we know we didn't do it there. Yes, we did. So it's sites equals get sites. You can use the get sites function to get all the sites. And then we're going to say for each site as using the wrong keys today for each sites as sites I want to loop through the sites. Then I'm going to switch to the site switch to blog passing in. And I think it was blog ID. Yeah, there we go. And then once I've switched to the content of that site I want to create the table. So then I can call the WP learn create table function. There we go. Once I've done that what do I need to do I need to restore so restore current blog or do it the other way that I mentioned, as we know there's multiple ways to do it. I'm just going to stick with this one for now. And that'll then create the tables for all the subsites. But then I also need to because I want this plugin to work on both single sites and subsite installs. I need to have an option for if this isn't a multi site or it's not being there to be activated. And then I can just call. So I can just say else over here. Sorry, my things pop up again when I click the wrong button. And then I can just call WP learn create table. And that's the only change I need to make. So now when I activate this plugin on a single site, it'll just call create table once. If I activate it on a multi site and it's being network activated it'll loop through the sites and create all the different tables for me. So let's test this. If I go back to my database, I'm going to, first of all, sorry, before I go to my database, I'm going to network deactivate the plugin. I really should have a deactivation hook, which deletes the table for me. That's just a bit of good practice, but I'm going to delete that form submissions table just to make sure. So there the form submissions table is no more. And then I'm going to activate this. So if I network activate. Now you will see that if I go back to my. You will see now there is WP form submissions, the first table for the main site. And there is WP to form submissions for the additional site. But now there's another caveat. What happens if a new site is registered. Now they own, there are no form submissions for that new site. So that's where you would do something like use the, and this gets back to the question that you had earlier, you would use one of the hooks. So maybe the WP initialized site hook. So let's open up that one. And what this does is it passes in the new site object. So you could then have something hooked into that, which when a new site gets registered, it loads the fields for that site. So you would need to think about that as well. That's kind of how you have to think about your, your multi site network and developing plugins or themes. Number one admin menus and admin notices and those things, where do those go, how do those work. You can use things like is multi site to check are you in a multi site or not. You would use things like is which one was it. Sorry, where are we is network admin versus is admin to check if you're in the admin dashboard. And if you're creating custom functionality custom tables, you need to make sure that you're using the correct switching to the blog, creating the new table, switching back and all of those kind of things. Okay, any questions around all of that I know it's a lot to take in. It's the kind of thing where the best thing to do is to test your plugin functionality on a multi site network. And then it gets back to what I was saying in the very first, very first slide, which is test test test test test. So have have a multi site network set up with one or two subsites, load your plugin or your theme test them across the site make sure the functionality works, then create a new site, and see if the functionality works there if it doesn't think about why and adjust things accordingly. It's it's not something that is that is easy to sort of cover in a short workshop, but hopefully I've given you some ideas and some concepts to think about. So that when you're building your plugins and themes, you have these things in mind. As I mentioned finally as I mentioned, if you are just using, and this is almost a. This is a good argument for not going too far outside of the WordPress ecosystem when it comes to developing your plugins or themes. If you were using if I was using a custom post type, for example, for my form submissions, I wouldn't have to worry about any of this, because when a new site is created that the posts table for that site is automatically generated. So if I was using custom post type and I was storing it as custom post type, that's how it would get stored, and I wouldn't have to worry about these things. It's only because I'm using a custom table that the problem comes in. So use the core functionality WordPress the core option functionality the core post meta functionality the core post functionality custom post types and all of that as much as possible. But if you have to step out of that environment if you have to create custom tables or any kind of custom storage of data or functionality, you do need to think about how that's going to operate in a multi site network. Okay. Any questions on plugins specifically or anything else that I've covered today. Hopefully I've given you a sort of a view of what can happen in a multi site network and what you have to think of. But are there any questions around any of that before we wrap up for today. Okay. Well they don't seem to be any questions at the moment. Thank you Mark for your kind words. If there are questions around this topic that you that you might think about afterwards or if you're watching this on WordPress TV, you're welcome to leave them in the chat if you have any questions about this GitHub issue. And I will and I will follow up afterwards, if need be. As I said I am I am preparing a tutorial on this which will cover all this information as well with links and documentation and those kind of things. In that tutorial I'm going to try and do a little bit of a deeper dive into the functions. I've actually been thinking about spending a bit of time, working on the documentation side and maybe creating a page specifically for multi site. I noticed that at the at the very minimum lists all the multi site specific functions hooks and action hooks and filter hooks, just at a minimum, so that folks can easily just go to that page and see all the multi site specific stuff and then link through from there. So I'm going to try and think about if I if I can do that in the near future. If anybody out there has some time on their hands and they want to create that documentation. Please do go ahead if you're not sure where to start let me know, and I'll gladly help you but I do think it would be something that would be would be super valuable. Thank you all for joining me today. It was lovely to see you all again. It was lovely to see my my fellow haircut friend Mark. Thank you. Thank you for joining me, and I will see you around. I'm sure. Otherwise enjoy the rest of your Thursday enjoy the rest of your weekend and I'll see you all next week.