 Everybody. Welcome to extending we commerce like a pro. Um, that name is kind of full of itself. I know I realize that now because, uh, we're just extending WordPress, but we're going to do it a really professional way. Um, I'm going to show y'all kind of how I approach it, um, at modern tribe. So we'll dive right in here. Ric Flair. Every time, every time I pause my head. Um, okay, so I'm Chris Flanagan. I'm a back end developer for modern tribe. Um, I'm a husband and a father. I have two beautiful children. That's my six year old daughter Beatrix and I skating. We wore matching outfits. Um, I love craft beer. I'm in a band. Um, and I live by the beach and I'm on it all the time. So that's my life. I'm about three hours north of here in Sarasota. Uh, I work on enterprise level. We commerce sites very often. Um, one of my main projects I'm working on right now is a massive we commerce site that's going to be released hopefully in the next month or so. Um, I've been working on it for about five years with Wu and I'm still not a master. Um, you know, I'm still constantly Googling and looking for the right filters and trying to figure out the best way to approach things and be performance. Um, we commerce is a big deal. It's the biggest shopping cart out there right now and it's got really, really cool framework inside of it that allows us to do what we want with it and make it our own thing. Um, this site can find me on Twitter. I don't tweet much, but I do get notifications so you can find me on there. Hit me up and that's my website who is Chris.com. This is my first time giving this talk. So you'll bear with me if it seems a little scattered or some slides out of place. You are my guinea pigs. Um, this talk is also php focused. I am a back end developer. I barely ever touched css or js. Um, this is about getting into the nuts and bolts of we commerce and making it function how you want it to. Um, and feel free to interrupt me. I love conversation. I like an open forum style. If you have a question or a note or just want to tell me I'm wrong, then go for it. Um, it's also impossible to present on we commerce and just talk about we commerce. This is going to go a lot to kind of the philosophy behind everything. I developed on wordpress how I structure code how I work with classes and methods and and all that, but we're going to keep it within the we commerce atmosphere. Okay, so these are kind of the five steps we're going to go through. Um, I know we're kind of crunched on time and I have quite a few slides and demos. I want to do, but, um, so I might gloss over some parts a little bit, but again, stop me if you want me to. Uh, we're going to talk about approaching we commerce. What's the goal, you know, kind of preparing and getting ready to start a project in. Uh, we're going to talk about building a framework and how we go about building some big extension for. Uh, how to find what you're looking for. Um, when you know you want to do something in we commerce, how do you approach finding that and doing that. Um, we're going to do some coding. This is also the first time I've ever done this. I'm going to try a set up kind of framework or code and a plug in. And we're going to try to solve some of the needs of that thing together, like googling and whatever right in the code. And, uh, then we'll talk about staying compatible. So what's the goal? Um, that should be your first question that is probably answered by the fact that you're working on a we commerce project. Somebody approached you with an idea, something they need wood to do. You know your goal. Um, let's figure out how we approach reaching that goal. So you've got to have your clear end product in mind. Um, one thing that I had never done much of before working for an agency and with a team is actually having a wireframe and a strategy in place before I even start writing code. And I found that incredibly valuable to know exactly what you need to have done step by step from beginning to end and then going into code and actually do it. Um, at tribe, we're lucky enough, each team has at least one digital strategist and a designer that floats around. So before we even get our tasks to start coding, we have, we know exactly kind of the architecture that we're going to be building. What post types we're going to need, taxonomies, what the, what the user is going to see. We can see the flow and everything before we even start writing the code. And it's very valuable. Um, and when you're approaching a WooCommerce project, you want to know kind of exactly what parts of WooCommerce you're going to be manipulating. Before you even dive in as well, because that's going to make a big difference on how you set up your base framework and then start building your extensions. Uh, so what do we touch? WooCommerce is full of lots of cool things. Um, and lots of things that tie into each other or have their own methods. And you've got to be careful and know exactly which ones, which, which of these things you're going to be manipulating from products and their variations. Their meta, templates, currency pricing and taxes. This is a, this is a big one and a, and very, very complex to work with. And you've got to be very careful approaching it. If you're going to be manipulating the prices or sales prices or the taxes or fees of a product during the checkout flow or when it's an order item or anywhere along this path. Um, there's a lot of different little pieces of meta that tie into each other. And, and just, it's got to be very careful when working through that. Um, what are we going to create? And we're going to make some gateways. Are we going to make our own order statuses? Woo has a nice filter where you can put in all the different, you know, they got processing on hold, complete. You can add as many of your own kind of, of statuses as you want. And then that opens up a world of filters that you can use to manipulate those orders in different ways. Um, for example, on one of our projects, we wanted the user to be able to create a quote. So there's basically like creating an order, but not paying for it. And then they can come back and pay for it at a later time. So we created a custom commerce status called quote or wc dash quote. And that allowed us to have it stored, handle it, how we want to handle it, let them expire. We can do anything we want to it. And it was handled in our own way because of that status. Um, custom tables. Are you going to be using the rest api endpoints? Um, imports and exports, all these different things you can create on top of WooCommerce that are pretty common. And this is just a couple of ideas and problems. Are you going to create problems? That was my little joke. Um, I should have bought a laugh track. Uh, touching one or two things, doing something small, you can just build a simple plug-in and call it a day. Um, but as soon as you start touching multiple different areas of WooCommerce, you need to start thinking about building this out properly. Uh, simple plug-in, you can stick around with 5.2 if you want. You don't need anything crazy. You can use a single file. Just throw your snippets in there with your filters. Um, no reason to make a child theme. Uh, so WooCommerce provides a templating structure within their plug-in that you can mimic in your theme. And it will override its template files like, uh, the cart page or the checkout page with the file that you have in the same structure in your theme. And this is great when you're building a huge project around WooCommerce. But if you're just manipulating a little bit of its functionality, there's no point in setting up a whole child theme and copying the templates over. And then when we update their template, yours is going to be broken. So it's best just to kind of hook in, um, and do your small little tasks. Uh, I'll show you a quick example of a simple plug-in. I just made this one called blue tweaks. Pretty small. Can you see it? Okay. Um, this is it. It's just one file, has an action, and it replaces, uh, where the add to cart button is, it adds a little line of text underneath it. And that's, if that, all you're doing is three or four of these kind of things, then it's easy enough just to set up a simple plug-in file, throw your filters in there, and go for it. Now, I recommend keeping out of your functions file and your theme. Keep your theme your theme and your logic and your plug-ins. Um, but that's what a lot of people actually suggest on online tutorials is throwing in your theme functions file. But I wouldn't do that. I like to preach organization, and that just doesn't feel right. Okay. So let's talk about building a framework. Keep your stuff organized. That's really important. Uh, if you've been developing for a long time, then you've probably gone through the phase where you just create long files of procedural functionality that gets executed every time, and it works. It does what you want it to do, but it's not, it can't grow. It can't handle large amounts of visitors, and it's going to break at some point. So I do it the tribe way. Um, you can do it your way. I'm sure everybody has their methods and how they like to do things organized, but I think the one point is don't be lazy about it. Um, take the time to build things the right way, even if it means it's going to take you an extra hour to structure it the way it should be or whatever. Instead of just cowboy coding and knocking it out. Uh, we use a framework called square one, which is kind of a wrapper around WordPress. Um, it gives us a lot of tools that we use on, on most of our sites. Uh, it wraps, uh, post types in a, in a, in a, in a class that we can use to do extra stuff. Like, and we use a CF for all our meta fields. So it allows us to kind of, um, connect that and, uh, get meta values out differently and handle them differently. It's, it's a really cool framework. Uh, we also use containers and dependency injection, which I'm not going to use in my sample code because it's, it's kind of complex. Um, and not really necessary for most projects, but it works really well for us, um, in our flow. Uh, one note I kind of touched on a second ago is, is keep the theme and themes. If you're, uh, theming your shop and do it in a, in a theme or a child theme, um, use the WooCommerce template structure and keep logic out of your template files and in a plugin. Um, that's one thing I, I, I'm really, um, passionate about is keeping that separation there. Um, your business logic and stuff should be in your plugins. Your themes should be for presenting the content. It should have this html and your css. Um, so I, I'd preach that for WordPress and for WooCommerce and everything. Um, I highly recommend namespacing and auto loading and using modern technology. If you're building a highly distributed plugin and you have to do 5.2, then, you know, you already know what the case is there, but you're missing out on a lot. Um, php7 is, is a huge step forward for the language and, um, the fact that just in general, just namespacing and auto loading your classes cleans up your coding environment so, so quick, like it makes a huge difference. Um, yeah, even if you're working solo, whatever, use version control, um, get is important. Again, even if you're a solo developer, don't, don't tell yourself it's not. It really is. It's a great team tool, but it's also wonderful just for just keeping your code organized. Um, keeping a historical log of what's going on, allowing you to, to work from anywhere, any machine. Um, helps with deployments, you know, uh, instead of having to ftp everything, like, I don't know, I used to ftp everything for like 10 years. That's how I managed code was ftp to file up and down from the server. It was terrible. Um, we like to commit the whole WordPress install with our framework that we use. Um, but we just moved that into composers. So whenever we pull down the framework to start a new website, we run a composer and installs WordPress and a subdirectory and it's, it's a pretty neat setup. Um, document everything. This is something that I learned at, um, tribe, because I didn't document everything. I've worked solo for so long. I just wrote code and wrote code and wrote code. And then when I started inline documenting everything, it made it much easier to work with my own code. Like, it wasn't just for helping others. I wrote something a month ago and I don't know what it did or why it's there a month later. If I left myself a little note, then I can go back and, and see and it's really helpful. So I highly suggest it. Um, okay, this kind of structure thing I'm talking about when building a framework. We'll have, uh, we commerce is over here with all of its classes. And I like to mock those classes or wrappers kind of things in my extension for the ones I need. Like I might just have carton products because my extension only uses those two parts of WooCommerce or only overwrites those two parts. Um, you got to keep your core plugin as well with your utilities and your assets and so forth. Then we have our like post types and taxonomies and metas. Um, and I'll show you an example in a second. I'll pull it up and all this stuff is, is a unit and works back and forth with WooCommerce. Let's see an example. I'll show you now. Okay. Um, I kind of half built this plugin for this presentation. Can you all see that? So in the root directory, I have my core or my main plugin file. Um, all it really does is initiate the core to find some, some things. I bring in this tool post to post plugin. That's really cool. We use it a lot. Well, I say it's really cool. It's really useful. It's kind of written terribly, but it works. Um, I install all of that through composer. I get, uh, I get, uh, I mean, I install my name space and I install the post to post and, uh, all that's in there. And then the main meat of the plug is in the source here. I have a core file that, uh, all it really does is load in my service providers. And this is another concept that tribe taught me is I keep all of my hooks inside these providers. Um, this is slightly different than what I use every day. But it initiates all the classes I need. And it allows me to add all the actions and filters I want to use right here in the service provider. Now that's, that's organization I really like it. That way I don't have hooks and filters being thrown throughout all of my files. But I know where they're contained. I know where this is where I communicate with the internals of the other plugins and wordpress. Um, then we have these post type wrappers and I like to do them for the, uh, we commerce post sites. So I've got like a product here. That went created. I said a product ID. I said which root product it is. And then, um, down here I've got some extra functionality that I'm building it with my extension. So what I'm building here for this demo is a bundle kind of plugin. It allows you to take a product and turn it into a bundle. So you can say connect these products to this one. When you purchase this one, it's this price of this product. But you get all of these other products that would be more expensive if you bought them separately. So, um, I've got a little function for this bundle, uh, get bundle product IDs. Just some stuff that's not in woo. But I feel like belongs with that post type. So I'll show you here where I use it. The cart. And this is another thing I like to do is have a WooCommerce directory and have a class for each. Um, I mean, they do have classes, but they're more of a concept to WooCommerce. The checkout is kind of a concept. The cart, there's a class for it, but it's also a concept of WooCommerce. Um, so when I, I've filtered in here to, this is showing in the cart, right? So when you're in the cart, I want it to look differently. I want it to show what products are part of this bundle. And to do that, instead of, uh, I get the item here and it's got the product ID and I could create a WooCommerce, uh, product object. And do what I do some stuff to it. But I need those extra features that I built into my product class. So here I can make a new product. And when it does that, remember in the constructor, it sets what the woo product is. So if I ever need anything directly from the woo product class, I can do it through this. Um, but it also allows me to use these extra functionality. Is it a bundle? If not, just return the name of it as it is. If it is a bundle, then I get the bundles product IDs. I loop through them. I add some text to display what it is. And, um, then it shows up in the cart. So let's take a look. I don't know why I'm looking up there. I can look right here. So I've got these, uh, three products. Uh, half of a watermelon, a flaney pack, and then this is what I make my bundle, the flaney pack and play. Um, I use post to post to set up a connection between products and products. Um, post to post is a really cool plugin that allows you to just build these small database relationships between different posts. They can be different post types or users. And that way you have this connection system. I mean, you can probably do the same thing with meta or taxonomy, but there's something about it that just feels right when you connect it this way. So over here you can add products into your bundle. It'll search through what I have. I've already added both. So now this bundle has got both items in it. Um, God, keep doing that. I've strained my neck. Uh, I think I've already added it to my cart. What did I break? Oh, I got my break points on one sec. Yeah, see, so here we go. It knows that it's got a bundle in the cart and it searches. It pulls out the ids that are connected to it and lists them underneath. I mean, it's pretty simple functionality, but the framework that put it together to do that is pretty complex. Now if that's all you need it to do, then yeah, make a little plugin file and you can display what you want in the cart. But what we've built is a framework that's going to allow us to do a whole lot more to this. Like during checkout, we're going to need to go get the two products. That are part of that bundle and reduce their stock and put in the order that those are the items that were ordered. Don't actually put a product bundle item into the order because it's just all it is is a basket. It's not the actual products. Um, but it's nice to let the admin kind of manage those bundles like they are actual products. Let me see here. I'm going to go back to the slides and then try to get through those real fast. And then we'll do some coding. Again, if you have any questions along the way or want to talk about your day, just let me know hooking up. All right. So we want to talk about finding our actions in our filters. Nail down exactly what you want to happen when you want it to happen. Find the most appropriate filter action. That's kind of one of the most challenging parts because we commerce gives you so many options knowing which filter or action you want to use is the best takes time. You need to think about it. You need to think about what's happening before what's happening after your point of time in the execution that you're going to be plugging in code. Priority. Don't forget that the filter priorities are really important too. If you have a lot of third party. We'll plug ins in there. You have no idea how many filters might be manipulating the same data that you're manipulating. So it's good to track that down. PHP storm and other IDs allow you to search an entire code database for things. So you can search for the filter and see where other people are using it, what that priority is, and make sure that you have yours in the right space of time. Dynamic hooks can make things troubling. So hooks don't have to be just text that you can search. They can use variables, combinations of variables and text. That's how gateways get loaded. They can make it hard to track down. So it's a challenge. WooCommerce has quite a few of them. Another trick that WooCommerce plays on us is this multiple path to get to the same destination. WooCommerce changed a lot in the past few years to where it's using a lot of ajax for its functionality. So that flow can sometimes be different than if you aren't using ajax with your WooCommerce setup. The biggest culprit I found recently was that when you go to pay for an order outside of the normal checkout flow, It uses what they call their short code order form, and it submits a form to the server. It does a page reload and everything. Whereas on a normal checkout flow, it confirms the order in ajax and sends you to the thank you page. So if you're trying to do something that happens during the checkout process, and all you've accounted for is the main flow that people go through, Then you're going to wind up missing orders that your code should be executed on. So you have to make sure you have all paths covered that WooCommerce can take to get to that end spot. Like this is some code i had to write where i had to have two actions doing basically the same thing. The checkout validation worked through the ajax and validated some custom fields i had where the WooCommerce before pay action is called in the short code functionality that they use. So i have to have my own function for that because i have to check that to make sure it's actually the short code going and then i call the same exact function that the normal one does. It's kind of a pain and WooCommerce is pretty good about keeping their hooks in place for all the different flows, but there are things like this that stand out. This one, i just ran into this one last week. You can set a product to category visibility hidden in WooCommerce, and this is supposed to make it not show up in your shop and in your catalog. It's kind of like just having a hidden post that you don't want people to see, but it does not filter out the rest api, and this is actually intended. They don't want to be touching things that i remember i was reading the ticket on github, but they feel like they shouldn't need to put this functionality in place for rest api calls. Because the rest api does its own thing and anyway, so i had no idea and we hidden products were showing up on a customer site. Fortunately, it's not launched yet and they found that and we fixed it with a pre get post filter. We added in this product visibility, which turns out it's a taxonomy and i had no idea. I'm like, where's the setting getting set because i couldn't find it in the post table or the post meta table. And then when i found that ticket on github, i realized it's a taxonomy they have that they don't really display as a taxonomy, which now i think about it. Reports are possibly my biggest issue. It's a really cool feature that they have in there. It's nice that a free plugin comes with a reporting system with graphs and dates and so forth. But i had to do some work on it where a client wanted to remove their fees. They didn't want their fees showing up in the report. They didn't want it counting towards their books or their calculations or whatever. They're in japan, so they work a little differently financially than we do. And trying to get that out was a nightmare. Reports are just one long giant sql query with calculations in it and it's a royal pain to try to manipulate. They give you a filter to adjust the where or the joins and all that. I almost just made an extended class of reports and built all the functionality out again. But fortunately we were able to get it to the query to do what we needed. And it's really a big pain to work with. There are some cool third party reports plugins out there, though. I haven't used them, but i've heard about them. I heard they're really, really slick. Random slide. I guess we'll talk about it. Closures for filters. So this is something i was doing the other day. And there's kind of a little something to teach you. You can put a function into a variable. Add a filter right after using that function. Do something you need to do and then remove it immediately after. And that can be really, really useful. I did this. It took me a little while to figure out how to do it correctly. Like we needed some fields, the sites in japanese. And we needed to show just one part untranslated and still in english on the amount in my account page. So the thing to do was add this filter, turn off the text domain, Then turn it back on right after. It turns out i was doing it way more complicated and needed to be. Just like this. But that happens. And when you realize it, do it. Change the code. Don't be lazy. Using the right tools. We talked about this a little bit. But i highly recommend php storm. There's other good id's out there, though, too. The thing is x debug and break points and having the ability to search your files and track down functions. Through your idd is extremely helpful and saves a ton of time. I used notepad plus plus for 12 years. Not even knowing there was better tools out there. Then i met chris wegman who's in here and he told me to get php storm. So i did. And that changed my life and my development. Yeah, highly recommend. Use a local development setup. That's again something most of you probably do but i didn't for a very long time. Let's code. I've got these slides on my website. You can download the example with commerce. So let's look for, i have a couple of to-dos here. What time is it? All right. So i got this little to-do list. Again, this is my first time doing a live coding, trying to figure it out thing. If it sucks, then you'll just tell me and i'll move on to something else. But i was going to say, let's pick one of these guys. How about allow variation selection? So one thing i was not accounting for at first when i was setting this up and then realized it's going to be needed. I'm going to pull this out of my cart. If you're buying a bundle, and the bundle includes a variable product, like this one, has my beautiful picture on it. You can choose different skins for the flanny pack. But when you're buying a bundle, there's no option to pick one of those. So we have to inject that into the bundle product. So what would be the best way to do that? Let's pull up the bundle. Absolutely. The thing that you need to figure out first is what's the best action or filter to use to put that out there. And then we've got to figure out, using the variation id, how to display it. Okay, so i think you'd want it on this page, just like you're buying a variable product. I've already hooked into the before add cart button, so we could probably just do that again. But for organization's sake, i'm not going to add the filter again. Not in this one. Where was that? Oh, no, that was in my tiny little mini plug-in. So yeah, we're going to use that filter. This guy here. WooCommerce after add to cart form. Wait, no, that wouldn't be good because we want the form. So one good way to track down a filter you need, especially in a situation like this or in action, Look at the WooCommerce template files. They have it right there in the root directory of their plug-in template. We want to see a single product. Look at that, there's an add to cart directory. This will house, we can see exactly how they display it and what they... Let's just look at a simple one. We can see what filters and hooks they have. So they have this before add to cart button action. That can be a good one because we want to make sure it's still within the form tags Because when they add this to their cart, we're going to need to grab that field That they select and make sure we add the right variation option. So probably not after quantity after the button. I think, well, no, we want the add to cart button. Probably after quantity. Let's try that. So we're going to go over here and add another filter. This one will be for... It won't be cart. It'll be shop. Getting pretty boring. Yeah, I guess this is kind of done. Are y'all enjoying this? Y'all want to just keep talking about WooCommerce? Okay, yeah, let's do that. Thank y'all for letting me experiment. I know. Matt's popping up when we get a good seat. All right. Let's talk about staying compatible. You're going to want to use core woo functions. Don't feel like you have to rebuild the wheel when woo provides All these awesome tools like for you to just use at your command. It also helps because when WooCommerce updates and starts Deprecating functions and so forth, you will have time to adjust And to change because you're using something that they will support for a while. When they're going to remove it, they'll give you time and let you know. The wcobject function is really useful. It returns the core WooCommerce object which has your cart And all sorts of cool things like that. With the custom product class that i made, i'm only going to put Functionality in there that woo doesn't have. There's no reason to put something that we can get straight out of the Woo's main object class for the product when it's already there. And if they're going to change how that works, we don't want to have some Function that we've built that's doing that and then breaks All of a sudden because woo's changed how that works all together. If you don't manipulate data with wpdb, you don't want to do You just use the functions. They're there for a reason. And they're there to keep your site running when they make changes. The change log is your friend. New versions come out. Make sure you read through the change log. Look for deprecated functions. Search your code base and make sure that you Update the ones that you have that are deprecated. WooCommerce makes this easy because if you go to the Deprecated function, they usually have in-line documentation Telling you how to do it the right way now or they have it within That deprecated function. Always update locally first. I'd never turn on auto update if you have a customized word press site. Auto updating anything is a really bad idea. It's going to break stuff unless you're just using a Straight-up vanilla word press website. Let's talk about that. The in-line documentation is really good. Templates change, so like i mentioned with the simple plug-in, Don't be making a custom theme with WooCommerce overriding Template files unless that's your plan is to make a big themed Word press store. Well, i didn't need up some time Because i thought the coding was kind of boring. Do y'all have any questions or want to chat about anything? Yes, sir. As far as hosting? Well, 400 products really isn't that much. I mean, it feels like a lot. It's 400 products. But their sites, the japanese site i work on has like 5,000 Products. It's ridiculous. It's got tons of variations. So WooCommerce can handle that Pretty well. You don't have to do too much Optimization, but definitely find a good host. You wouldn't want to do that on shared hosting. Site grounds, middle-tier packages are pretty good. If it's going to be a money-making site and has the Potential to grow, then use somebody like wp-engine. They're kind of one of the standards. Or if you can get a server guy to set you something up, you Could use amazon services. We have a lot of clients on Wp-engine, but we're starting to try to migrate to our own Amazon instances. Yes, sir. Say that again? Yeah, yeah. Throw all five of them into a single plugin. I just called that one tweaks. You can put them all on there. I just like to keep that logic separated from the theme. It could be your theme, your view. Yeah, yeah. That should stay clean. Yes, sir? A consignment? What do you mean by that? Oh, yeah, absolutely. If you have a decent developer doing Dynamic products like that is not a big deal. And we will handle the checkout process. Great. Yes, sir? Freight shipping? I haven't. I know that Woo includes some... Okay, cool. Yes. Yeah, I've worked with subscriptions. And official WooCommerce add-ons are really, Really well-built for extending, just like WooCore is. So they've got great filters and actions all through them.