{"id":137979,"date":"2015-03-13T08:00:00","date_gmt":"2015-03-13T12:00:00","guid":{"rendered":"http:\/\/premium.wpmudev.org\/blog\/?p=137979"},"modified":"2015-03-13T01:57:48","modified_gmt":"2015-03-13T05:57:48","slug":"featured-content-widget","status":"publish","type":"post","link":"https:\/\/wpmudev.com\/blog\/featured-content-widget\/","title":{"rendered":"Creating a Featured Content Widget \u2013 With its Own Image Uploader"},"content":{"rendered":"<p>Have you ever wanted to put something in the sidebar of your website that you couldn&#8217;t quite get to work with the default widgets or third party plugins?<\/p>\n<p>Widgets are pretty useful things for sharing related content, displaying authors, top content and more, and using the right widgets can make or break a website.<\/p>\n<p>In this article we&#8217;ll take a look at how you can use some code to make your own widgets. You&#8217;ll need a basic understanding of PHP and HTML at least. If you know some object oriented PHP that will be a plus, but isn&#8217;t necessary to understand the process, as I&#8217;ll explain along the way.<\/p>\n<p>Let&#8217;s get started.<\/p>\n<p><em>Note: Scroll to the bottom for a fully working plugin using the code in this post!<\/em><\/p>\n<h2>Our Goal<\/h2>\n<p>Learning by example is the most effective method, so let&#8217;s set a goal we want to achieve. A featured content widget is\u00a0be a good place to start. This widget would allow you to specify a title, add some text, an image and a link. This information would be presented in a nice way in the sidebar.<\/p>\n<p>The screenshots below show how this will all look when used in the new default Twenty Fifteen theme:<\/p>\n<figure id=\"attachment_137980\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-137980\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/02\/final.jpg\" alt=\"FInal Widget\" width=\"700\" height=\"456\" \/><figcaption class=\"wp-caption-text\">Our finished front and backend views.<\/figcaption><\/figure>\n<p>We&#8217;ll build the widget without the image capability first because it&#8217;s a bit simpler. Once we&#8217;ve figured everything else out we&#8217;ll add in the image to make\u00a0the widget\u00a0fully functional.<\/p>\n<h2>Creating a Plugin<\/h2>\n<p>You <em>can<\/em> add all the code in this article into your theme&#8217;s functions.php file but a widget really is something that should reside in a plugin. Creating one is pretty easy so let&#8217;s start with that!<\/p>\n<p>First, create a folder in your <code>wp-content\/plugins<\/code> directory and name it something unique. I&#8217;ll be using <code>my-featured-content<\/code>.<\/p>\n<p>Next, create the main plugin file within the folder. This should have the same name as the folder with a PHP extension: <code>my-featured-content.php<\/code>.<\/p>\n<p>Open the new file and paste the following PHP comment. This is parsed by WordPress and the information within is used in the plugins section to list your plugin.<\/p>\n<div class=\"gist\" data-gist=\"03f1da6260e472e74756b81f8293e420\" data-gist-file=\"plugin-header.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/03f1da6260e472e74756b81f8293e420.js?file=plugin-header.php\">Loading gist 03f1da6260e472e74756b81f8293e420<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>At this stage you have a fully functioning plugin! It doesn&#8217;t do anything but it will be listed in the plugins section and can be activated. Let&#8217;s do so now.<\/p>\n<figure id=\"attachment_137981\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-137981\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/02\/backend-widget.png\" alt=\"Backend Widget\" width=\"700\" height=\"81\" \/><figcaption class=\"wp-caption-text\">Our plugin listed in the backend.<\/figcaption><\/figure>\n<p>If you want to learn more about creating plugins in general, take a look at our <a href=\"https:\/\/wpmudev.com\/blog\/wordpress-plugin-development-guide\/\" target=\"_blank\">plugin development guide<\/a>.<\/p>\n<h2>The Components of a Widget<\/h2>\n<p>Creating a WordPress widget takes four steps. We need to initialize and set up the widget, output a form in the backend, add any rules for processing the backend form and, finally, specify how the widget behaves on the front-end. These steps all translate to specific functions. Let&#8217;s look at the big picture by drawing up the structure of our code.<\/p>\n<div class=\"gist\" data-gist=\"7e8d2bed87f16351c32568b8ed734ca3\" data-gist-file=\"widget-skeleton.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/7e8d2bed87f16351c32568b8ed734ca3.js?file=widget-skeleton.php\">Loading gist 7e8d2bed87f16351c32568b8ed734ca3<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Note that we are creating a class extending the <code>WP_Widget<\/code> class. If you have no idea what this means, don&#8217;t worry, you don&#8217;t need to know any object oriented PHP to create a good widget. What you do need to know, though, is how to initialize the class.<\/p>\n<p>You need to hook a function into <code>widgets_init<\/code> and from within that function use the <code>register_widget()<\/code> function to initialize the widget by passing it the name of your class.<\/p>\n<p>The &#8220;mfc&#8221; part of my naming scheme refers to &#8220;My Featured Content.&#8221; This is called function prefixing and serves to create more unique function names to prevent naming collisions between different plugins.<\/p>\n<p>Another tidbit which may help you is what a &#8220;method&#8221; and a &#8220;property&#8221; is. Functions contained within a class are referred to as methods. Variables defined within a class are called properties. There is no significant difference but it&#8217;s good to know so you don&#8217;t get confused by terminology.<\/p>\n<h3>The Widget Constructor<\/h3>\n<p>The <code>__construct()<\/code> method contains some basic information about the widget. The base class <code>WP_Widget<\/code> takes care of the heavy lifting for is. By adding the code below into the constructor, our widget will show up in the widgets section.<\/p>\n<div class=\"gist\" data-gist=\"7185a67b85f7f3a8f6f860fe31e78f25\" data-gist-file=\"constructor.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/7185a67b85f7f3a8f6f860fe31e78f25.js?file=constructor.php\">Loading gist 7185a67b85f7f3a8f6f860fe31e78f25<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<h3>The Backend Form<\/h3>\n<p>When the user drags our widget into the sidebar they&#8217;ll be presented with a form, which is used to populate the front-end display. In our case we need fields for: The title, the description, the link text and link URL. We add the image in later.<\/p>\n<p>The final version of the <code>form()<\/code> method is below. It&#8217;s quite long but don&#8217;t get to scared \u2013 I&#8217;ll explain everything underneath.<\/p>\n<div class=\"gist\" data-gist=\"e8020bd5219c8c7652216c8940332064\" data-gist-file=\"form.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/e8020bd5219c8c7652216c8940332064.js?file=form.php\">Loading gist e8020bd5219c8c7652216c8940332064<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>The only reason this is so long is that we have four fields. We begin by determining the value of each field. The <code>$instance<\/code> variable contains the values of our fields if they have already been saved. For each field we create a label and a user input element by using the <code>get_field_name()<\/code> and <code>get_field_id()<\/code> functions.<\/p>\n<p>The reason we need these functions instead of just typing the names and ids ourselves is that there may be multiple instances of the same widget around. WordPress uses some built-in magic to manage all this for us. The final name of our input element may be <code>widget-mfc_widget[2][link_url]<\/code> instead of just <code>link<\/code>. This is how WordPress handles multiple widget areas, multiple sidebars and multiple widgets.<\/p>\n<p>The result of this code should be a form in the widgets section you can use to fill out the widget details.<\/p>\n<figure id=\"attachment_137982\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-137982\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/02\/widget_form.jpg\" alt=\"Widget Form\" width=\"444\" height=\"389\" \/><figcaption class=\"wp-caption-text\">Our widget&#8217;s form in the widgets section.<\/figcaption><\/figure>\n<h3>Handling Form Data<\/h3>\n<p>Using the <code>update()<\/code> function we can determine what happens to our form data before it is saved. We actually don&#8217;t need anything special so our final function will look like this:<\/p>\n<div class=\"gist\" data-gist=\"e9ac1ef15008f47c0c2a2b672ea1cc3a\" data-gist-file=\"update.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/e9ac1ef15008f47c0c2a2b672ea1cc3a.js?file=update.php\">Loading gist e9ac1ef15008f47c0c2a2b672ea1cc3a<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>This function is handy if you want to do something to the form data before saving it. A good example is the RSS widget. When you enter the RSS URL and save it, the most recent items are retrieved and cached. You could use the function to validate and sanitize URLs, numbers and other data as well.<\/p>\n<h3>Displaying The Widget<\/h3>\n<p>Finally, the <code>widget()<\/code> function displays our widget. You can add any HTML here and it will be output in the sidebar.<\/p>\n<p>The function takes two arguments: The first one contains data about the widget area itself, and the second contains the instance variables of our widget.<\/p>\n<p>When widget areas are set up a number of parameters are defined. The content to add before\/after the widget and before\/after the widget title is most prominent. To make sure your widgets play nice with other plugins and WordPress itself it is a good idea to use the following frame when creating plugins:<\/p>\n<div class=\"gist\" data-gist=\"d267a6ff5ad838530d3e549ceab685f9\" data-gist-file=\"display.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/d267a6ff5ad838530d3e549ceab685f9.js?file=display.php\">Loading gist d267a6ff5ad838530d3e549ceab685f9<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Into this frame we add the value of the description field and the link, which we construct from the <code>link_url<\/code> and <code>link_title<\/code> fields, something like this:<\/p>\n<div class=\"gist\" data-gist=\"891f36ca322272d834e42587baaf5be0\" data-gist-file=\"html.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/891f36ca322272d834e42587baaf5be0.js?file=html.php\">Loading gist 891f36ca322272d834e42587baaf5be0<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Don&#8217;t forget to use string escaping functions, which serve to protect the data before it is served to the user. You can read more about this in the <a href=\"http:\/\/codex.wordpress.org\/Validating_Sanitizing_and_Escaping_User_Data\" target=\"_blank\">Validating, Sanitizing and Escaping User Data<\/a> article in the WordPress Codex. The result of our code should be the following:<\/p>\n<figure id=\"attachment_137983\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-137983\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/02\/Screen-Shot-2015-02-23-at-13.57.49.png\" alt=\"Featured Content\" width=\"262\" height=\"220\" \/><figcaption class=\"wp-caption-text\">The Featured Content widget so far.<\/figcaption><\/figure>\n<h2>Adding An Image<\/h2>\n<p>You can use a number of methods to add an image. At the bare minimum this will require some JS and CSS, which means we&#8217;ll have to learn how to add those to widgets. We will be using WordPress&#8217; built in media library function \u2013 no need to reinvent the wheel. If you&#8217;re building a custom solution, the methods of including JavaScript and stylesheets is almost exactly the same.<\/p>\n<p>We need to enqueue scripts, just like we would do on the front-end or the WordPress admin. The actions to do this must be defined in the constructor function. Let&#8217;s add the following to it:<\/p>\n<div class=\"gist\" data-gist=\"009a5efb3aa1e3ab9a0e279b7545b2c9\" data-gist-file=\"enqueue.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/009a5efb3aa1e3ab9a0e279b7545b2c9.js?file=enqueue.php\">Loading gist 009a5efb3aa1e3ab9a0e279b7545b2c9<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>If you&#8217;re not familiar with OOP (object oriented PHP) the notation may confuse you here. The second parameter of the <code>add_action()<\/code> function is usually a string which indicated the function that is called. The same thing is happening here but we are indicating that we want the <code>mfc_assets()<\/code> function from within our class, not the global scope.<\/p>\n<p>The next step is to create the <code>mfc_assets()<\/code> function inside our class and enqueue the necessary scripts and styles within it.<\/p>\n<div class=\"gist\" data-gist=\"6a87cc6d6ddef22e3ed57874d8274043\" data-gist-file=\"assets.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/6a87cc6d6ddef22e3ed57874d8274043.js?file=assets.php\">Loading gist 6a87cc6d6ddef22e3ed57874d8274043<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Above, we&#8217;ve enqueued the <code>media-upload<\/code> and <code>thickbox<\/code> scripts. These are included within WordPress and\u00a0are the basic components of the media dialogue. We also include our own <code>mfc-media-upload.js<\/code> file, which is a very simple JavaScript file that governs our upload process (more on this in a second). Last, but not least, the style required for the <code>thickbox<\/code> functionality is also enqueued.<\/p>\n<p>The next step is to modify the backend form to add the image field. We need to figure out the value of the image field and output the controls for it, just like we did before:<\/p>\n<div class=\"gist\" data-gist=\"bff23da6c619544d881d195ea8048766\" data-gist-file=\"image.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/bff23da6c619544d881d195ea8048766.js?file=image.php\">Loading gist bff23da6c619544d881d195ea8048766<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Note that this is very similar, the only addition is a button input with the class of <code>upload_image_button<\/code>. Our Javascript will detect when this button is pressed so we can select an image. Create a new file in the directory of your plugin, name it <code>mfc-media-upload.js<\/code>. The code you will need to paste inside is the following:<\/p>\n<div class=\"gist\" data-gist=\"499c97d28254072aa156814c85a2fd3b\" data-gist-file=\"widget-skeleton.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/499c97d28254072aa156814c85a2fd3b.js?file=widget-skeleton.php\">Loading gist 499c97d28254072aa156814c85a2fd3b<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>This bit of code will open up the media uploader screen when you click the button. Once you&#8217;ve chosen an image it will take the URL of the image and put it into the input element so it can be saved.<\/p>\n<p>Finally, we need to use the value of our image field to output an image in the front-end. I added mine above the description like this:<\/p>\n<div class=\"gist\" data-gist=\"a26fc92389c195257c891f685f71c187\" data-gist-file=\"image-display.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/a26fc92389c195257c891f685f71c187.js?file=image-display.php\">Loading gist a26fc92389c195257c891f685f71c187<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>The final result should look something like the screenshot below:<\/p>\n<figure id=\"attachment_137984\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-137984\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/02\/Screen-Shot-2015-02-23-at-14.27.40.png\" alt=\"Featured Content Widget With Image\" width=\"264\" height=\"334\" \/><figcaption class=\"wp-caption-text\">Our featured content widget wit an image<\/figcaption><\/figure>\n<h2>Conclusion<\/h2>\n<p>As you can see, creating a plugin takes a bit of work but once you get the hang of it, it should only take 15-20 minutes to churn out a simple one like this. It can add a lot of power and control for a user over a website, not to mention the stress it can take off a developer&#8217;s shoulders \u2013 the client can manage the sidebar.<\/p>\n<p>If you&#8217;d like to see the full code in action you can download the <a href=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/02\/my-featured-content.zip\" target=\"_blank\">plugin I&#8217;ve created<\/a> for this tutorial. You can activate and use it all you want, make sure to learn something nice from the code!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Have you ever wanted to put something in the sidebar of your website that you couldn&#8217;t quite get to work with the default widgets or third party plugins? In this post, we&#8217;ll look at how you can create your own widgets and even add an image uploader.<\/p>\n","protected":false},"author":344049,"featured_media":138984,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"blog_reading_time":"","wds_primary_category":0,"wds_primary_tutorials_categories":0,"footnotes":""},"categories":[557,263],"tags":[390,131,52],"tutorials_categories":[],"class_list":["post-137979","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","category-tutorials","tag-code","tag-developers","tag-widgets"],"_links":{"self":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/137979","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/users\/344049"}],"replies":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/comments?post=137979"}],"version-history":[{"count":3,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/137979\/revisions"}],"predecessor-version":[{"id":209260,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/137979\/revisions\/209260"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media\/138984"}],"wp:attachment":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media?parent=137979"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/categories?post=137979"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tags?post=137979"},{"taxonomy":"tutorials_categories","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tutorials_categories?post=137979"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}