 So, when I was growing up, I had a good friend who has since moved away. And I don't see him very often, I see him about once a year. And we don't do a very good job of keeping in contact. But the one positive thing that's come out of all of this is it ends up being really interesting to see snapshots of his life each year and the way things change. And a few years ago, I caught up with him and he talked about how he was taking up fishing. And one of the things he bragged about being economical, it was as a hobby. He said, listen, Sal, I bought a rod in a reel. I even dig worms out of my backyard for bait. I eat the fish after I catch them. I'm making money on this hobby. And then I saw him the next year and he had a little more equipment. He bought waders and a different tackle. Fast forwarded this year when I was talking to him and he's buying a boat. So, with many things, his hobby grew and in many ways I see this in websites. When I work on websites often with WordPress, I start out and right out of the box, I've got a great website doing what I need and then little by little, we need to grow it. We need to add some things. So this is an example of this happening. I was working with a client. We're working with a 2016 theme and they had a request. They said, hey, Sal, here's what a post looks like. What we'd really like to do is we'd like to add a subtitle. And I said, no problem. We can add a subtitle. And so I hopped into the editor and I went into the content and I put an H2 there and I said, all right, we've got a subtitle. And they pointed out that the word subtitle, if you break it down, sub means below, title. So here really what we added was a heading to our content rather than adding a true subtitle. So, okay. I needed some way to subtitle in here. And so I did the first thing I did is I took my theme and made a child theme out of it because I didn't want to edit the original theme. And I'm going into the child theme and I found template parts slash that single, which spits out that header area. In that header, you can see there's the title and that spits out an H1 tag. So that's that. And I said, great, we need a subtitle. So I went in and I added near the bottom H2 put in a subtitle. It's a beautiful day. And I took a look at the site. And indeed, now I've got a subtitle. I've got this under the title. Everything's good. But of course, this solution probably wouldn't please any client because those of you may have noticed I hard-coded this, which means that every post on the entire site is going to have the same subtitle. It's a beautiful day. They won't. But I think this is important and this is a big part of my process. I often feel a little overwhelmed with any programming task. If I can break it down, OK, I need to get a subtitle display. Well, can I just get an H2 to display with something in it? And then once I get that to work, then I can work on and build from there. And that's what I did in this. So we've got Hello World. And as we can see on another post here, this is my introduction to post MetaPost, I've got that same subtitle, not what we want. So we don't want this to be hard-coded any longer. So we need to put it somewhere in WordPress in the back end. So log in into WordPress and looking at the back end, we've got our title and we've got our content area. And it turns out we've actually got another area where we can store information. This is called our custom fields. And by default, it's there but not displayed. So here I'll show you how we can display it. If you scroll to the top, there's a screen options dropdown. You click it. In there, you get a bunch of checkboxes. And when you check custom fields, now you get this new custom fields box down at the bottom of your post where you can add this information. So that's exactly what we're going to do. We turn this on, we get it, and here's a zoom in of it. I'm on my Hello World post, it's my first post. And in here, I've got Add New Custom Field. And it's got room for me to add things. I'm going to add a name and a value. Now when it comes to naming it, it's sort of the title, what label are we putting on this? This is a subtitle that I want to put in. But now this area, these custom fields are used by lots and lots of WordPress plugins and even WordPress core itself. And I want to make sure I don't conflict with somebody else's work they're doing. So I'm going to prefix my name that I'm using here. I use fe underscore as my prefix, fe are the first two letters of my last name. So I use that and then subtitle to ensure uniqueness. So the name is fe subtitle and then the value I'm using is seize the day. I feel that would be a good subtitle. Seize the day and now I go up and I hit my update button and the page reloads in the back end and this value is still there. And I go to a different computer and I log in and I pull up this page to edit it. And this value is still there. This is important because it means that we've now stored it somewhere in WordPress, which means that we can then use it. It's important that when we put this information in, it persists. So we've got it in there. Now we need to spit it out. So this is that template part we looked at previously where we hardcoded our H2 in there. And so as we decided hardcoding in H2 isn't going to do what we need. So taking a look just at that one line, we're going to replace it with some PHP code to get that value that we've entered. And this is the code. We are going to dive into this and go through it. But right now I'm just going to call this magic code. It does what I need it to do. It pulls out that information. But there is one small piece I want you to take away from this magic code in this moment. And that is please note FE subtitle in that code. That is the name we used when we added our information. So we've got that code block and we will explore it. But right now just note we are using that name that we used. FE subtitle. Great. So there it is again. We put it in. We named it FE subtitle. Seize the day is that value that we put in there. And it turns out using that magic code, if I go visit my page now on my Hello World post where I added this, it says seize the day. I do have resources that I'll be tweeting out at the end. You've got the slides up right now. I do have links in here to some template code. I have that child theme that I created available on GitHub to anyone if you want to check out the code. That'll come out at the end. So I'm now hopping to a different post, an introduction to post meta. Hello World was my first post. This is the fourth blog. And I go down to my custom fields and I notice something different. And it's pretty cool. And that is when I get to that name area, I don't just get a blank field. I get a dropdown I can choose from. WordPress says, hey, I noticed you'd use Fe subtitle on one of your other blog posts. Maybe you want to use it here too. So that saves me from making those typo errors and making something plural or prefix. And then I didn't get it right here. So it has that prepopulated. So I'm going to use Fe subtitle here once again as that name. And my value is going to be extend WordPress posts. That's the subtitle I want on this post. So now when I take a look at it, indeed my magic doing its work. This is post number four, an introduction to post meta. I've got the subtitle I entered here. I go back to Hello World, my other post. I get the subtitle I entered there. So now I've got the functionality that I wanted. My client can now enter subtitles on all their different posts and have the information they want. Grocery shopping. Every time I go to the grocery store, I am faced with that decision as I get to the bill. There's the little cart and the big cart. And I go, I don't even look at the baskets anymore. I've got two boys at home. And so the basket is definitely way too small. But I'll often look at that list and I'll say, you know what? I think I could use the little cart. And inevitably, I get halfway through the store. I'm about to the deli and I realize there is no way making it through the shopping trick. So I get the big cart and I take things and I put them in. And other shoppers come in and give me that look like, should have taken the big cart to start with. Fortunately, WordPress is smarter than that. WordPress is ahead of me on this. WordPress does not make us choose between a little cart or a big cart. WordPress is built to grow and handle additional information that we're adding. This information goes in the database. Now, I need to confess, when I started programming and for a long time after I started, I was terrified of databases. And slowly I've overcome that fear to some degree. A couple of things help with that. One of the big things is I now run my websites locally when I'm doing development and I'm changing things. That way when I break everything, there's still a good website out there running for everybody. But my copy here I can break and then go back and fix. So that's probably the biggest thing that has allowed me to dive into databases. But what that has allowed then is for me to get a better mental model. And I realize that databases are a lot like spreadsheets. And once I started thinking about database in terms of a spreadsheet, my life was much smoother. So for WordPress, there are a number of database tables, they call them. And a database is very much like a spreadsheet tab. You have a spreadsheet that has multiple tabs, you flip through the sheets, each table is like that. So one of these is called WP posts. And this is where our blog posts go. When we type in that blog post and we put in the title and we put in our content, all of it is stored in this table. And it has columns. It's got 23 different columns, ID, post title, post content. And so ID is a self-incrementing number. That just keeps track of what post this is. WordPress likes to have that identifier. Okay, it's that post. Hello world is the first post, post ID one. Then our post title, our post content, even though content looks like a small box there, everything that you put into that editor gets stored in this area. Post status, post status, did you publish this post? Is it a draft? And there's a number more, as I said, there are 23 columns. But what there is not, is there isn't a subtitle column. There's no spot for that subtitle to be stored. Instead WordPress has a database table, another sheet, another tab in that spreadsheet. And it's called WP post meta. Post I have to be a confusing term when I stick with it, because I thought of it as after meta. Like post apocalyptic is after the apocalypse. But here what we're doing is we're saying this is post as in blog post meta. Meta information is just information about something. Meta information about me is my height, my shoe size, my age. So post meta is information about posts. And this table has only four columns, the meta ID. Again, this is one of those self increment ID numbers. We've got two right now, next one would be three, the one after that would be four. I'm gonna hop over to meta key, which looks familiar as that name we put in when we added our custom field, our custom value there. And then the value that goes with it is our meta value. So you see epi subtitle and seize the day, epi subtitle and extend WordPress posts. And then we have that post ID column. And so this is a really clever thing that they do. So instead of trying to jam everything into the WP post table, they have this entirely separate table where we do things and we map them back. So post ID tells us which post does this information go with. The subtitle seize the day goes with post ID one. Going back post ID one was our hello world post. Looking down post ID four is in the post meta. And indeed our second subtitle has a post ID four. That's how the information's being connected. So what we have these two different database tables, the information is still being applied back to the original posts. So how do we get this information out of the table? Out of this spreadsheet. We've got it living in there, but now we wanna pull it out so we can use it. And to do that, we use a thing called get post meta. In general, it takes three parameters. The post ID, we just saw that ID, that value that indicates okay, is let's go with the hello world post number one, introduction of post meta post number four, or some other post. So that number that identifies the post we're interested in, the meta key, and then a third value, which can be either true or false. Now I need to tell you, I have been doing this for a number of years and I have literally never used false as the third value. I read an interesting post about that false works as a good third value. I have it linked in the resources, certainly you can take a look at it if you wanna learn more. For right now, use true. Your life will be easier, just use true. So in my example here, I get post meta and tell it I want post number four, I want that FE subtitle, and then I give it true because I always give it true as that third parameter. And that is going to go into the table, find the matching row and give me that value back. So in that case, that would give me that post ID four, FE subtitle, and I would get extended WordPress posts back. So get post meta is what we use to pull information out of that table. And there it is. So let's dive back into the subtitle code that was ever so magical and see if we can take away some of the magic. So the first thing we do is we call a function called get the ID. And what get the ID is it says, okay, I'm WordPress, I'm showing you some page right now. What ID goes along with the post that I'm showing you? If you're looking at the hello world post, the ID is gonna be one. If you're looking at the introduction to post meta, the ID is gonna be four. So get the ID is gonna give us that number. So post ID is now the number of the post we're looking at. We're gonna use get post meta that we just looked at. We give it that post ID. This is the one we're looking at right now. So we're showing the right subtitle for the right post. I'm using fe subtitle to tell it, this is the key, the meta key I wanna look up. And I'm using that third value of true because I always use true and I get back my subtitle. Now I'm gonna do one last thing before we display it and that is I'm going to check and make sure we got a subtitle back. We added a subtitle to two of our posts. Right now this website has four posts. It can have 100 posts and only two of them have subtitles. So we don't wanna spit something out on pages that don't have subtitles. So I'm gonna check and say, hey, if there is a subtitle, then echo out H2 tags with subtitle in between. When there is no post meta in the table, the get post meta, this subtitle value would have a value empty string. That's like having an opening quote and a closing quote right next to each other with nothing in between. That comes back. So in our if statement we're checking saying, hey, is this true? Or do we have something? And that spits out. So our subtitle code to display it. And indeed we did see this out what we need. Now I have a confession to make. I have a pet peeve reading blog posts that talk about code and have coding tables. I get all excited and then I get to this point where they say, this code is not productive ready. Do not use this code on a live website. And I get so frustrated because I just wanna copy and paste it, make my life easy. So my confession here is this code is not production ready. Don't run this on a live website. However, we're gonna fix it so you can run it on a live website. We're gonna refactor this. And the whole thing here that we're gonna refactor is down in this echo statement when we're spitting it out. Now our problem is when we have that field there that we allowed them to enter. We can have a website that we control. We have lots of people writing different blog posts. They're entering and they go in and they put in a subtitle. And maybe they put in something malicious in this subtitle field. One example of something malicious that could go in there would be a script tag that loads JavaScript from another website. And that other website could then load JavaScript which comes back and does something that varies. Like, listens for the cookie of a log user, sends that information back. So then what else could login as the user from a different machine based on the information they stole. So we don't want to allow this type of thing to happen. One of the things we really don't want is the idea that people could put tags in there and load JavaScript. So we're gonna make one small change on that line. And that's it. We're gonna wrap subtitle in a function call to escape HTML. And what that's going to do is it's going to prevent any HTML that is entered in that field from rendering on the page. Try and put in a script. It's not going to work. So anytime we're outputting information here we want to escape it to make sure that we're not allowing anything that varies in it. This code is now refactored. And this code is production ready and you can run it on your live website. The link to the template code has this in it. I would feel comfortable deploying this on my own site or a client site. So let's take a look at more fun that we can have these custom fields. So you'll see here that we've added a second one. There's that add custom down there. We can add more than one of these. We're not limited to one. And here I'm adding FE underscored because I'm using that unique prefix to make sure somebody else code. I don't conflict with them. At the time I'm calling it learn underscore more. And I'm gonna put in a URL. As a matter of fact, this is a URL to my companion blog post to this talk which I will tweet out at the end of the talk. And so that has more information here that people use. If I take a look at my WP post meta table and after I save this, hey, look, I've got a new row. I've got a meta ID of three, right? It keeps auto incrementing each one that gets added. The post ID is four because we added this to post number four. The meta key is different now at four because that's the key we put in. And the meta value is that URL that we just entered. Great, our database. I can pull it back out using get post meta. If I give it the ID of four, that meta key, FE learn more. Third value always true. That will pull that URL back out and I will have it to work with. So now once I have it, I can use it and display it on my page. So my code to display the learn more link would look something like this. I'm gonna grab the post ID. I'm going to get the URL by calling get post meta. I'm going to check and make sure I got some value back. Does this post have this information? And then I'm gonna echo out. And in this case, I'm creating a link with an A tag. It's always gonna say for and the URL is what's gonna go in the A track. And indeed, if I do this, I put a little bit of CSS on there to make it look like nice pretty new button and I get this learn more button on there. Again, I've got a link to the template code. So we'll take a look back at this. And once again, I need to make my disclaimer. This code is not production ready. Don't run this on a live website. So we'll fix it. And to fix it, again, we're gonna change that echo statement because that's where we need to focus. And before we even fix it, I'm going to change it to make it easier to fix. And that is by using the printf function. The printf function is highly underutilized and super awesome. And I wish I started using it sooner because it makes my life so much easier. Printf takes a string. But in that string, you can put some placeholders that say, hey, hang on to this. We're gonna put something in here. That's what we've got. We're spitting out an A tag with an href, our quotation marks. And then I put this person which says hold this spot. We're gonna put something here. And then we close it and we have learned more and I'll press it. And then on the next line, I tell it, hey, this is what to put in that percent S spot. This is particularly nice when you have a bunch of pieces that you try to need to put together. And I don't know if you've ever got to the point where you're opening quotes and closing quotes and putting periods in between them to take a whole bunch of strings and put them together. This is a really nice way away from that and be able to pull things together in a nice, tidy way. You can see what it's gonna look like at the beginning with your placeholders and then just tell it, these are the pieces to go in. This also works very well in making a room and making it cleaner when I add my escape in functions. Last time we escaped HTML because we were displaying some content. We were worried that somebody might put in HTML tags there. We didn't want that to happen. Now here we're not putting in content. Here it's a URL. So we've got a different escape in function called escape URL. Again, there are tricks people can use. If you're doing something with an href you could do JavaScript colon and then put JavaScript to execute in there. And again, we really don't want to give people the ability to just add JavaScript to our pages. So this is going to make sure we don't have any problem like that happen. So escape URL, this is now refactored. This code is good to use. I would use it on my own site. I would put it on a client's site. All right, if we can hang on to questions for the end. I would love to take them, thank you. Going back to the hello world post. I'm gonna add another piece of post meta here. And I know we're adding lots of post meta. This is the last one. And this one I'm calling fe underscore color. And some of you who spend time with CSS recognize what I've put in there. I'd ff0000 that is a decimal color. That is red. So I'm giving it a color in CSS format. Take a look at the WP post meta table. Indeed it shows up there. We can see my post ID is one. We're down at the bottom here. Meta ID is four, fe color. And then we've got that red color here at the end. ff0000. And using that, I can add some code then why that in my theme. So much of this should look very similar. So we'll break this part, right? Post ID, we've got the post ID. Get post meta, we give it the post ID. We give it our fe color. We always give it true as the third parameter. We get our color back. Now we're gonna do something just a little different here. And that is we're gonna have a default. So I'm gonna say if there's no color, if that color was an empty string that didn't give us anything, then I want the color to be set to black. There are some CSS colors you can define by name. I could have instead used pound sign and then six zeros behind it. You can do by name. In this case, I'm doing it by name. We'll use the color black instead. So that's our default. Default color is black. If there's a value stored in our post meta, we're gonna use that. And then I'm using my print f. I've taken my header line and added this style, style color, and then percent s because that's the point. And then we are putting in the color. I've wrapped that in an escaping function. In this case, escape attribute because we are working on an attribute in here. So there are a lot of different escaping functions. Really, those are the three big ones I use the most escape h, escape url, escape. But whenever we have people putting in this information, it's a good idea to escape it. We're putting it out. So after we do all this, what's it look like? If we go and take a look, oh, now I can change the color of my header. That's fun. Gutenberg is coming. If you were here for the previous talk, you've heard a lot about it. A lot of interesting stuff going on. One of the things that happens with Gutenberg is the custom fields meta box is going away. You can't go up and pull the check box and have that pop up. Which sounds like a bad thing, but it really isn't. And that's for a couple of reasons. Two primarily. The first reason is that you can get it back. There's a plugin called the Custom Field Gutenberg Plugin. You run that plugin, you will get that same box that we were just looking at on your Gutenberg site. So you can get it back. But the real reason that it isn't as important or not really bad news that it's going away is that that box we've been working in isn't really the best user experience. Now I certainly managed some post meta on my own site in that way. But I'm working with a client to tell them, oh, well you need to scroll down to the bottom and then type in fe underscore subtitle and then you can put the subtitle. Not a real experience. And so the good news is there are some tools we can use. One of them that I really like is called CMB2. This is a WordPress plugin on the WordPress.org repository. It is freely available. And it allows you to create custom fields. So if you take a look with a little bit of configuration and I've got a link to that in the resources here, you get this cool meta box of custom fields. And it says, oh hey, title color is the label I gave it. And I told it I want this meta box to be wired up to fe color. So notice that little red swatch in there that it gives us as the preview. So now if I go in and click that select color, I get this nice color that comes up. And I can go in, I can pick a different color. Here I pick the blue that I use in a lot of my branding. I hit update and take a look. You can see that my title color is now blue. And when we look down here at fe color, that blue value is updated there. And if we go looking wp post meta, notice that last line, that value has been updated there. So we're doing that same post meta update. But now we're using some additional tools on top to really improve the user's experience. Because it's no fun typing in fe underscore color. So we populate that in, they're good to go. And there we can see if we go and view it. Yes, indeed, showing the title with that new. CMB2 has a lot of different field types. We can be helpful. For example, the email type. If I try and put something in that doesn't have an at sign, not going to let me put that in, I'm gonna have to admit that isn't helpful. So there are a lot of different field types, a very useful tool and really makes the experience for our clients much more friendly. So to recap, you've got the wp post meta table, where we've got post meta information. We tie it to the post table through that post ID. And we use the git post and meta function to pull that information out. By giving it the post ID, the meta goes with it. And then always that third value of truth. I am Sal Farello. I do work as iron code studio. I do have a blog post as a companion to this at salcode.com slash post dash meta. I am on Twitter as Sal code and I will be tweeting out that link. And I appreciate your time today, thank you. And we do have lunch coming up at this starting in seven minutes. So if anyone wants to run out the door, I will not be offended. But if anyone wants to ask a question or two, we can do a few here. After this, I am heading to the happiness bar, which is the desk area out there where we're providing support for anybody who needs it. And I will be out there and I would love to continue conversations out there as well. But does anyone have any questions in here? I just have one question, yes. So the question was when working with printf, we had that percent s in there, which is our placeholder. What if we had more than one of those? What if we have a whole bunch of them? Printf actually, really cool. First, you can have lots of them and then give them sequentially and they will get filled in sequentially. You can also, and I never remember the format and I always have to look it up, you can do something where you give it a number in it. It's something like percent one dollar sign s, percent two dollar sign s. And so you tell it, this is the first one, this is the second one, this is the third one, which works well in terms of changing order. And that comes up sometimes when creating translations, people will use that for translations because maybe those fields get reversed in different languages. So short answer is it will do them in order. Most of the time that works fine for me. Occasionally, it's nice to have one in there where you designate what order you need them in. Correct, yep, just comma's going right after it. So it's a little weird in terms of a function because you give it always that first parameter but then however many more parameters you need to give it just with commas, right? So comma, first value, comma, second value, comma, third value, absolutely. Good question, question in the front. Yeah, very high level. How would you choose between advanced custom fields and CMB2? So advanced custom fields is a commercial plugin that you can purchase, which is a very reasonable and terrific plugin and does great stuff. It actually has a drag and drop editor that you can create, which is nice. You know what, they are both nice. ACF does have an advantage if you need to have nested fields within nested fields. That is not a capability that is in CMB2. So in that case, I will definitely go there. My one thing that I really like about CMB2 is by default you define a PHP code. ACF, if you define it in the editor experience there, I always export that to PHP code because I want my configuration to live in code. If I make a copy of this site somewhere I don't have to worry about, I need to copy the database to get the same behavior over there. So I tend to lean towards CMB2 for that reason. And that is always publicly available and if somebody else wants to use it they don't have to worry about purchasing the plugin. But ACF is very powerful and a wonderful value and I do use it on some projects. So any other questions? Awesome, great. Well let's wrap it up. Have a great lunch. I will be at the happiness bar and I would love to continue any conversations there about PostMiller. Have a great day.