Create a Contact Form Plugin In WordPress | John Morris | Skillshare

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Create a Contact Form Plugin In WordPress

teacher avatar John Morris, I help freelancers get clients.

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

13 Lessons (2h 47m)
    • 1. Introduction: What You're Going to Build

      4:00
    • 2. Lesson 1: Folder Structure and Plugin Header

      11:47
    • 3. Lesson 2: Main Plugin Class Setup

      5:27
    • 4. Lesson 3: Build the Contact Form

      36:57
    • 5. Lesson 4: Add the Shortcode

      10:01
    • 6. Lesson 5: Enqueue Styles

      8:27
    • 7. Lesson 6: Create the Custom Post Type

      22:59
    • 8. Lesson 7: Inserting Form Submissions

      31:29
    • 9. Lesson 8: Send the Notification Email

      10:03
    • 10. Lesson 9: Handling Redirects In WordPress

      4:43
    • 11. Lesson 10: Adding Custom Columns

      18:18
    • 12. Final Thoughts

      1:32
    • 13. Next Steps

      1:16
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

474

Students

1

Project

About This Class

In this course, I show you how to build a contact form plugin in WordPress. The idea here is for this to be an introduction to building WordPress plugins. So, it's not everything you could ever want know, but you will learn some of the basics of WordPress plugin-building. Here's a run-down of the things you'll learn:

  • How to Organize Your Files and Folders
  • The WordPress Plugin Header
  • Using PHP Classes With WordPress
  • How to Build a Contact Form
  • WordPress Action and Filter Hooks
  • How to Create WordPress Shortcodes
  • How to Add Custom CSS and JavaScript In WordPress
  • How to Create a Custom Post Type
  • The Proper Way to Handle Form Submissions
  • Inserting Posts Into a Custom Post Type
  • How to Send Emails In WordPress
  • Handling Redirects With WordPress
  • The Right Way to Add URL Parameters
  • How to Add Custom Columns To a Posts Table

These are things you might expect to find in a course like this, but are NOT in here:

  • Creating custom tables in WordPress
  • Inserting data into custom table
  • Adding custom menus
  • Working with $wpdb

Basically, you can choose between using custom post types or custom database tables when storing data in WordPress. In most cases, custom post types are the way to go. So, that's what I chose to do here. That's the scope of this particular course. Other courses I do, I may go into custom tables. In any case, when you use custom post types, you don't need to do any of the things listed above. WordPress does most of it for you... which is the benefit of custom post types.

Source code for the plugin is included.

Meet Your Teacher

Teacher Profile Image

John Morris

I help freelancers get clients.

Teacher

Click here to start this class

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Introduction: What You're Going to Build: Hey there. John Morrissey, John Morse online dot com And welcome to this WordPress plug in course, this one. We're going to be building a contact form, and I have sort of cheekily given this the name, the simplest, the world's simplest contact form. So it's gonna be a really basic sort of contact form that allows you to have a form on your page on your WordPress site in a page, collect that data and then be able to view it in your back. And and really not a lot more than that. And the whole idea of this course is to introduce you to WordPress. Plug in building. So this isn't gonna be a complete a dizzy everything you could ever want to know sort of thing. It's really meant as an introduction to show you some of the basic concepts how you put your folder structure together, how you actually even connect ah, plug in with WordPress and get things to work together. And some of the basic built in functions that you might use and so forth. So really meant is an introduction. And then hopefully I'll be able to do future courses where I sort of build upon what we do here. So with that said, let me go ahead and show you what? Just what This does real quick. So we have, as I mentioned here, we have a contact form. This is embedded into a page on my site. Using a short code you can see right here. And when we come here and we'll just fill this out real simply so we'll put my name. Ah, that's fine. Will do website and we'll just take something like this. So name, email, website and message and will hit. Submit and you can see it says your message was submitted successfully. And if we come over here on in the menu in WordPress, this adds a new menu item here called feedback. Now, you see, I have this one down here. This is actually come from my theme that I'm using on this site. So just ignore this when you see this throughout the tutorial, this is the one that we're looking at. So if we look at feedback and we we go to this page, you can see here that I now have some feedback in here and a couple things I want to show you will drag this over. You see that we have some custom column. So it actually shows the email, the website and the excerpt. We can click on this, and this will take us into the actual feedback that was posted. You can see this actually looks like a WordPress post will talk about sort of why that is and what we're doing here to make it look like that. But you can read the message you could edit. You could pretty much do anything that you could with a post. You can see we have the email here. If you look down on the bottom left down here, you'll see when I hover over that, it says mail too. And then we have the website. That's clickable as well that we could go to so pretty straightforward and basic, but allows again you put a form on your page. People can submit that form. You get feedback here that you can then read through. So very, very, very simple. It also actually, if we go over to see if I can find my mailbox here and if we come up here Ah, got some email in here that. Maybe. Okay, so if we come here, you can see that I have this message that got sent as well. So you have new feedback here, the details, and then you can click this so I'll go ahead and click that and you can see Ah, here on my site. It takes me right to the to the that feedback that reply or whatever, so stores it in the in. WordPress also sends an email to any admin is, well, actually loop through and get all the ad mons and send them an email so pretty straightforward. That's what the plug in does. So let's sort of dive in and talk about how to do this. So the first thing that we need to talk about 2. Lesson 1: Folder Structure and Plugin Header: let's sort of dive in and talk about how to do this. So the first thing that we need to talk about is folder structure. So we're all familiar with wordpress, then you'll this will look familiar to you. But in WordPress, you have these sort of files in the root folder, every install WordPress. And then you have this WP content folder. This is where our plug ins, they're gonna go. And in here you're gonna have a plug ins and the themes and upgrade and upload. You may have others, depending on what plug ins you haven't sold. But we want the plug ins folder, and this is where we're going to put our plug. And so the first thing that we need to new do is creating new folder. So we're gonna call this folder. We'll just call this John Morris forms, keep it pretty simple. And then we're gonna put all of our files in here. Now, the very first file that you need is you need one that matches the folder name. So we're going to do John Morris dash forms dot PHP. So that's how WordPress knows. You know, has all this stuff. It does to be able to read the folders or files that are in this plug INS folder. And when it sees a folder the way it knows what the main plug in file is, these two things have the same name. Okay, so this John Morris stash forms dot PHP is going to be our main plug in file. This is the file that WordPress is gonna look at first. This is where we're gonna include any other files that we use into it all that sort of thing so that this is, ah, pretty important file. The next thing I'm going to do is just sort of give you some basic structure. We're not actually gonna use all of this structure throughout the course. We're not going to use every single one of these folders, but it will give you sort of a baseline that you can work from. And this is I would say this is the generally recommended folder structure as you get into more complex plug ins and so forth, this is probably gonna You may have to change this. This may not be adequate, but sort of to start out. This is what's recommended. So the first folder we're going to create is one called admin, And this is where we're gonna put all of our admin stuff. We'll talk about that in a second, will create another one called includes and we'll create another one called public. So the idea here is we're all of our anything related to stuff we're gonna do in the back end of WordPress is going to be put in our admin folder. Anything in terms of CSS and JavaScript and images that we're going to be using on the front end is going to be put in this public folder, and then it's a little bit sort of different, but our main actual any sort of classes that we're gonna include or we're gonna create a class and we're going to use that in the front end. Or maybe it's a common class that's all going to go inside of includes here, and we have We have some examples of this as we go through this so you'll get to see this so beyond that. Then, in our admin folder, we're gonna create some sub folders. So the 1st 1 we're going to create is called CSS. The next one is images. And the next one is for, as you might guess, job script. Okay, now it so happens that in this plug in, we're not actually going to use any of these. But you do want to separate just to keep your head sort of straight. You want to separate where you store your CSS files and JavaScript files and images files for stuff you're going to use in the admin from stuff you're going to use on the front end . So as you might guess, our public folders actually going to have the exact same folder structure. So we're going to create CSS images and we will create Js. So you put those, uh, those appropriate files and in each one of these, depending on whether you're going to use in the admin, are you going to use the in the public here? Right. So that's our our basic structure. The last thing that we're going to do here. And no, this is just something that sort of I know this. I did some research before I wrote this plug in, but I wanted to find one of the things we need when you're building forms you have all of the input fields and you can hand code them all. But a lot of times that can lead to inconsistencies across fields and so forth. And it's just a lot of extra coating and there happens to be PHP classes out there that will do this for you. So I found one. I'm not saying this is the one you absolutely have to use. I'm not saying this is the best one. This is just the one that the way it worked, I sort of liked. So I have the link in the file. But if we come over here, the file download that you're going to get has this link in it. But this is a pretty straightforward ah PHP class that we can use here. Okay. And I just sort of like the way it works with you add the way you add inputs the way that you set attributes and so forth. And it No, it's a little older, but it was really stable and worked well, so I like this. So the thing to do is we need this file right here. And so what I normally do is I just take this, and I'll just select all this and copy it on. We can come back over here, and this is going to go in our includes here. Okay, so this is ah, sort of a class that we're gonna be pulling into our main plug in to you. So that would sort of fit under this idea of includes. And so I'm gonna create a new file. I could just download the file, but I just ah, for for naming sake. And it's just a little bit easier for me to do it this way. So builder dot PHP. That's what we're gonna call this file and will open this, and I'll just paste in that code. Now, one of the things you have to be careful of is this down here. So I just remove this extra code and we look good to go here, and then the thing you'll notice he doesn't have the URL on here. I'm gonna grab this u R l just for you. And I'm gonna dump that in here so that you can find all the documentation for this. All right, so this is our main ah, plug in sort of form field class that we're going to use this is gonna help us generate the form fields again. I would recommend if you want to really get into tweaking this to come through and read through the doc documentation. But you can see here essentially, what you do is the first and CNC to new instance of this PHP inform builder class and then you can come down here and you can set the attributes for the form itself. So the action the U. R L the method the enclosure type would sort of mark up. You want to use class I d etcetera all these different ones that you can use down here and then when you want to use ah, add inputs to the form you use, add input and you can set some options. And you have all of these different options you can set for every input it supports text fields, text areas, select box check box radio buttons, etcetera. And then, once you're form is all you've added all your inputs, you just call build form and it will actually generate the output. So that's what we're going to do here. Ah, as we as we build our form. But that's our our main sort of class here. We don't really need this anymore. We're just gonna We're gonna call it and use it so we don't really need toe. Look at it anymore. All right, so that's sort of our basic starting structure. We have our folder structure. We have our main plug, plug and file built. We have our big our main class for building the fields that we need included. The last thing that we need to do sort of four initial set up is we need to do the plug in header. So wordpress wordpress requires that you use a certain sort of plug in hitter. Now, there's a lot to this. I already have one here. You can also come over and just go. WordPress plug in header and you will see right here. Header requirements, and it will give you if you expand this, it'll give you You could just copy and paste this. Okay? And then you can change these according to what you need. So no need to remember all this sort of thing, but I already have one. So that I have for this through. I'm just going to use that instead of retyping it'll Okay, so of course, we start off with opening PHP tags and then we have our, ah, our plugging header here. So the plug in name sort of self explanatory. What's the name of the plug in the U. R l of the plug in? So if you were uploading on the WordPress repository, you might use the plug in that you get when you do that, or if you selling it on your own site, you might link to the sales page forward. Or maybe the support page, etcetera, wherever you want to the home of the actual plug in to be. No, I'm not selling this or whatever. I may. Once I sort of released this course. I'm a post change this link to that the sort of sales page for the course. But again, just whatever you want the that that to be a description of it a Z you can see here this example Plug in. I'll sort of emphasize this is meant purely as a training aid, not for use in production environments, although I know a lot of people try to do that. So I did try to write this toe where it could just be used. Ah, the version ing the version number. I have the date here. When I started working on this, you could have ah, sort of aversion ing system that you want to use. 0.1 point 02 And then you get to 1.11 point two all that sort of thing. However, you wanna version it out here. Author Name, if that's your name. The author. U R l ah, the GPL licensing. This is pretty much, I would say at this point, required for wordpress plug ins. I mean, I'm not the licensee expert here, but I pretty much just always used this here. I don't know that there's really any way around that text domain is gonna be for when we get into a localization. We're not really gonna cover that. Too heavy in here. We have some spots where we're going to to set it up to do that, But, um and you always want to do that when you're building with your plug ins, but we're not actually gonna create, um, a localization file here, and then domain path is basically where your language files are going to be stored, so these two things sort of go together. So this, essentially, let's WordPress know that when we do the localization that the the the text that's being output is being output by this plug in. And then if there's it knows toe, look in this file for any sort of language files, um, then it has its whole system for doing that. So that's what these two lines are. So but that's you that's your stored sort of standard plug in header. So this kind of gives you a basic shell of your WordPress plug in and and now we can sort of start building from here. So the first thing that that we want to do 3. Lesson 2: Main Plugin Class Setup: So the first thing that that we want to do is we need to include our files that we're going to need. So the first file that we need is the one that we just sort of we just put in here. So we're gonna do require once, and we're gonna do dir and we're going to reference our includes file, and we're going to include our form builder class like this. Now, a couple things here First off, when writing WordPress code, it's sort of the WordPress. WordPress has its own coding standards, and one of the things you do is whenever you have parentheses after were after that opening parentheses, you have a space. And before the closing parentheses, you have a space. So you sort of see that done quite a bit. As I go through this, that's just a WordPress standard. I try to follow as best I can. Um, so just keep that in mind as we're doing this. Also, some of you have may seem the use of dirt name that that PHP function, and then the file constant, uh, and that will help you get the nay, the the path to the current directory. But as of I think it's PHP 5.3. You can just use Dural like this. It basically does the same thing. So it's a little bit of a short coat shortcut there. All right, so that's gonna include our main ah, form builder class that we need. Now we need to write our main plug in class, and we're going to sort of build the show first. And then we are going to Ah, fill that out as we go through the rest of the course. So they're ah, phew methods that we're gonna need that we're gonna use in doing this. And so will sort of lay that out first. So we're gonna create our class of class, doesn't exist, and with WordPress is is pretty important that you do this because this plug and could be installed on a word person soul that has a bunch of other plug ins, and so you need to make sure that you avoid any any naming conflict. So you just want to check to make sure that the class it doesn't exist and of course, you prefix it toe to make sure that you know it doesn't that that deems not gonna exist. There's, ah lot lower likelihood that someone's going to use the prefix J M o on their plugging class. So I'm probably safe there. But you still always want to check so that it doesn't trigger a fatal error. The worst thing you could have happened is someone installed your plug in they go to activate it and that trickles of fatal air because you have a naming conflict. And a lot of times people just on install your plug in and be done, whereas if they install it, they activate it. And there was a naming conflict. But you used this check here, your plug in will. Still you're plugging will still activate. But it just know nothing will show up, which is better than triggering a fatal air. And then they'll probably be like, OK, nothing shown up and then contact you and you could figure it out from there. So again, that's why we want we want to do this. So now we're gonna actually create our class. We're gonna again call it J mo forms and again, Like I said, we're just going to lay out some of the main functions to start off with. So we're gonna have a constructor and our constructors where we're going to do basically most of the loading for a plug in. We'll talk about that. Short codes and our all of our hooks will talk to Hooks just here in a second. We're also going to be using We're gonna have some CSS on the front end of this. So we will. We need a function to in in Q all of our styles properly. We'll talk about that when we get to it. So that's what this method is. We also need one to actually build our form, and this is going to be the one that handles are short code. And so we need to pass in this ATS parameter here, and we'll talk about that when we get to that. And finally, we're going to have a form handler when the form is submitted. Then we need to handle the data and store properly and so forth. So we'll call this form handler. And of course, again, we'll talk about that when we get to that. So those are four main methods, and then, of course, we need to once we're all done, Stephen. See an instance of this class. Okay, so that's that's our main plug in class. These are the four methods that we're gonna we're gonna work with now. There's gonna be a couple of these gonna have quite a bit to them. Some will be a little bit shorter and so forth, but we'll walk through that Ah, as we go here and then we're gonna So what I'm gonna do is I'm gonna do the front end sort of display of the form first, and then we'll talk about and get to how we're going to do the admin part of that and, well, sort of walk through all of that as we go here. So the first thing that that I want to do here 4. Lesson 3: Build the Contact Form: So the first thing that that I want to do here is actually build the form. So that's sort of the most important part of all of this. And so that's what I want to start with. So we're gonna start with this form method here. And so now there's a number of things that that we know we need to do here. But when this for miss submitted Ah, one of the things that that we need to do is we need to make sure that what were submitted the way we're going to submit this, we're gonna use sort of the built in. We're not going to create our own sort of post routine. We're going to use his words. WordPress is built in form handling, and so we need to make sure, though what? What that essentially does is when you submit it to you're gonna smit it to a page on admin page WordPress called admin dot posts admin, dash, post op PHP. So that's actually gonna be submitted to another girl. And then we need to be able to redirect back to whatever page this was. This form was submitted from so that we can show our status message. So to the user, it looks like the page just submits to itself but actually goes to a WordPress admin page that is built for handling submission of form data. And then it will redirect back to, ah, the page that it came from. But we need to tell admin dash, post which page it came from. So we're gonna have a way that we do that. But in order to do that, one of the first things that we need to do is we need to globalize the post that were on. So we have the post I d ah, and weaken can send that through. We also need to handle our any are short code. If you're not familiar with short codes Ah, short codes can have parameters, so you can do things like, Ah, it's just a honeypot equals true. You can add parameters like this, and you can have as many as you want in a short code. And that is how someone can can set you can insure, insert a short code and have options so you could have you know, different forms of different options for your form or so forth now for this, We're again. We're keeping it pretty basic. We are going to I'm going to show you. Ah, I'm gonna have some. Some optional attributes were not actually going to use them in the form when we do this. But just to show you how you actually handle ah, short codes in inside of WordPress. So WordPress has this function called short code attributes. So we're gonna I'm gonna write this we're gonna do ATS equals and we're going to do short code at's. This is a built in wordpress function, and we will do this and inside this, then we're gonna create an array and in the array, we're going to essentially set some some some standard options here. So we'll do. Let's go ahead and push this back here and we're going to do That's and then we're gonna say j mo form, and we can actually back this up, too. All right, so if you look at this, we're calling the short code at ATS function, and we're passing in an array for the first parameter. We're passing in our ATS from what was submitted to this, this short code handler, and then we're giving this unnamed. This essentially allows other plug ins to filter the these attributes. So this makes this extensible. So what is this ATS? Well, this is if we come back over here, and if we said now, add honeypot equals true when this page loads WordPress actually takes this and it takes all of these parameters and puts them into an array. And we'll talk about how all that data ultimately gets to this method here in a second. But it creates though these attributes it turns them into a PHP array and sends them to this method in this ATS. So this ATS variable is actually an array, and it's got all of these in an associative fashion. So add honey pot is the first element. It's set to true whatever other ah parameters you'd have in the short code will be in this array. So it's short code at allows us to do is allows us to set defaults because we may want to allow, add honeypot and let them. You set that option. But we also want to have a default, and so that's what this does. So what we do is just is this simply right here. We set our defaults, so we're gonna That's what this array is Add honeypot, and we are going to set it to false by default. Okay, So what? Short out court ADT's short Kodak's is going to do is it's gonna look at this array that was submitted from what will came in and short code, and it's gonna look at this array of defaults. And if this ah, this option, this element exists in this array, it's going toe overwrite this default with what was submitted from the short coat. However, if it doesn't exist in this array that was submitted from the short code is going to use this default. So this array right here is essentially your defaults for for your show short codes, that's the big That's really the sort of the big thing when it comes to handling. Ah, short code is dealing with the defaults versus what is submitted from, or what is added to the parameters in this short code here. So that's this is this is essentially short code handling 101 right here. Is this this section right here? So that's how you do it and what your end up with is you end up with this is all set to equal. You set up your end up with, ah, this ATS array, which stands for attributes. You end up with this at at Saray that has all of your options. It's done all of the filtering through the defaults And what set in the short code, etcetera. And you now have an array of attributes for this particular short code here. So you can now trust what you have from this. Okay, now, again, we're not gonna actually use this, and I mean we are, but we're not gonna I submit that parameter in our short code here, but I wanted to show you this so that because short codes is sort of a big thing that you're gonna deal with inside of WordPress. All right, so now the next thing that we need to do is we need to start building our four. Remember, this is the page where we're gonna fill out our form. So the first thing that we need to do is we need to instance e eight, the form class. So this is our class that we included right up here. So If you remember from the Hub Post, you just do something simple. Like form equals new, and it's PHP form, form, builder. And we're not going to set any. You can set some of the attributes when you when you call this, But we're just going to use the set attributes option to do this. So this gets us going with our four builder. Next thing we need to do set some some attributes. We're going to set our form options, and we're gonna set to here. So the 1st 1 is our action block. Remember? I said we're gonna We're gonna send this to admin dash post dot PHP. So we're gonna have wordpress uses built inform handling here. So we need to set the action attributes here. So we're gonna do set at and again this this. I just want to make sure this all this set at right here. This isn't wordpress. This is coming from our form builder right here. This is how this was built. So I wanna make sure that that's clear. The difference between built in wordpress functions and what's coming from our PHP form. Boulder class. So set at. And we're going to set the action attributes, and we are going to set that we need to set that to admin post op PHP. So WordPress has a built in function that you can use to easily get admin pages. So we do. It's called admin underscore. U R l Now, if you just use that by default, that's going to send you essentially to the dashboard page Ah, in WordPress, which isn't what we want. So what you can do with this function is you can pass in the slug or the seepage, the ending You are all the path of the pay, the admin page that you want. So in this case, we want admin dash post dot PHP. And so what this is gonna dio is this is going to give us all of this is going to give us what we need essentially to, ah to to create the WordPress, you or else. So this is going to do the hard work of figuring out OK, what's the U. R l the domain that it's installed in? What's the word? Where's wordpress? And what's the WordPress path? Maybe it's in a sub fold earth. It's three sub folders deep or whatever. We don't have to worry about any of that. We just say use admin, u r l wordpress nose. And then we say we want this admin page and all the different menu items in WordPress. So if we come over here no posts as edit dot PHP, this is upload dot PHP. This is edit dot PHP with the post typeset to page. This is at a comment. So all of these different admin pages have a different ending sort of area here. This happens to be the one that, uh, that accepts form data that we can use now. One other thing that that we want to do here is we're gonna again We're press as this escape u R l built in function and this Just make sure that this is essentially safe when we put it into our form here. So we're gonna use escape Buehrle around this admin u r l here. So it's just ah again making sure it's safe for for use in our code here. All right, so that sets the action block for form. Now, the next thing that we need to set is we did this honeypot thing here. We need to make sure that we set that for our form. And again, the ad honeypot option comes from this. If you see right here down here, add honeypot is one of the options that you can use from this PHP class. So we just want to make sure no doing this right here gets everything set up and gets our defaults and all that sort of set up. But we still need to tie it into our actual form builder here. So we're gonna dio form and set at. And it was the ad honeypot option. And then we're gonna set that to ATS and honey pot that what was what came from up here, whether it's the default or what was passed through the short code. So that's how you tie something from the short code through your your method here into the actual form, so that if we set this to true, if you came and did add honeypot equals true, that would override this ad. Honeypot equals false. And now we have a honeypot added to here. Okay, so that's how you accept options in your short codes. I know I'm sort of hammering that. But it's a really big thing when you're working with WordPress pub plug ins, a lot of plug ins that you see out there, you short codes. We haven't actually tied this Ah, through yet. We'll show you had to do that once we get done building the form. But again, that's how you sort of tie things together. All right, Next, we're gonna add our form inputs. So on our form inputs. And you remember, from over here we use this add input method here, and we have a bunch of different options. So Argument one is a human readable label that is, Parson, turn the name and I d If these options aren't explicates explicitly set Argument two is an array of settings. So this is essentially where we can say if we want, you know, a text field or if we want ah, select box. And if we want to select box, then we're going to add in a, um our options will be a part of what we can add there. And then argument three is a string valid for a Chmela attribute uses the name and I d Okay , so it has three different options. These are all of the different options you can set for argument number two. Okay, for this array right here. So type name I d. Etcetera. So again, it's just a just a foreign builders gonna build the inputs for us. So we're going to do as far as what you can see on the front end. We're going to do name, email, website and message as you, as you saw from from this form right here. We also need some hidden fields that we're going to do. So we need We need an action block and we'll talk about that. Ah, here in just a second. We also need a nonce so that we can verify our form. And as I mentioned earlier, we need Ah, redirect. So that redirect is is what's gonna allow it when it gets submitted to admin Post. We're gonna send the URL that that submission came from to admin post, so that if the in our form handler which will talk about down here, which is going to be this method, we can create a redirect back to the original post. Okay, so let's actually go ahead and do the inputs first. Okay, so we'll do the public facing one, so we'll start with name will do form, add input, and we are going to do We're gonna call this name. This is so this is the human readable label that's going to show right here. Okay, So that this right here is what we're This first option is then remember, the second argument is an array of options. So do array, and we'll come down here. And the third option is then sort of the label for is essentially the name of the form input. So when you create a form and you you you get you know, you have to give it a name so that when you submit it to your post data Ah, it that the element in the array that stores this data has this particular name. So Ah, that's what this is. So this is the human readable name. This is the name in the actual input. We just inspect this real quick, so you see, name equals name. That's what this is here. Okay, so this is the name. And then this array in here is gonna be the the settings. The attributes for this particular input. So we're gonna do type equals text and we are going to do a placeholder, and we will set that to enter your name. And then we're gonna set whether this is required or not so required and true. And I have a mistake here. All right, So, um, that's how we added input. We, whatever the label is, is the first option. The second option is array of essentially the input attributes. So the type the place over the required basically anything you want, you can see all of them are here. Type Name I d label value placeholder class. If it's a select box or a radio or check box, you have this options, which is an array where you set the actual options. Um, men, Max step. I mean, there's all sorts of different options here. We're not using all of them. You don't have to use all of them, but essentially, this is going to add in all of your inputs. Now, I'm gonna sort of fast forward here a little bit just for for time sake, because a lot of these public facing one's air actually really similar. So we have name we have email, we set type to email. Placeholders entering email address were acquired Equals true. And this is set to email. So you can see these are all really pretty similar. Except for we just changed in email and we use the type of email here in this website. The type is said to you r l placeholders UBS. And on your website you Earl, we're not requiring this. And then again, the name is set the website and then our message This is a text area are place holders sent to enter your message. This is required. And again, our name is called a message. So again, I just want didn't want toe bog you down with with me typing all those out. So I pasted those in there, but you can see they follow that that same pattern there, So I think pretty straightforward there. Now we have again three hidden inputs that we that we need to talk about. So the 1st 1 is, um, what we're gonna call the action. So we're gonna do form, do add input, and we're gonna call this action and it's hidden so we don't need Ah, the label doesn't really matter too much. But again, we're gonna do array. I do this and we'll give this again the the name of action and then in our ray here are type is going to be set hidden. So this is Ah, if you're not familiar with it hidden for hidden inputs. Essentially, this is this is, um, something that you could have submitted with your form, but it doesn't show up. It's not an edit. A ble input on here. It justice submitted, sort of in the background. If we look over here, you can see we have input. The name is set to action type equals hidden. The value equals J mo contact form. You don't see that anywhere on here. So this is a hidden field, and we're going to, as you saw set the next option here, which is we're gonna set the value to J mo contact form. And the reason why that we need this is again goes back to what we were talking about with how this for miss submitted. So again, this form is gonna be submitted to Admin post. And so that admin post takes form submissions from all sorts of different forms throughout WordPress. So we need a way to know when we go to our form handler down here, we needed a way to be able to pull out the are particular form submissions that we want to handle so we can handle those in the way that we want to work with them. So the way that we're doing that is we're submitting this this feel this hidden field called j mo contact form. And then when we get into our when we get into our form handler, we can use that to to pull out and make sure that we're handling our own form so that that's an important part of of this whole deal. All right, so ah, that's the first hidden input that we need. The next one, then is we need ah, we need a nonce. So not stands for number used once. It's a security thing. And essentially what we're gonna do is in our form, handler, We're gonna verify this nonce and that what that tells us is that make sure that this the data that we're processing in our form handler was sitting submitted from this form. Not from, you know, a hacker building a former on their own site and then sending it to AM and outposts and trying to recreate our form here and then be ableto hacker. Ah, hack our site, etcetera. So we're just verifying that the data that we're handling was set from this form, and we're only gonna handle that data. If it's, you know, it's not that data. Then we're just gonna ignore it, so form add input. And we're going to give this a name of WP Nantz and that we will do array on and again, we'll do WP no, right here and then for our options, as you probably guessed will do type equals hidden and then we The value for this is a little tricky because we need to create a we need to create an actual knots that can be verified. Fortunately, WordPress has a built in way of doing that. So we're gonna do value and we're going to use the built in wordpress function WP create nonce, and when you use this function, you need to give you need to Cem, you need to add in and essentially a unique identify. Ire. Ah, For this, this particular form and action. So it's gonna be submit contact form. Um, you know that the what this value is this sort of up to you. You kind of want to try to make it somewhat unique. But what wordpress recommends is that it be something that that speaks to what the action being performed is. So in this case, they're submitting a contact form. So that's we're going to need this later when we get into our form handler to to again pull out of our nonce and verify our nonce. So we just need to pass this for right now, but this function does everything that we need to do in order to create the nonce for us. All right, So the last hidden input that we need to do here is the one we talked about earlier, which is our redirect i d. So going to do redirect I d again our array on. We'll do again. Redirect i d. And in our ray options, as you might have guessed, hidden field. And then the value is going to be remember, we globalised post earlier because this so this is a short code that's inserted into a page and So post, there's going to be this post variable in on this page and so we can just globalize post. And now we have access to all of the information about this particular page. Of course, the only thing that we need is we need just need the Post i d. So we're gonna do post I d like this. So that's going to when we submit the form, it's going to submit a hidden field named Redirect I D. With the value with the I d of the post that the form was submitted from. So that's how that's what's going to allow us to be able to do our redirect. Okay, so that that is our form. Now we need to just get into get into out putting the form. So there's a couple things that we need to do because with short codes, you can't just echo directly in the method here. Um, the what WordPress is expecting from this method is for the HTML that's to be displayed to be returned, and then WordPress has, in its processing of the short codes, will do the echoing for you. So if you echo here, let's say we put some content appear that said, you know, fill out the form if you echo in this method, If you output directly into this method and we put our short code here, what would happen is your output would actually happen above this. Fill out the form so it wouldn't be happening where you put the short code. So it's important that you make sure you always return out of a short code here. So with the way our form builder works, though, when we run to come down here when we run build form this is this is you see, it says outputs the formas age to mouth. So it's going toe output. Um, we don't really I didn't dig into this this too much. You may be a way for you to get around that, but ah, right off the, you know, just sort of looking at it at a glance. You don't have a way to get around that. So what we do is we're going to use output buffering and so I'll just write this year. So, you know, short codes should not output that Ah directly or html directly, whatever. So what we're gonna do is we're gonna start an output buffer. So what an output buffer does is we're going to run, build form, and it's going to it's going to output data. But what PHP is going to do, is it sort of. It creates a buffer, and it's gonna actually catch all of that output instead of out putting it. It's going to put it into a buffer and so essentially keeps that data from being output directly and helps us get around. Ah, the fact that this class happens to output directly. So we start that buffer, we're gonna have a status message. So we'll go ahead and set up for that here real quick, and we'll talk about that here in a second. But we're gonna have a status message when we do a redirect from our form handler and we're gonna do filter input and we'll do input. Get so we're gonna it's gonna be a get parameter. It's again Buehrle parameter of the status message, and it's gonna be called status and we will use the filter. It's just gonna be an indicator. So it's gonna be ah, Juan or zero are. Actually it's gonna be a wandered it won't even exist. Now, the nice thing about filter input, which is a built in PHP function, is that if this U R l parameter doesn't exist, it's not gonna throw in air. It actually runs is set within its own within its own workings. So you can just run this. And if this exists, then it'll set whatever the value of this u r l parameter is to this variable. And if it doesn't, it will just be false. So it's pretty handy. So we're gonna dio we need to do this before Ah, we build the form because if you remember, our status message is on top of the form. So that's why we're doing this status message right here. So we're just going to check and see if the status the Europe parameter said, Ah, status is equal toe one. And if it is, then we are going to print out ah status message and so will do. Div Class equals message and success. If it's set toe one and we'll do P and we're gonna actually we'll get this here and I'll show you what we're doing here. We're using print F because all right, So that's our our format for what our message is gonna be. But we are going to with WordPress. When you output data, you always sort of add the option for localization. And that's what this function does. So you have two functions that are you'll deal with heavily. When it comes the localization. You have double underscore. You'll have underscore e. The difference is that underscore. We will echo and double underscore will just return. Okay, so since we're using print F here, then we were going to just return out of this function. And all we're going to do in here is we're gonna put your message waas omitted successfully , and then we're going. If we go back up to the top, you remember we have our text domain, right? So we're gonna take our techs domain, and we're gonna use that down here, and we're going to pass. That is in as the second primer to do this double underscore method. So you might be asking, OK, why are we doing all of this? What this double underscore method does is it essentially, If there's a let's say, someone speak Spanish and they created language file and members. We have that languages folder that we talked about before they put a Spanish language file into that into that folder in the selected WordPress that they were using in WordPress. You can select which your language ah, you want to use. And so they select Spanish, they and the language file that they put into ah WordPress into that languages folder. They will have translated this message right here. And so what WordPress will do is it will. It will substitute the Spanish version for this for this message right here. So this essentially allows this to be translated. That's the whole point of this. And that's why we have the text domain that we set up in our plug in header. And then we reference that in our localization files so that WordPress knows that this message came from this plug in. There's a whole way of doing that, and it's sort of a rabbit hole, which is why I'm not getting into it, because I want to try to keep this introductory and light. But when you're building your plug and you always want to make sure and set up for that, so what Print F is going to do so The double underscores sets us up for localization. What print f does is it takes this second parameter, and when it and outputs, it drops it in where we have this percentage s where we have this place holder. So we can't run this double or double underscore directly in this. Ah, this format. Here we could use content, ation or complication or whatever. However you say that word, we could do that, but I just like using print if I think it's a little bit cleaner. Um and so I I used enough to do that. All right, so that's our our status message. Ah, And again, if the data was, if we get a positive status message back then that's Onley when this is going to display. And this message right here can now be translated into different languages if need be. So that's the whole point of everything that we just did there. So the next thing is, we're going to build the form. And so if you remember form, build form, it's pretty much that simple. And so that's going to take all of this. It's gonna take these attributes. It's going to take all of these inputs and it's gonna actually build a form and give us our actual form output over here. And then remember, we have output buffering on, so we're just gonna at that point, we're going to return and clean buffer contents. And so return OVI get clean. Okay, so what, Obi get clean. Does This is ah, built in PHP function. So obi start starts the buffer. So all of this out put the printing and the build the build form. All of that's not actually gonna be output yet. It's gonna be put into a buffer, and then when we run return, Obi, get clean, get it Means it's going to get all of whatever stored in that buffer is going to get that. And you could set this to say of variable like output equals and it would set this output equal to whatever stored in that buffer. The string Essentially, um, so that's what the get part is. The clean part is, is that it's going to clean out the buffer. So essentially Obi get clean is going to get all of our output, and we're gonna have it now available and then it's gonna clean everything out of the buffer, which is important. So weaken here. We could just return that. Remember, we have to return out of a short code. So essentially, what this this line here is doing is it's taking everything that we built here in sort In this this output that we didn't allow to output, we buffered. It's now returning that toward presence ing Here, here's here's the data from this method. So again it's it's sort of specific to this. This because this outputs the way that it does. And we don't have a way to just grab the form and stored as a variable, we have to output it. That's why we use the output buffering here, and I actually, a lot of times when I do do plug ins, I will use output buffering like this, and I will close off, for example, close off PHP like this and I might do something in just straight html and then open PHP back up and the output buffers going to grab. All of this is this is this is now considered output because we closed our PHP tags and back here we're reopening anything in here is gonna be actual direct output. And the reason you do that is because it makes it easier to write your HTML like this. You know, it actually shows up looking like standard html wears. If you did it inside of PHP tags, it gets a little convoluted and hard work with. So actually still use the output buffering Even if I'm you know I'm not Ah ah ah, I don't have I'm not tied to a form like this. All right, So that that is our form. That's probably is close to our biggest methods. We sort of tackled the largest frog right off the top. The last thing that we need to do with this form is we need 5. Lesson 4: Add the Shortcode: The last thing that we need to do with this form is we need to You might be wondering. Okay, where did this j mo form come from? Like, Where do we designate that? We didn't say that anywhere in here. So where is that sort of coming from? And what we do? Is we in our conch constructor up here? WordPress. This is where we start talking about hooks. So there's a couple things going on here, right? We're using built in WordPress functions in our PHP code. We've imported just a regular PHP inform builder class. This is not anything specific toe wordpress, and we're using that. We're also writing sort of standard PHP code. And, you know, we're using PHP methods like print F and filter input, all sorts of things. So we have this sort of a mash up right of WordPress, built in functions of methods from a class that we included and then built in PHP stuff. So how does this all sort of come together? How do we know? How does WordPress know? The way that we want to use this and so forth, And so essentially what you have is you have what you write in your PHP code, right? Which is what we've done in our four method here and in our class and all that. And then you have WordPress and you need to tie the two together. The way that you do that is through what are called hooks. So if you look through WordPress there as word the actual WordPress code, let's see if we can find something in here. I mean, sure, So if we go to let's go to WordPress includes No, no, actually, we're using admin posts. Let's just go to admin and man and let's go to includes and let's see if we can find admin post interesting. Well, let's let's try and open this one. And, yeah, just trying to find one here where I can show you this. Probably post op PHP would have this. And so this is the actual WordPress code. This is the WordPress pages and stuff. Ah, that that you see, when you when you look through stuff and I'm just looking for ah hook to show you what this might look like. Let's just do this. If there's a do action in here anywhere, okay? You see, this right here. It says do action. So this is what's called an action hook. So essentially, WordPress is putting in this this function and it za little bit confusing to the way it all works. But essentially right here. I can specify that I want a callback function to run before WordPress continues on with this the rest of this code. Okay, so and and the name of this hook is post locked dialogue. So the way that I would tell WordPress which one of these? Because these are all over the place. You can see there's three do action hooks in this file to action post lock loss, dialogue and do action WP creating auto save. So the way I tell WordPress, which one of these I want to ah, to hook into and and have my callback function run is by this name right here. Now this variable is data. This is a data that WordPress is going to send to my callback function. So if we come back up here, this one says, post this. I haven't actually checked it, but I would assume and it says right here it says the post object. So it's going to send all of the post data about the particular post that happens to be being viewed at the time so I can get all of the post data, uh, and use that in my callback function. So this is an action hook. Let's see if there's any filters in here. Yeah, so apply filters is a similar idea, but it's a little bit different, so an action hook is sort of something that's going to be it. Oftentimes it's something where you are going to add something to the display of WordPress or something that WordPress is doing. So let's say I was on this edit page page and I wanted to add a button ring here. Well, there again, this is a little I want to be clear that this is a tiny EMC editor, so it works a little bit different, so this isn't exactly 100% but just in general, the idea If I wanted to add a button here, I would be adding all new sort of input to this right, so that would be generally where you would see an action hook. Ah, filter is, let's say I have a list of items. So right here under template, I have a list and let's say I want to add an item to data that already exists. That's where you would generally see a filter. Or maybe I wanted to remove one of these again. You could do that with filters. So filters air generally working with you have sort of, um, some data and that data is being passed to you through these variables. And oftentimes it's multiple ones like this, and you're going to change the way that that data works or something about that data. And then you're gonna return all the data back to WordPress so it can continue in processing it like normal. An action hook is where you're going to add something completely new. WordPress is going to run your callback function, and it's not necessarily expecting any data returned back to it. It's just gonna run your callback function, and then it's going to continue processing so with a filter if you don't return. If you don't grab the data that was sent to you from this filter and then return it back to WordPress, you'll sort of cause problems with WordPress. Where's with an action you don't necessarily always need to do that. Okay, so it's like a quick primer on actions. So for short codes, the one we need Ah Oh, are the hook we need actually is a specialized one. So it's not called. It's called ad short code like this, OK? And it's going to allow us to sort of hook into WordPress and, you know, it'll add so that this short code will be processed when we're on this page. Word presence of just out putting this will actually output well, what we have from our our for method here. So we got to give the short code name. So this is where we specify what we're gonna We want to go in here. So add short code. This is the name of the short code, and then we need to tell WordPress. Okay. What method or what function is going to process? The short code is going to to generate the output that this short code is going supposed have. Well, that's the method that we just created, which is our four method. So this essentially tells WordPress Hey, we have ah short code. The name of it is J. mo form right. And the brackets are how you designate that? This is a short coats. That's a built in WordPress thing. You don't need to put those in your name. You don't want to put those in your name here. And then you say Okay, Whenever you come across this short code, you tell where press whenever you come across the short code, we want you to run this method. Now, this is this array thing a specific to the fact that this is a class. So you need to tell WordPress the object and then the method that you want to use. So in this case, we're using this because we're already inside of this method and then we're using the form method. If we were out here, let's say, for example, and we created a function, listens to function short code, and we won't make this too complicated. But if we were out here, then we would do ad action. My short code that would be the name of the short code, and then we would just reference the function like this. Okay, so when you're when you're not in a class context, it z sort of that simple. You just written, you know, reference the name of the function. But in a class context, you gotta tell you got essentially account for that. So that's what this is right here. All right, So when we do this, then WordPress knows Okay, whenever I come across this short code, I'm gonna call this function or this method, and that's going to build our form. And that's how when we load this bill, this is the back end where we created this page. That's why when we open this and we view it instead of just getting that, that the short code right here we get the actual form, which is the form that we built right here. Okay, so that's I mean, that's a really big part of working with word press plug ins. This is something that you're going to do on a fairly regular basis. So I just wanted toe. I know I'm sort of labored through that, but I really wanted to show you that part of it now, another thing that we're gonna do when it comes to the front end 6. Lesson 5: Enqueue Styles: now, another thing that we're gonna do when it comes to the front end is we're going to Ah, we're going to deal with some of the styling. So ah, the way that we're going to do that is we're gonna do this in Q scripts. Ah, method here. So since we're up in the constructor, let's go ahead and add in. We need to hook in again. We always hook in our script, so we're gonna we're going to do. Ad actions were adding an action, adding something to an action hook. The name of it is WP in Q in Q scripts and again, we're going to tell it that we want to use our in Q scripts method from this class. So again this and in Q scripts slide over here. So what? This is telling WordPress this w p and Q scripts. This is sort of its whenever you want to add styling to the to the front end or really the back. And I actually think the back and his admin and Q scripts is going off the top of my head. But whenever you want to add ah script, whether it's a Java script, file or a CSS file. You use this action hook called W P and Q scripts. What this does is instead of just out putting your your the reference to your script directly in the header. WordPress actually does some checking to see if you know that that maybe you're trying to include J Query and Jake worries already included. Well, there's There's no reason to include Jake Weary twice, So it's going to say, Okay, we don't need to J queries will include it once, and that'll be that'll be fine. So it does sort of some checks. Um, some sanity checking before actually putting in, Ah, your script that you want a reference. Okay, so that you always want to use W. P and Q scripts to include styles and javascript. Now, what we told this action hook is that the where were the method for queueing our scripts? Is this method right here? So when we get into this method now, we need to actually, you know, in Q r ad in our our style. So first thing we're gonna do is if we come up here, we'll close this down. That's a little cumbersome and cause that town and we'll come back over here. Okay, so we're in the public, and we have our CSS that were wanting to add a little CSS here. So in our CSS file, we're going to do new file, and we're going to do style dot CSS. Right, So and then we'll open that up and we'll have some styling to that here in a second. But we need to tell WordPress. Okay, we want to use this style on the front end, and the way that we do that is is we, ah, built in WordPress function called WP in Q style. Again, This does all the sanity checking and stuff that that that you want for for including this in WordPress. The first parameter here that we're gonna give it is the name of this style. So we're just I sort of tried to keep this consistent. J mo forms j mo forms etcetera using that throughout. So that's the name of this style sheet. And that's how WordPress sort of knows that Ah can do some of its sanity checking. So, for example, if let's just say Jay Query was a CSS found out of a job script file. If I did, Jake weary and there was another plug in that loaded that same you know, Jake weary file. And there was WordPress loads it by itself. WordPress would again say I don't need three j coury files. I just need the one so it would just load the one. So in this case, you know, there's most likely not going to be another CSS file with that name, so WordPress is gonna load it, but then we need to tell it where and where this file is. And so there's another built in WordPress plug in called plug ins. You are l. And essentially, what this does is it helps ease padding on and getting the correct path, or you are l two something. So here, we're going to passing. We're gonna work. Essentially, what? When this is all said and done, What this is going to do is it's going to have the URL to our actual plug in. So J John Morris dash forms. We need to tell it the rest of the path from there to our CSS file. So we're gonna do slash public flash public CSS style dot CSS. Okay, so that's where we public CSS style Nazi SS. That's what we need to pass. It is the first parameter to plug in Jor El. The 2nd 1 is we pass in this file constant PHP constant. So plug in Jor El can take this and it can figure out what this is. It can figure out where this the root folder for the plug in is. And then it essentially adds this onto the end of that and we end up with the full u R L to r style sheet. So that's the way plug in Jor El works another thing. And then going back to WP in Queues Style Ah, we have. If there's any dependencies, that's the third parameter. We don't have any, you know these? Ah, the rest of these options. These parameters are optional, but what I want to get to is a version number. So one of the things when you work with WordPress, plug ins and urine queuing styles is that Ah wordpress will look to sort of cash those things beaker or it'll or it'll set set it up so that the browser will cash them. And of course, that's good for per plant performance and so forth. But when you are working with a plug in and you're you're writing your your your style, she and you're trying to test having it. Cash could be difficult to deal with, so what you can do is add this version number and let's say you just do something like this to start off with. And then let's say you change your CSS code, you can change it to this, and WordPress will see that as a completely different files, sort of. So basically it won't cash it, and it will reload it fresh. So every time you change your style sheet, you can increment this up and make sure that you're seeing the changes that you wrote in your style sheet as you're developing. And then once you get all done, you're like, OK, it's all done. You could do set an actual version number like this or whatever you want to dio. So that's why I kind of go through all of this for in queueing the style. So again, what this does is we're adding the action were referencing this method. We're hooking it into this WP and Crew que scripts hook and we're telling Wordpress Hey, in Q the style load this CSS style for us. We want that on the front end and then in our actual steel s file, it's really pretty, pretty simple. I don't want to get too bogged down in the CSS with this, so I'm just gonna drop it in over here, but it just does. Some does the status message into some basic the PHP form builder plug in by default doesn't have any space here between the bottom of this input right here in the top of this label. So you see, down here we added a little bit of margin to the bottom here, and then we just did the basic styling for the message. So added some padding, gave it a green color, got rid of any margin that might be on the actual paragraph tag and the status message, etcetera. So just some really, really basic styling. I'm again. I'm not gonna go over that too much because I want to stay focused on the more important parts. You get sort of style this however you want here. All right, so that is kind of our front end dealing with the front end and the form and and all that sort of thing. The next thing that we need to do then is we need to act. 7. Lesson 6: Create the Custom Post Type: The next thing that we need to do then is we need to actually handle this form, right? So this will allow us to submit data to admin Post, But we need to deal with that data and actually store it. Um, n a We need to store it anyway, that can we can collect that data and use it now. This is where it gets a little bit, sort of. We got to kind of go back and forth because and ordered the way that we're going to store the data is we are going to store it as a custom post type. Okay, But we first need to create that custom post type. And the reason I'm storing as a custom post type is really for simplicity sake. If we come back over here to this page, this feedback page here No, I don't have to write this whole table. I don't have toe. I don't have to deal with creating a new table in the database to store the data. I don't need to do any of that, because when we use a custom post type, WordPress does all of that for us. And so it created it saves it as this post type called J mo contact form. We create this new menu item called feedback etcetera. So there would be a lot more code that you would need to write in order to use your own custom table and to create all of this back end on its own and so forth. And you absolutely can do that. And maybe as you if you really wanted to develop this out you would. But again, for sort of focusing on trying to give you an introductory course here, I wanted to keep this simple. And, of course, this. I mean, it stores the data just fine so we can see here. Another advantage of this is if we come over here to tools we go to export because it's a custom post type. It actually shows up here so we can export our feedback and download an export file. So it's another advantage, and of course, you know, because it's sort of built into WordPress, it's a it's a custom post type. There's all no sorts of different things that are already done for us that we don't have to do when it comes to dealing with the data. So that's why I'm using a custom post type again. If you really wanted to develop this out, I could see you saying, Well, I want to create my own custom table and so forth. But this just makes is a really simple way to be able to store data. And also, I should say that is generally the recommended way. Um, if you're not no. If you're not gonna if you're gonna be storing data that ah, you know, isn't it is just It is really similar to what a post is, and you really don't need to rewrite to create your own custom Custom table, Andrea, right? A bunch of code. Generally, WordPress recommends that you don't do that. You just used a custom post type. That's sort of what custom post types or for so again, you can sort of make that distinction. But that's just what I went with here. All right, so in order to do that, then we need to Like I said, we need to create our custom post type. And so, in order to do that, we're actually going to do that in the admin, because this is the admin area sort of here. So we're gonna sort of contain that stuff. Ah, to itself. Here. So, um Ah, in order to do that, then where you are going to create a new file in here, and we're gonna call this class class dash J mo forms and men dot PHP. I know super original here, but gets the point across. All right, whatever that is. And then we're gonna create, just like before. We're going to create a class we're gonna check if it already exists. So if class doesn't exist, j mo forms and men that and then create the class and again in here we're gonna have Ultimately, we're gonna have a couple. Um, we're gonna have a couple methods, but the one we need right now to get going is we need our to create a a post type. So we're gonna first thing we're gonna do is we're gonna do our constructor, and then we're going to create a We need a method for creating our actual ah, post types will do public function, create post tape like this. So, essentially, it's the sort of the same pattern as before. This is gonna be a callback function in our constructor. We're gonna hook in to WordPress and tell it that we want to use this method to create our post type. And then this method is where we're actually going to create our post type. And it will just in stanciute an instance to this will do J mo forms and men equals new J mo forms. Admin. Okay, so in our constructor will just knock that out real quick. We're going to add an action hook, and we're going to do this on the in it hook, and we're gonna do a ray this and create post type. So you when creating post types, you generally want to hook them in on this innit? Hook that just make sure that they're set up in time for you to use just sort of the recommended way of doing. It's the proper hook to hook them in on. So that's why we do that. And then we're course telling it. Okay, this is the, um, method where we're actually going to create the post type. So create a custom post type. There's WordPress has a built in function called register post type again, super original right. Um And so in this you just specify the data. What, you want the post type? You know what? You want it to actually be the and and there's a number of different options. You know, I'm calling this feedback, and if you look only when we pull this out the If we pull this out, try it again. You'll see we if, Well, let's click in here. You know, it says, Ah, it says edit post, for example. Right here. This is not really a post. So I I didn't set every option that you can set, but you can pretty much set all of this, so this could be at it. Feedback. You know, when we went to the Exporter, you might have noticed that it said something about posts, and so far you could set whether the editor shows up here. Whether these custom fields show up, etcetera, you can edit Ah, almost everything that you can imagine when it comes to how you want this post typed work. Which again, is why this is sort of the recommended way that you use you store data because it has so much ability for you to customize it. Okay, so in this register post type, when we call this essentially the parameters that we're gonna set here us telling WordPress how we want this post type created. So the first parameter that we need to set is the name of the post type. So just calling this G j mo contact form. This is a sort of a back end. If we look at our Earl over here, um, we can see, actually, we go back to this page, we could see it says post type equals J mo contact form if you go to Ah ah Post are all posts. No, you will see all this one has it set to This is the fault one. So let's go to pages and all pages. You can see the post type is set to page. So this is the sort of back end name that were too designates like a ah, an I d for this post type. Except it's not a number. It's It's a name. It's ah, string. So that's what we set here. You want this to be be unique because you don't want it to conflict with one's. Their default built into WordPress or any other plug ins that might be adding post types. So again, you generally prefix this with JM like your whatever you want to use for your prefix here. I'm using jam. Oh, but generally it's gonna be sort of the name of your plug in. So if you called the name of your pug in Feedback Express, you might use f x or you know f e X or F X s or whatever something related to the name of your plug in as your prefix so that you don't have conflicts with other plug ins. All right, so that's the name. And then we need to just set some an array of options that, ah, that you have available four Ah, working with, ah custom post types when you create it. So all the options I talked about that you have that you can set when it comes to how you want your post type to work. That's what goes in this array. Okay, so the 1st 1 here and actually if we just go to register, is where you can find this register post type. Ah, we come down here, you can see this. These air under labels. These are all of the different labels that you can set. So the name, the singular name and new name that a new item and that item new item view out of, um, etcetera, all of these different labels you can set. And then when we get into the arguments the ray that I'm sitting now you can see it can be public excludes from search publicly queria ble show you. I show you and them I mean, there's just a ton of options. So you sort of want to go through these and figure out what you're trying to do and then figure out what option you need to set what way in order to do that. So I'm not gonna bog down and read through all of these here. But this this codex this wordpress Codex, this is your friend will be you referencing this often. Just like you might reference a PHP manual often. Okay, so we're going to set a few of these here. First, we're gonna start with labels. You saw all the ones that you have available. I'm sort of keeping it it short here. And we're gonna when you set the labels you set in array and you saw all of the ones that you could set those air Basically, what you use inside of this array. So again we're gonna keep it simple, and we're just gonna do name and we're gonna set that. Ah, as you saw in the thing equal to feedback and we're gonna use our, ah, domain, our text domain. I think it's just j mo forms like this. So there's that. And then we're going to set our singular name, and it's it's really just the same thing. So singular name, okay, and feedback double underscore feedback. So that's our labels that I mean, that's pretty straightforward. Nothing super crazy about that. And then there. So with this particular type of post type, a lot of post types that you create you won't necessarily have to be this sort of nuanced. But in this particular case, this is, ah, feedback that we want to be able to see in our navigation menu on the left hand side. So we can, um, we can see the feedback that's actually coming in, but we don't really want this feedback displayed on the front end, and that's that's a little bit different than a lot of post types that you see out there. A lot of post types will either be, you know, you want it completely hidden from the admin menus and everything, or you want to completely visible like a post. You want that completely visible. Now, if you created a video custom post type, you'd pretty much want that completely visible. So this actually has some nuance in terms off. We want to see it in the back end, but we really don't want to see it in the front end. We don't want people to be able to search for it, cause this is meant to be sort of private feedback that people are giving. So the way we set these options is ah, a little. It's actually nice because I can show you a few different things. So first off, we're going to set public to false. So this is sort of like a generic. If we come over here, it's sort of a generic, um, display when it comes to ah, the the post type. This is ah, a kind of almost a global sort of setting. So it controls how the type is visible. The author showing knave menu show you I exclude from shirts public clear queria ble It's going to affect all of the's options, but some of these we want and and so it's sort of like this umbrella sort of option. Ah, and we're gonna set that toe false because we want to We want to start off by making it completely hidden. So it's gonna be hidden in all aspects except for the very specific exceptions that we make to that. And I think that's the best way to approach that, because you don't always know all the ways that weird press is gonna show something in all the places. And so if you miss one, you may end up with it showing up somewhere that you don't want it. So we just make it. We set public toe false. That's sort of just gonna hide it. And then we're gonna We can override some of these, uh, these these other options down below. You can see it references showing them you can show you I exclude from shirts public wearable. You can see it references these and ah, we so we can override those down below. And that's what we're gonna we're gonna do here. So we're gonna set public to false, and then we're going to set has archive two False, because that's again on the front end. That is, if it's going like if you had a category page and you had a category listing and it lists all the post in that category, that's what has archive is Well, we don't want it displayed on the front end. Oh, however, we do want to show the you I this is gonna This is Ford the back end. So you remember this was under public. This was one of the things that that option effects were now overriding the false that we set in public and setting that too true. Same with show in knave menus. We're gonna set that. Ah, I guess when I said Oh, so showing knave menus actually is because we turn show you I on We set that to true again . That is sort of a a, um, a umbrella option. It's now going to turn all the stuff in the back end on. So now everything in the back end is completely on. However, there are some things that we don't want it on for. One of those is if we go into, ah, appearance and then we go into menus. You'll see when you we go to add ah items to our menu, you can have categories you're gonna post you can have pages and any custom post type. So we could have feedback here if show and knave menus was set to true. The these feedback would show up in here and you could actually link to an individual. One of these posts will we've set public to fall. So those posts, actually, the front end being able to view these on the front end isn't actually supported. So it's not actually is not gonna make any sense toe have it show up here because we can't actually link to it anyway, So we're just gonna set that to false so that it doesn't show up here And then from here, it's just about, um, where we want this to show up in our menus. So ah, and how we want that toe look. So the first thing we're gonna set is a menu position. I'm going to set that to 25. Um, let's do see if it shows that here on this Yeah, so right here, 25 means below comments. So menu positioned, 25 is below comments. Well, that's where I wanted it. So that's why I said that to 25. And then we are going to have Menu Icon and I'm going to set this to dash Icahn's testimonial. Now. You might be like What? So if we come over here, um, let's see, we find the icons is probably down a little bit further. Maybe I missed it Menu icon. So it's either the u R L to the icon to be used. So if you have a custom, your icon you want to use you just upload that somewhere along with your plug in. And then you ah, in here You said this to the u R l of wherever that that icon is and WordPress a load that icon, or you can use the dash icons icon font defaults. So if you're not familiar with dash icons, the's air actually made by WordPress for its you. I, um Let's see, Web Developer Resource, I think, is what we want and so you can see each one of these icons that has dash icons, playlist audio If we click on this one, um, dash icons, admin post. We click on this one. It's dash icons, admin comments. They all have a sort of name or identifier like this. If you want to use one of these, you just look through here, forgot which one you want to use, and then you use that identify her here. And WordPress knows what what, what you're talking about. So that's what we're doing here. And then the last thing that we're going to do here is a thing called supports. So that is what I remember. When we're on this page here, we can. I said, we can choose if we the editor, shows up. If the custom fields show up and so forth, that's what the support option is. You explicitly tell it what you want it to support. Now, if you don't set this option, it will support everything that a regular sort of post supports by default. So in this case, I want to I want to tell it that I only want to support a few things. So title editor and custom fields and the reason that is is because I don't need to support featured images. I don't need to support comments. There's a lot of things I don't need to support here because this is just collecting data. So we were going to store our ah, the name that was submitted as the title of our feedback. Because I think that makes the most sense is when we're looking for feedback. Will who submitted it? So this is what's gonna show up if we look here. This is what we're gonna see first here. And then we're going to store the message that they actually submitted as the content here and then the submission, email and the email on the website. We're gonna store as custom fields here. So all we need is title editor and custom fields in. This needs to be editor, not editors. So those are the only ones that we need. We don't need anything other than that. So that's what we're setting here. And so that is our custom post type set up. So we have our action hook. We have our register post type. We've set all of our options in here. Now. Our custom post type is sort of ready and set up to go. The only other thing that we need to do is we need to come back over to our main plug in file, and we need to make sure and include that that class that we just created in otherwise WordPress won't know to use it. So we're gonna do again there, and we'll do admin and will do Class J mo forms and men dot PHP. Okay, so now what's gonna happen is when this again When this is activated where precedent lug, load this plug in file first, pulling our foreign builder little poor poll In this admin, this j mo forms admin. And over here we create the class and then we instance, seen an instance of it. And because we're running our ad actions in our constructor when we instance, eat this, it automatically runs whatever's in this constructor, which ads. Our ads are action which actually creates our post type. So essentially, whenever this file gets loaded, our post type will be loaded in wordpress and again, if you're not familiar with WordPress, the way it works, that sort of has a loading procedure. So every time a page is viewed. And WordPress, it goes through this loading process. And so you're hooking into that process and you are adding in your your admin pages, you're adding in your short codes, so every page that loads will at word, Pressel doesn't always load everything, but it loads what's appropriate for that particular page. And so we have all of this stuff sort of available to us. So can we just keep sort of hooking in to WordPress to do all of that? All right, now that our post type is created now. 8. Lesson 7: Inserting Form Submissions: all right, now that our post type is created now we can actually handle our form data. So this is where we're going to actually take our data. That's submitted to admin post, and we are going to do something with it. Now, as I mentioned, we're sending this to admin post, and so we're not going to, you know, we're not going to in our form page here a lot of times, If you've seen me, do PHP tutorials yourself, submit a form we're not going to do. Okay, you get the post Post, ah, equals post data, right? We're not gonna handle our post at it in this four method, because wordpress has a built in way of dealing with formed out of that we want to sort of tap into. And so what we're gonna do is we're going to hook into that admin that post pages. Now, I'm gonna just sort of dropped these in over here, and then we'll talk about that because I think it's a little bit easier to just sort of talk about these. So there are two hooks that are available in admin. Post was there's actually four, but for our case for there's too that we really care about. So the 1st 1 is admin post no privilege. And then, you see, we have J mo contact form, and then we have admin post J mo contact form. Okay, so remember I told you were submitting to admin dash post op ph piece. That's what the first part of both of these are is. That's essentially the page that were on. That's where these hooks are located. Now we have no priv. And then this one down here just doesn't have that. No Priv. So essentially the difference between these two hooks is if someone is logged in or if someone is not logged in. So if someone is logged in, then this is the hook that will be run here. If someone is not logged in, then this is the hook that will be run. Now, that's sort of important. If you want people who are logged in to be able to submit this form and people who are not logged in, they can't submit the form right. It won't let it go through. In our case, we're going to take feedback whether they're logged in or not in fact, this is a contact form we're gonna assume in most cases they're probably not logged in. But there's chance that maybe there may be some people that are logged in, and so you'll notice in both cases were hooking into both, and we're sending them both to the same form. Handler. You could send these two different form handlers. You could handle it different if someone was logged in, not logged in. You could just not hook into one of these. Now, there's a number of different options here, but in our case, we're gonna treat them both the same. So we need to hook into both so that people that are logged in and people that are logged out can both submit the form. Okay, so this is one of the basic protections that submitting toe admin post allows for, and so we're doing it right off the bat. When it comes to how we hook in, you're, uh I also know that we have the note that we have. This is called J mo Contact form. Now again, you might be wondering, Well, where does that come from? Well, if you remember Ah, when we created this form. We created this action. Remember, we created this action ad put, uh, uh, input. And we set the value to J mo contact form. That's where that comes from. So when we submit this form and it goes to admin post WordPress is going to look at this action value, and it's going. That's how it's going to create this hook right here. So it sort of creates these hooks on the fly. So you need to make sure and match up this. This what comes after? No priv underscore with whatever you put whatever you put down here in this action hidden input right here. So you can change this. Just need to make sure that you change it in both places. All three places here in here. Okay. All right. So now what we have here when we add these action hooks is when our former submitted that that'll be set to admin post. And now whether the users logged in or law not logged in. WordPress knows to send data. That was that was submitted with Ah, this action block to all any for any data gets that was submitted with that action block to this method right here. This form handler method. So this essentially allows us to capture our specific data for our form and now be able to process it. And so that's what we want. And so again, it it's a built in way of dealing with of handling formed out of where we don't have to do our own posts and all that sort of thing. So it's the recommended way that you handle form data in WordPress. All right, so then we need to actually handle are formed out of. So the nice thing about this is that what you get here, ultimately is you get what you would normally be used to working with, which is the Post Array. So now you have your post data that you're normally used to working with. You don't have to do it up here. You don't have to do. Ah is post at a set because you know that if you if WordPress has gotten it this far, there's something there was a form submitted all that sort of stuff. So again fairly handy for working with all of this stuff. I'm gonna actually go and close this here to some of this and this gets a little bit along . All right, so now that we have our form data, there's a few things that we want to do right off the bat. So our general, what we're going to do in this method is we're going to first verify our nonce. So we talked about that nonce that's submitted. We're gonna verify that we're gonna verify to make sure are required fields have been submitted. Then we're going to build our arguments for creating ah record. And for a custom post type, we're going to insert that post. We're gonna check to make sure it was inserted. If it was, we're going to send an email, and then we're going to redirect the user back to the page that they came from. So that's what's happening in this this method. So let's go ahead and dive into it. So as I said, first thing we're gonna do is verify the nonce, and WordPress has a built in way of doing this. So first thing we're gonna do is we're just going to see if the nonce was set. So if the knots isn't even set, then you know we can't really do anything with it. We can't verify it if there isn't one there and again. This is if someone, if a hacker built ah form on their own site and they didn't realize they needed a nonce and they tried to submit a form from their site to our admin post, they wouldn't be able to do that because they don't have the knots. That would be a situation where the nonce might not exist. So if it doesn't exist or we're gonna call this built in WordPress function called WP verify knots and it does exactly what it sounds like it would do, which is, is going to verify or not. So the first parameter is the actual field in our port post data where the nonce has been saved, right where the form the element in the array that it's stored in. So you remember, if we come up here we created added a field called WP nonce. So that's what we use here in our post at it. That's where it's going to be be stored. So we're gonna tell it that, and then we're going to tell it the action that we ah set when we created that non choosing WP create knots. So let's go ahead and to sort of finish this out for a second. Okay, So if the nonce doesn't exist or wordpress can't verify the knots, then we're gonna handle that's we're going to consider that an air We're not gonna process this form now This submit contact form. Remember up here when we did WP a WP create nonce, we said submit contact form. So whatever you put here, when you go to verify the nonce, that's the exact same thing that you put here. That's part of how WordPress it uses time. It uses the user, etcetera. But that's part of how where press verifies that this data came from that form. Okay, so we're verifying the knots if the if, if it's not set or it's not verified. What I'm doing right now is just ah called WP die. And we're going to create a message. Measured fields are required. So what What WP died does is a lot like PHP that actually this is the wrong one. Okay, so explain that a minute. So what WP diet does is it's a lot like ah, the dye method. That's in there. The dye function that's in PHP except it has a little bit of when used. WP diet adds this message that you specify here. It adds it to there's some HTML that goes around it so actually creates a paid instead of just a plain text air. It actually creates a little sort of background in a little container area for it to show up, so it just looks a little bit nicer. Um, and it's that all is built into WordPress. There's not anything that you need to do their you just called WP die now. Dying in all of these different places may not be the best way to handle this. No, you could handle these in different ways, But again, I want toe, you know, I'm throwing a ton at you already, So I just sort of wanted to keep this streamlined and and so I used dying several places where you may look at it and go well, you know, I want I want to do something a little bit different there. However, in this particular case with a nonce you pretty much if the nonsense and verified or not set you pretty much don't want to do anything else, and throwing a die air here probably makes sense. And then this message cheating. Ah, that's pretty much in default in WordPress, if you if in in the way WordPress itself actually handles nonce failures on all its forms. If there's a failure, the nonce, that's the message that you're going to see. So it sort of just helps you to have your plug in match with what WordPress is already showing for knots failures. So that's why I used that particular message here. You can use whatever message you want, but one of things that to caution you against is if it's a nonce failure. One of two things happened. Either the the user let the site let the page sit because it's based on time. So the page sat open in their browser on the computer for a really long time, and then they came back to it and tried to submit the form, and in that case, you again. WordPress is built in forms. This is the message that they're going to see if they did that anywhere else in WordPress default WordPress. So you're giving them the same message that they would see in other places. And so they probably would. No. It's something that they might be used to seeing the other likely scenario if, for a nonce failure, if someone's trying to hack your site and or her hack your form and so you don't want to give him a ton of data. So having a sort of cryptic message like this in this scenario sort of makes sense. Ah, because of what it is. All right, so that's gonna verify our nonce. It's not verified. You'll just stop right there. It will die and output that message. Next. We want to verify our required fields. So here, depending on how you build your form. And I shouldn't mention that up here, you know, I added these particular inputs, but you can come through and customize this right? So for if you want to use this and you want to maybe use this on your own side or Yuhas, our developer want to take this and you want to use it for clients that you're working with . But they want different inputs. Will you just come up here and no change these inputs or add new inputs removing puts whatever to build the form that you want. You just need to make sure than when you change that form appear that you come down to the form handler and you change the stuff that's in here as well. So here we're going to set what are required. Fields are for this particular form again. If you change the form, you would need to change and you want where you want have different required fields. You would need to change this, but we're going to set this equal to ah array, and we're just gonna put the names of the field. So we're gonna do name email and message, right? So in our form, those air, the required fields and then what we're gonna do is we're gonna loop through through these , and we're going to check them in our post data. So we're gonna run if empty and we're gonna do post field. If that's empty, then we're just gonna again. This is a place we're gonna use WP die. But this is a place where it might make sense to use. Do would handle this a little bit. Ah, differently. But this is what I'm gonna put here. Now. One thing about this is in some ways, this does make sense to do it this way. Because if you remember from our ad input here we have this required option. True, True. If we look at our form, you see, has these ass tricks is by it. Html five has a built in required option are attribute that you can set for Foreman puts. So if we try to cement you see it how it says, please fill out this field. Please fill out this field. This one doesn't say anything. This one says, Please fill out. I guess it doesn't say it, but if we try to submit this, you see, it says, please fill out the field. So that's actually html five. So html five hasem built in validation to it already. So again, you know it's not gonna even let them submit the form. If this data isn't fill out now, you don't want to rely on 100% on that. Which is why we're doing our check in the background here because again a hacker could build their own form. So again, it's a likely scenario that if these fields are empty, it's not because someone tried to fill out our form here because that already has the validation on the front end. It pretty likely that it's a hacker who build a former on their own site who's trying to to do spam this or whatever, so dying here might actually make sense in that scenario. But again, this is a place where I could see you not just completely killing the script. Uh, you might want to do something else there. I'm just for simplicity. Sake and use die there. All right, so if we get through those checks, then we know are nonsense verified, We know are required fields air filled out. So now we can actually go ahead an insert our data into the database and the way we're doing that because we built a custom post type, is we are going to create a new record for our custom post type, so we don't have to write a bunch of SQL code. We don't need to connect to a database in the table and all that sort of thing. All we need to do is insert ah post. And so we are going to use the built in WordPress Method WP insert post and we are going to pass in some post arguments and then let's go ahead. I actually don't remember off the top of my head don't be insert post. We're gonna pass in our arguments and then the hunts of second up Oh, WP area. So if this call to this function, um, fails, right, so we're not able to insert the post the section up second option is whether or not to return Ah wordpress air And by default, it's that the false we're going to set it to true. And I'll show you why here in a second? But this is the method that were ultimately or function were ultimately going to call that is going to insert our data into our database as a record in our custom post type that we created S O. We need to pass in an array of arguments and the ray of arguments are the arguments for what are actual? Ah, this actual data is going to be so There's a few things that we need to set here. Um, actually, let's do post r equals array. So he's gonna be our post arguments and the first thing that we need to set here is the post author. So because it's a custom post type, it sort of needs toe. Have an author. Now you're not going to set it. The person submitting the form may or may not be a logged in user, right, cause we're we're allowing both people to do that. So ah, if they're if they're not logged in, there's not They're not gonna be, Ah, they're not going to be a member of the site. And even if they are a member of the site, it's a good chance they're not going to be an author. They're not gonna have author privileges. So the way that you you handle this is you just set the post author to you as the admin. So I've set this to a user idea of one. If we come over, I don't see Let's go here. Let's go to users. Let's go to use. There's all users. So I'm the user here the way you find you. Use your ideas. If you look down here in the bottom left. When you hover over this, you'll see it says, Actually, if we got a view, I think it is. Maybe it's edit. Okay, So the way that you do it is actually, most of the time you're gonna be, uh you'd have an idea of one, right? Ah, and if you if you notice if you click into here it just has users dot PHP because it's your own profile. So it's not. If you looked at someone else's profile, it would actually show you, Ah, the user, i d. It's actually the view link, but because I have Perma links turned onto pretty permit links, it's just in the bottom left. You can see it, says author and then John Morris. So the way to do this would be to go to Perma links and let's go ahead and just turn them to playing real quick. And then if we come back here and reload this and we go to view, you can see now it says author equals one in the bottom left there. So that's how you know what your user ideas So and then just come back here and go back toe , Post name and word. Pressel. You know it. It's not gonna be a big deal to do that for just a few seconds for most most sites out there. And so now it's back to author slash Jan Morris. Okay, So that's how you know what your user ideas, I would say again, if you're the admin the first account that you created on the site, you're most likely gonna have a user idea of one. So you can set that here. Whatever the user I d is, you can set that here. You might be able to see if we can post author now. It it actually. Ah wants an imager. So you need to figure out what that image er is. And that's the way you can do that. But you only have to set that that one time. So it's not that, you know, it's not a huge deal. Next, we're going to do the post title. So remember, for here we're using. If we go to our feedback, we go to our records. We're using the name of the person that submitted the form. Um, so in this case, you know, Smith is John Paul Morris. So we're gonna do post title, and we are going to use post and name. So we're using again the name that was submitted from the Post. And you see here I said this this variable equal to this one just because it's easier to type. That's really the only reason I did that. But now so we're gonna set this like this, But we do need to sanitize this data. So fortunately, WordPress has built in met their functions for doing that so we can use sanitize text Field because this is a text field and we can wrap our post name in that and word Pressel sanitize it properly. So WordPress will assume that this was data that was submitted from a text input on a text area and on a check box. Except it's from a text input. So do what's appropriate in terms of sanitization for that. So again, that's that's pretty straightforward and handy. It's it's nice and easy for us to be able to do that. Next, we're gonna do post content and we are going to do for this one. We're gonna do sanitize and we're gonna do text area field, and then we're gonna do our post message. Okay, So ah, that that's because that came from a text. Every field we're going to use this built in function, text, area, field and again, like everything here. You can just sanitize text field. You could just sort of google for it. And these are usually the first thing is gonna come up. So you see, sanitized Text field has sanitised text area field. Um, let's go ahead and click on text area field. FIFA has any Ah, there's there are others here. A lot of times they'll show up in the sea also area here. Um, there should be. And the other thing you can do is you can click into these can expand full source code. Or you could just click into this formatting dot PHP and it will show you what they are So sanitised. Text fields. Ah, sanitized text area field sanitized text area field emoji there's you just sort of come through strip slashes get at each smelt. There's all sorts of functions in here that you can use depending on what your particular the situation is. So that's sort of how you can find where those things are at, right? So that's the post content. And I keep doing this That's not gonna work out. You need to do commas because this is an array. All right, So we're gonna do next, we're gonna do the post type, right? So this is where we're telling WordPress What post type This is four. Because it's not a post. It's not a page. It's one of our specific The post type that we created. So again, we created this over end. Ah, there's J more foam forms, admin. It's this designator that you set right here. That's the same one that you need to set right here. Okay, like post status. We're gonna go ahead and set this to publish The only reason it doesn't really matter in a way, because we're not showing these on the front end and so forth. But if you do want to use the exporter Ah, the exporters going to export, it might. I guess it might export the drafts and so forth. But we just said it to publish, so that if we want to use it in any of the other places where custom post types can be used Ah, lot of times they will filter out drafts and private post on that sort of thing. So we're just gonna set it to publish were not displaying on on the front. And anyway, we turned all of that stuff off. So it's not really going to matter in terms of it actually showing up on on the front end. All right, so that that's gonna create a post. But you notice we only have name and email here, and if you remember from before, we're saving our website and email address as custom fields. So we need to save this data as well on the way that you do that as you say that as a meta data, because website and and, um, email are not things that are default data for a WordPress post right there. A WordPress post isn't generally gonna have an email address associated with their website . So this is what it makes our the way we're using the post type a little unique. So we need to add it as metadata because it can't be added as just regular default that ah matched to, like, a post title or post content. So we're gonna do meta input. This is gonna allow us to add custom post type. Ah, are, ah, metadata to this post. And so we're going to do an array and are to pieces of metadata that we're going to add are , as you see from over here submission, email and submission websites. So let's go ahead and do submission email and we're gonna set that too Sanitize email can built in wordpress function and post email. So you sort of hopefully starting to see the pattern here, and then we're gonna do submission website. You know, far as I know, there's not a sanitized you or else we're just gonna do sanitize text field and we're gonna dio post website. Okay, So what this is going to do is it's gonna crew. This is all of our arguments for a post. So when we run WP insert posts and passes in going to create a new post, that's a custom post type of J mo contact form, and it is going to set the title of the post equal to the name that was submitted from the form going to set the content equal to the message that was submitted to the form I'm going to set the status to publish. And it's going to create too Ah, custom fields one is going to be called submission email, and it's going to be set equal to the email address that was passed. And one called Submission website is going to be set equal to the website. You are l. That was passed in our form or submitted in our farm. So now we have all of our data that we need to capture for us to be able to to take feedback from our users. So once we do that, we're going to, uh, used WP insert post. But we're gonna set this equal to post i d. And there's a reason why here. So I said that equal to post i d. And then we are going. It's comment this So this is insert the post so WordPress will attempt to insert that post . If it's able to, then you know it's gonna return the post. I d back to us. If it's not able to, it's going to return. We set this to true, so it's going to return a WordPress air object. Now you can handle that that air objects sort of however you want, and that's part of the reason why we want it returned as an object. If it fails, but the other one is because WordPress has a built in function called Is WP Air. So it's an easy way to check if our insert failed or not. And so we're gonna check off of post i d. And if it failed, So if it is a wordpress air than right now, I'm just doing die, right? So we've talked about this a few times where you can use this or use something else. But there was a problem with your submission. Try again. Again. Your message could be whatever. Also, because you have access, if it is a WP air than post i d will be set to will be an object that contains what the air is and potentially a message about what happened. You could display that data to the user if you want. You sort of handle that out. However you want again for simplicity sake. I'm just you using die right now. Okay, So if the post is not inserted successfully, wordpress will die and display the air message. But assuming that it is now, the next thing that we want to do as I mentioned is we want to send some emails to the admin to notify them. New feedback has been posted 9. Lesson 8: Send the Notification Email: now, the next thing that we want to do as I mentioned is we want to send some emails to the admin to notify them. New feedback has been posted, so we're gonna do send emails to add men's. Okay, so the first thing we're gonna set we'll talk about this a second, but we're going to set a to actually. Let's let's talk about this real quick. So let me pulled us over so you can see it. WordPress has a built in mail function, so PHP has its own mailer function. WordPress has its own one that I think does a few things before it sends it. Ultimately, through the PHP male function but and in plug ins can hook in and then do SMTP Or you could have things like mandrill that can hook in or think send grid as a plug in where it'll be sent through their It'll reroute all WordPress smile through their servers. So that's why you want to use WP mail instead of the built in PHP mailer because it allows for plug ins to be able to hook in and override this. That the other so But in any case, the Ultimately, the parameters that we passing are gonna be similar. We need a two. So the email addresses that were going to send it to a subject, a message, any headers and then there's a last option that you can add Here is attachments. We don't have any attachments we're gonna send with it. But you could do that. If you want to do so. We need to build all of this stuff. So we need to build the two we need to build the subject. The message, etcetera. So Ah, the first thing that we're gonna do is going to do to We're going to set that equal to array because what we're gonna come down and do is we're going to get our admissions. So we're gonna use get users, which is a built in you ah wordpress function. And we are going to get on Lee, the users who have a role of administrator. And so WordPress has Rolls has admin editor, author, subscriber by default, and they all have different privileges inside of WordPress. And technically, they're called capabilities inside of WordPress. In this case, we just want to get anybody who has a role of administrator because we just want to send those people ah, e mails here. So there is some nuance here where plug ins can add Ah, plug ins can add. You can install a plug in that will allow you to create custom roles with different capabilities. So you might, instead of checking for a role, you may have a custom role that has is really similar to an administrator. You might want to get those particular email. So instead of squaring for users that have a role of administrated, you might want to query for users who have a particular capability. Um, but I think in most cases, dosing a roll of administrators is going toe work just fine. So we're gonna get all the users, have a role of administrator, and then we're going to loop through the array of that users, and we're going to grab their email address. That's ultimately all we need for our two array. So we said our ray appear empty so that we don't have any sort of air in terms of a notice that it wasn't said toe array, etcetera. So we're gonna set to equal to and men user email so that's essentially going to create an array of email addresses that for all of our at the containing the email addresses for all of our admin on this site, there only happens to be one. But if you have three, add Mons. It would create an array that had the three email addresses of the three admits in it. Okay, And that's what we're ultimately gonna pass in here, because that's what this needs and needs an array of. I think it's a ray or comma separated list of email addresses, so that allows us to build our our two who were going to send it to. Then we can build the email. So the first thing the actual message is going to be sent, so the first thing we need, as you can see here, is we need a subject. Lines will just set are subject line. You can set this now pretty just straight up new feed back posted still like this, your feedback posted, Okay, and then the next thing we need to do is our message. So before we can do our message, though, you remember from the email the user, the admin was able to click a link that took them to the specific feedback that they just got notified about. So in order to do that, we first need to set up that you are else we're gonna do post edit. You are l That's what we're calling it. And we're going to do a sprint f and we're going to build our You are Ellen here. So the u r l is going to be Our format is going to be, ah, our first place holder. And then it's going to be, ah, post equals and our second place holder and then and an sign and edit equals action equals at it. Okay, you might be wondering, Well, where does that come from? If you look here in, Are you Earl? We have the Earl of our site and our admin page. We have, um, Post op PHP. And then we have post equals and it's you r l of Earth's the It's the idea of the post, and action equals edit. So that's actually where this came from. I just looked at this u R l and said Okay, what do I need? The place holders are for things that will change So if you install this on a different site, the U R L The domain will change, etcetera. So remember, from before we used our built in function admin u r l that allows us to target or get a specific admin page from WordPress. So that's what's gonna go in our first place holder. So this will generate a U R L It'll basically generate this. You Earl John Moore show WP admin post dot PHP. Right. That's what we put here. So it'll generate all of this right here and put it in right here for this place holder. So then, you see, the next thing we need is our question Mark, our post equals Well, it depends. What? What Post was just created? We'll remember this. Submitted successfully, we saved the Post i d. From WP insert post. So we know the Post I d. We put that in here for the second place holder, and we do that by just coming here and going post i d. So that will be put in place of the second place holder. And then action equals at it so that that's just the rest of this year, girl. So that just allows us to build our you Earl here. So now that we we have that we can Ah, we can make sure that they get set to the right page. So we have a post edit you, Earl, Um, and actually, all move this up here just cause it's kind of a set up thing Gonna build that sort of first . And we can keep our message clean, and then we can build our message. I'm again. This would take a little while to type out, so I'm gonna just drop in, um, this message and we'll just walk through it real quick. So it's a pretty standard email message. So the subject just set to new feedback posted opening paragraph tag. You have new feedback. Here are the details. Closing paragraph tag, and then we have just individual lines here. So we have a line with the opening paragraph tag that says name. Ah, sanitized. Text field. Post name. So we're taking the name that was submitted to us from the, uh from the you Earl from the form were posting it in here. Ah, sanitized. Tex airfield. The message that was here. And then we're creating another one that has our post edit your l that we just created. So we're creating our link view. Edit the full message here, a ref equals placeholder, placeholder or passing in the post. You earl here. So that's just creating our message there. And then the last thing we need to do because you'll notice that we have html in, uh in that message is we need to set our headers. So we're gonna set our headers equal to array. Ah, and it's gonna be content tape, text, slash html and then the charge said is equal to utf eight mm on. And this needs to go H MLT html. Okay, so that makes it so that our our html we used in this mail wool be rendered properly, hopefully by the the email provider. All right, so that's our to that is our subject. That's our message. And that's our headers. Let's everything that we need here to send our email. So at that point, we can just send our email. Now, you could you could check to see if that 10. Lesson 9: Handling Redirects In WordPress: now you could You could check to see if that the email was sent properly and then do the redirect, maybe thrown air if it wasn't. I don't think the email to the admin is nice, but I don't think it's worth killing the script or displaying an air message to the end user if that email doesn't get sent properly. So I'm not actually running any sort of check on this. Whether or not that email gets sent properly, I'm going to re direct the user back to the page that they came from because remember, they submit the form on the page that we put the short code into. They get sent off to Admin Post, and now they're basically in admin post. As we're processing this now, we need to send them back to the page that they came from. And so you remember up here when we did redirect i D. We passed in the Post i d. This is the Post I d. Of whatever page they submitted the form from. So that's in our post data down here for us to be able to use. So there's a couple. There's a couple pieces to this. There's three built in WordPress function. So hopefully walk through this and it still makes sense. The 1st 1 is called Get Perma link. Okay, so what this is going to do is we're going to pass in our post redirect i d. And so what it does is it takes the post i d. And it creates a you earl out of it. And that's you need to use grip Perma link. Because based on what your Permal EQ settings are, it will correctly format and create that you, Earl. So get Perma link will do all that hard work for you. All you need to do is passed in the post i d. Which we saved. We had submitted in the form in this redirect I d element here. So this first creates the URL next. As I said before, we are going to show in our form, remember, we are going Teoh right here. We're gonna show a status message, and so were we Check for a u r l prominent called status. And if it is set toe one than we display a success message Well, over here on a form handler, we need to make sure that if everything submitted properly that that status parameter gets set back. So again, WordPress has a built in function that allows you to easily add query arguments to you or else. So we're gonna wrap get Perma link inside of this. Add query. Argh! Function now, The first sort of parameters in this are going to be what your you are. All parameters are going to be so you know, you could have five. You, Earl parameters, you would. You would just do them in this order. Status one, you know? Ah ah. Success to message equals three. Whatever you do, as many as you want the last. The last element in this method is going to be the u R l that all of these air going to be appended to Okay, so, um, you just make sure that this is always last inthe e the add query. Argh function because you can add as many euro parameters as you want. In this case, we only be we only happen to be adding the one. So this is all we need here. So what we will get from this is we will get a you, Earl to the correct post with a u R l parameter that that is status with the name of status and it is set to or equal to one. Okay, so that creates our u r l are properly privatized girl that we need from there. Then we can just do the actual redirect so WP redirect And what WP redirect needs is u R l redirect them to that. You were Well, now you again. You want to use WP redirect because it has again built in. It does sort of handling For what? Of? Javascript is disabled, and it makes sure that you don't have to call, do run the PHP header, and then the exit and all it just you just call WP redirect passing the URL, and it will do all of that stuff for you. Okay, so if we go back and we look at this 11. Lesson 10: Adding Custom Columns: So if we go back, we look at this again. We have our form handler. We create our post of our custom post type of crater feedback. We send emails, and then we redirect the user back to the page that they submitted the form from. So we have all of our ability to display the form. The form is submitted to admin post. We handle the form data. We create our feedback, and it now displays in the back end here on our in WordPress. And so we come over here. I probably should refresh this because sitting a while, but if we do Johnny Bravo, let's do just do the same. You, Earl, we submit this form. Your message was submitted successfully. If we come back over here to feedback, we get our message from Johnny Bravo. Pulled us out email address. This is Johnny's message. We get our data saved properly. How we would expect So we get everything that we sort of need here for this. So it allows us. We now have our form set up to collect data and store it, and now we can view it on the back end, so we sort of have the full sort of container that we need. There is one last thing that we ah want to do here. And that is and this is something I mean, this is something that is, I wouldn't say it's brand new, but it's fairly new. The wordpress that you may not see a ton of good tutorials help there. So you sort of getting some cutting edge stuff here, but you'll notice that I have title email website excerpt. I'm displaying custom field data in this. This these columns here. It doesn't work by that. Like that by default and Meyer fact, by default, you'll just have title and date here. So but wordpress allows you to customize these columns four specific post types. So that's the last thing that we're going to do here. And I'm gonna show you how to do that. Now, in order to do that, we are going to go over to our forms. Admin, um, class here actually may save this real quick when come over to our forms. Admin class here, and we're gonna add it in here because again, this is the admin area. So there are a couple. There's an action and a filter that we need to adhere. So I'm gonna drop the's in because they're a little bit longer, and then we'll just talk about him real quick. So the the filter is for there's two things you got to do when you create custom columns. First off, you need to tell WordPress you need to tell WordPress were adding extra columns. Okay, that's the first thing, then that's what the filter does. The second thing is, is you for each column, you need to tell WordPress This is the data display for this column. Okay, and that's what the action here does. So the filter adds the column. The action adds the data for the column. Now you'll notice in here again. We have manage, and then we have J mo contact form, and then we have posts. Columns. If this were a regular post, you would not have this j mo contact form. So if you just wanted ended the column on the posts page here, you would just do this manage post combs. But because we Onley want it to happen on this custom post type, you put in the custom post type the name of the custom post type that we created down here right here between manage and posts and that will apply this on Lee to this custom post type. So again, this is a hook. So we're telling it for this hook. We want you to use this method called columns Head, which will be in this class, and we're gonna create that in them in a second. Same thing for the action again managed J mo contact form. If you just want to do the post, you would get rid of this j mo contact form. But for here, this will only be applied to this particular post type and and here we're telling it for that hook, run the callback function content or columns content. We're setting a priority of 10. Not because that's we don't need. We don't care about that tennis or the default. So where that's not the one that we care about. We set it for this one right here. The reason we said it for this is because with action hooks you need by default, WordPress will only send one, um, one parameter for to your function. So when we create columns content, we're actually gonna have two parameters for that method and word. And this action hook has two pieces of data that it can send us. But by default, WordPress will only send one of them if you want both of them or if there's three of them. If you want all three, you have to tell WordPress I want three. Or if there's three of them, and you only want the first to you. Tell WordPress you put a to here until WordPress I want the 1st 2 Okay, so in this case, we want the 1st 2 pieces of data that WordPress consent us. So we put a two here, so that's we need to do that for that. Okay, so now we have our hooks in place. We just need to go ahead and write our methods. So ah, we come down under here creating new public function, and it's gonna be columns head, and this is our filter. And so we're going to get defaults. So these are the default com's that are already going to be there, right? And remember, with the filter, you're gonna get data, and you also have to make sure and return that data back to WordPress because if we don't return defaults than WordPress will not have that array available to it. And so it won't create any columns here. So again, we pass in defaults. We always make sure we return to faults on. All we're gonna do in our method here is is update this default array and then send it back . So we know by default, it has title and date. Mary talked about that. So we want to add in. Our calm is, but we actually want to put him in. Ah, particular order. So what we're actually gonna do is we're gonna unset. Ah, defaults, unfit defaults date. We're gonna get rid of it for a second. We know data is a pretty standard one. We know what we just sort of know what it is. So we're gonna be able to add it back in ah, pretty easily, and then just, uh, save a little time on you watching me type here, um, we're going to add in our custom columns, so we unset date, then we're gonna add in defaults. Submission, email. We're gonna remember this is just the column. So this is just Ah name. We want to give it. So this has date. This is the association Associative Array. This is the element that we want to give it, and it's set to email. And this is important because when we go to add the content, we're gonna check for each one of these, um, to see what calm or in. So we need to make sure we have this name. So we have given a name of submission, email or a key of submission email and then the value of email. Ah, submission website, website submission Xer, ex ERT. So this is what ads again, this is what adds these columns. If we pulled us over, it adds the columns and it gives them thes specific names. And if we look at this, hopefully this isn't too buried in here. You'll see that the name of this is submission email. So this you have this I d. And we have a class of submission email. So wordpress knows what the name of this column is. Okay. And so when we go to add content, we don't want to add the website under the email address and the excerpt under the website except We want to make sure that we add the content for email under email. Website under website, exit on the experts. So we need these. These keys right here. They could be anything you want, but you need to have them. And then this is the human readable label that will actually show up across here. Okay, So once we have that, then we can add are date back ends. We're going to do defaults, and we're gonna do date. And the way that we know this is I just inspected this element the day element before I removed it, and it tells you what it is. So it's not so hard to find and we want the human readable to be date. You could change this if you wanted to make it submission, date or whatever. You can really make it whatever you'd like. But this name needs to stay the same because that's how WordPress knows what data toe add there. All right, so, again, what this does, is it it? First, it removes date. It adds in these columns, and then add it's date back in so that these columns Ah, in our custom post type here these columns that we see here show up and they show up in this particular order email website excerpt date and again. You could do it. Whatever you order. You wanted that Just happen to be the order. I wanted it in. And then we return defaults back to WordPress so that it could actually display this. So that's our headers. Now, we need to specify the data for each one of these columns. So remember, we at public function columns content. And remember, we we specify that to number because we want both pieces of data. So we need the column name, and we need the post I d. And I'll show you why we need both of those here in a second. So the column name is pretty pretty straightforward. So we need to know what column were in so that we know what data to display. So what we're gonna do is we're gonna do if they want to do, uh, column name equals submission. Female. So that is what we set up here. That's why these air important. So if this is the column that were in, well, then we want to display Ah, the user data the user's email. So what we're gonna do is we're going to do we're gonna do another check. We're gonna check to see whether or not the email address is empty because we're displaying a link so we don't want to the link to show at all if if the email, if they didn't submit an email address and, uh, it's required, I know. But just again, you always were checking this stuff if they didn't submit une email address and we try to build a link without that email address we would run in, I think plentiful actually thrown air. And even if not, it would display, there would be an empty link sort of there, which we don't don't want that sort of messiness. We're going to check and see if there's actually data here. So we're gonna do not empty. And remember, submission email was a custom field. So we're gonna set submission e mail equal to get post meta. So we saved it as metadata That's synonymous, sort of with custom fields when it comes to posts. And so the built in wordpress function you used to get that post metta is get post meta and we pass in the post I d That's why we need both of these Both of these parameters that WordPress consent us because we need that post I d. So we can get the post meta we're going to do post i d. We're going to do submission email. I want to do true. Ah, and then do all these. Okay, So what this is doing is get post Metta is going to look through the post i d. That the post the Post I d that we just sent through. It's gonna look for a custom field called submission email which Ah, when we submit our form here, all right, we have a custom field called Submission the mouth submission website when we created our post. So that's why it's looking. We're gonna look for that particular one, because that's the name we gave it. So it's gonna look through that post to see if there's a custom field called submission email and if it is, it's going it's instead of basically this true means it's gonna return the content of that custom field. It's not gonna return an array. So if you, by default, get post Meadow will turn in a return. An array that is an associative array of the name of the custom field and the data that's in it. But if we just want the data, we can set this to true. Okay, so that's what Coat Post Might is going to do. We're some setting that equal to submission email, and we're checking if it's empty. If it's not empty, then we can go ahead and print it out. We're gonna do print F, and we're going to use our, um, our format here. So we're one a link a treff equals and we're going to do male two. We're gonna do a placeholder and then close up our link there. Do another place holder and we're going to pass in submission email twice, and I'll explain this here in just a second. So what this is doing again? Print F allows you to insert data into a format like this. So we're putting submission email into this first placeholder, which is the Earl of the Link that we just created. So that's male, and then it's prefixed with male to that essentially makes it so that what you're trying to do is when someone clicks on this email link you see in the bottom left it says mail to and then the email address. Oh, there's, Ah, browsers and email programs out there that when the mail to link like this is clicked, it will automatically open your default email program and create a new email to this person . So that's what we're we're ultimately doing there. Okay, so ah, and then the second submission email this place holder is the actual display of the email address in the column. So when you see this email address here, that's what's displaying it. So again, print F is a built in PHP function. You could con camp Incan could contain hate, but I like using print f just is cleaner to me. All right, so that's that is for the submission email. And I'm gonna just, uh, again sort of brevity sake here. Ah, drop in the last two because we have also the website and we have the excerpt. So it's it's a really it's very, very similar to what we just did. So submission website is pretty much identical, except that instead of getting submission email, we're gonna just look for submission websites over in the column name Submission website. We're going to grab the metadata, the custom field called Submission website from the Post I d. We're going to check if it's not empty. If it's not empty, we're gonna create a link. This time, we don't have a male to because it's not. The email address is just a standard U. R L Submission websites Submission website is identical to really this submission email except minus the mail to and the fact that it's submission website and says submission, email and then the last one is really, really simple. So if we're under the column name submission excerpt than we are going to call the the function, get the excerpt and we're gonna pass in the Post I d. Basically what that function does is it takes the post content, so that, in this case is, is the message that was submitted from the form. It takes that content and creates an excerpt out of it. And so we're actually in this page right here. We're just displaying the excerpt. So if someone writes a 30 page message to us, we're not going to display that whole thing here. the X Urbas believe it's 55 characters S o R. 55 words. So it's going to display the 1st 55 words of that message here, and then it will cut it off. And if we want the whole message, we can click through. Okay, so that's what get the excerpt does. And so for that excerpt block there, that's what we want to do. We want to display the excerpt so we just call, get the excerpt passing the post I. D. WordPress will grab that excerpt for us, and we just echo out into that column so pretty straightforward there. So all that allows us to then create those custom column so that we can see that data displayed on the front end or the back end. So that is the the full sort of 12. Final Thoughts: So that is the the full sort of. Of course, here you have a form it can collect, has the fields that you want. It can collect data. It takes that data, stores it in the database and then displays it to you in the back end of WordPress. In this feedback section and again, you can also add it like you can delete Utkan. Move this to trash. You just have all of the built in things for managing this data that you might want. You can export it through the WordPress exporter or if you install another plug in that allows exporting of custom post types. I just really think the custom post type thing is is a good way to go because it just allows you to tap into all of these things that can be added into WordPress, that if you build your own custom table and so forth, you would sort of have to work to support on your own. So anyway, that is again the full, full sort. Of course, they're the big idea here. It's not so much about the contact form and how to build a conduct form. It's not so much about maybe using this or whatever. It's really about some of the basics of how WordPress plug ins come together. Some of the the built in functions that Aaron Wordpress how you use those, you know, how you think about handling formed at a and so forth. So hopefully that gave you a really good introduction to WordPress and will building WordPress plug in. So thanks for watching. We'll talk later. 13. Next Steps: I'm honest there's no more. So online.com, so little housekeeping to finish up this course. If you haven't yet, be sure to head on over to the class area. There is a class section for some, some steps for you to walk through for this course. So be sure to head over in that it's under the discussion in Projects tab that you'll see on the course. Also, if you head over to my profile, be sure to give me a follow on my profile here so you'll be notified when I release new courses. And I also have an ongoing sort of weekly podcast style course called Let's Talk freelance. So if you would like to have sort of access to ongoing training regarding freelancing and online business and so forth. Be sure to check out that. Let's talk freelance course as well. And finally, I do have a daily tips newsletter on my website at John Morris online.com. If you head over there, you can sign up to that mailing list. You will also be put into my own, my very own mobile app, or you'll get access to over 78 hours of free content at the time of this recording related to freelance and so forth as well. So if you're interested in that, BD sure to check that out as well. Again, that's John Morris online.com. All right. Thank you for taking the class. If you enjoyed it, I appreciate you for You. Leave me a review and we'll see you in the next course.