{"id":150020,"date":"2016-02-09T10:00:00","date_gmt":"2016-02-09T15:00:00","guid":{"rendered":"http:\/\/premium.wpmudev.org\/blog\/?p=150020"},"modified":"2016-09-26T07:06:53","modified_gmt":"2016-09-26T07:06:53","slug":"wordpress-development-beginners-building-plugins","status":"publish","type":"post","link":"https:\/\/wpmudev.com\/blog\/wordpress-development-beginners-building-plugins\/","title":{"rendered":"WordPress Development for Beginners: Building Plugins"},"content":{"rendered":"<p>Interested in creating your own plugin for WordPress from scratch?<\/p>\n<p>Coding your own plugin if you haven\u2019t done it before may feel like you\u2019re venturing into no man\u2019s land, especially if you\u2019re not super confident about your PHP skills. The challenge is knowing how to get started \u2013 and being open to making mistakes along the way.<\/p>\n<p>Plugins allow you to add all kinds of functionality to WordPress, from adding a simple contact form to a page to beefing up your security and adding eCommerce capabilities. If you can dream it up, there\u2019s probably a plugin that can do it \u2013 or an idea for a plugin you can build yourself.<\/p>\n<p>This is the final post in our five-part series for beginners, teaching you the fundamental concepts of WordPress development so you can take the leap from tinkerer to developer. By the end of the series, you should be able to create your own rudimentary themes and plugins, and flesh them out with your own features.<\/p>\n<p>In this tutorial, you\u2019ll learn how to code your own plugin so you can modify the functionality of your WordPress site, third party plugins and even themes.<\/p>\n<p><em>Note: For this series, it\u2019s important that you already have a thorough understanding of HTML and CSS as both of these languages are essential building blocks when working with WordPress.<\/em><\/p>\n<p>Let\u2019s get started!<\/p>\n<p><strong>Missed a tutorial in our WordPress Development for Beginners series? You can catch up on all five posts here:<\/strong><\/p>\n<ul>\n<li><a href=\"https:\/\/wpmudev.com\/blog\/wordpress-development-beginners-getting-started\/\" target=\"_blank\">WordPress Development for Beginners: Getting Started<\/a><\/li>\n<li><a href=\"https:\/\/wpmudev.com\/blog\/wordpress-development-beginners-php\/\" target=\"_blank\">WordPress Development for Beginners: Learning PHP<\/a><\/li>\n<li><a href=\"https:\/\/wpmudev.com\/blog\/theme-development\/\" target=\"_blank\">WordPress Development for Beginners: Building Themes<\/a><\/li>\n<li><a href=\"https:\/\/wpmudev.com\/blog\/wordpress-development-beginners-widgets-menus\/\" target=\"_blank\">WordPress Development for Beginners: Widgets and Menus<\/a><\/li>\n<li><a href=\"https:\/\/wpmudev.com\/blog\/wordpress-development-beginners-building-plugins\/\" target=\"_blank\">WordPress Development for Beginners: Building Plugins<\/a><\/li>\n<\/ul>\n<h3>Hooks, Actions and Filters<\/h3>\n<p>Before we get stuck into making an actual plugin, let&#8217;s take a detailed look at hooks, actions and filters. It&#8217;s these elements that the whole plugin system is based on and will help you fully understand the behind the scenes of how WordPress actually works.<\/p>\n<p>Let&#8217;s have a look at an example.<\/p>\n<p>What if you wanted to create a plugin that added some analytics tracking code to your site? Tracking code is typically placed at the bottom of a webpage right before the closing <code>&lt;body&gt;<\/code> tag. It must remain in place if the theme is switched and it must work on any WordPress install. So, if you don&#8217;t have control over themes directly, how do you do this?<\/p>\n<p>Remember back in <a href=\"https:\/\/wpmudev.com\/blog\/theme-development\/\" target=\"_blank\">WordPress Development for Beginners: Building Themes<\/a> I mentioned the <code>wp_head()<\/code> and <code>wp_footer()<\/code> functions and how you must add these to your theme? Our example above is exactly why these must be present. The <code>wp_footer()<\/code> function can execute other functions defined by plugins.<\/p>\n<p>Here&#8217;s\u00a0a code example you can play with:<\/p>\n<div class=\"gist\" data-gist=\"cd771764131ae237fc6d4af93bcb5f63\" data-gist-file=\"basichook.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/cd771764131ae237fc6d4af93bcb5f63.js?file=basichook.php\">Loading gist cd771764131ae237fc6d4af93bcb5f63<\/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>Let&#8217;s break it all down. Firstly, I wrote a function that simply echoes the tracking code. It isn&#8217;t used anywhere, it&#8217;s just a function sitting there in my plugin. Then, using the <code>add_action()<\/code> function, I told WordPress when to execute my function.<\/p>\n<p>Whenever WordPress gets to the <code>wp_header()<\/code> function it finds all other functions, which are hooked to it using <code>add_action()<\/code>. It then executes these functions one-by-one, echoing the tracking code as a result.<\/p>\n<p>This is the basis of hooks but we&#8217;ll delve into them in a bit more depth later in this tutorial so you can learn about and use their power. Before moving on, I want to mention a slight correction. The <code>wp_footer()<\/code> function in the footer of themes is not actually a hook, it&#8217;s a simple function that contains the hook somewhere within its code. A hook is called like this: <code>do_action('wp_footer')<\/code>, but this really wasn&#8217;t important for the first example, you&#8217;ll understand more about this soon!<\/p>\n<h4>Terminology<\/h4>\n<p>Now that you&#8217;ve had a taste of what&#8217;s to come, let me properly explain the terminology you&#8217;ll read about in this tutorial before we move on.<\/p>\n<p><strong>Hooks<\/strong> are a part of the WordPress <code>Plugin API<\/code>. Actions and filters are two different types of hooks. <strong>Actions<\/strong> allow you to add functionality, you basically define a function that is run whenever the hook is processed by WordPress. A <strong>filter<\/strong> works similarly, but instead of adding functionality, it modifies existing functionality. For example, WordPress has a hook which determines the length of the excerpt: 55 words. You can use a filter to modify it to different word count.<\/p>\n<h4>All About Actions<\/h4>\n<p>Now that we know the basics, let&#8217;s look at the <code>add_action()<\/code> function in more detail to understand it better. The function takes four arguments, which are:<\/p>\n<ul>\n<li>Name of the hook<\/li>\n<li>Name of our hooked function<\/li>\n<li>Priority<\/li>\n<li>Accepted arguments<\/li>\n<\/ul>\n<p>We&#8217;ve already looked at the first two, which are the only required ones. They identify which function should be executed and where it should be run.<\/p>\n<p>The third parameter determines the order of the functions that are executed. This is useful when there are multiple functions tied to the same hook. It&#8217;s entirely possible that you want to add multiple tracking codes to a website. Using the priority argument you can control when your function is run.<\/p>\n<p>The accepted arguments simply tells WordPress how many arguments the hooked function accepts. You&#8217;ll need to look in the <a href=\"https:\/\/codex.wordpress.org\/Plugin_API\" target=\"_blank\">WordPress Codex<\/a> for each hook to see if you need to add something here. Some functions take more than one argument, in which case you&#8217;ll need to specify it here. Take a look at the example below and you&#8217;ll see why this is the way it is when creating our own hooks a bit later.<\/p>\n<p><strong>Example Action<\/strong><\/p>\n<p>WordPress doesn&#8217;t just offer actions in themes but also in the backend admin and within the context of specific user actions. The <code>publish_post<\/code> hook is run whenever a post is published, allowing you do something at that point.<\/p>\n<p>The need for arguments becomes apparent here. If I add a function to this hook, how do I know which post was published and what the details were? Looking at the <a href=\"https:\/\/codex.wordpress.org\/Plugin_API\/Action_Reference\/publish_post\" target=\"_blank\">hook documentation<\/a>, you can see that the function is passed the post ID and post data as two arguments.<\/p>\n<p>For example, let&#8217;s send an email to the post author when a post is published:<\/p>\n<div class=\"gist\" data-gist=\"d31f6febc709c93d4207e31a01e551ad\" data-gist-file=\"email.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/d31f6febc709c93d4207e31a01e551ad.js?file=email.php\">Loading gist d31f6febc709c93d4207e31a01e551ad<\/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<h4>All About Filters<\/h4>\n<p>As I mentioned earlier, filters work in much the same way but modify data so you&#8217;ll mostly be returning within your hooked functions. To add filters we use the <code>add_filter()<\/code> function, which takes the same arguments as <code>add_action()<\/code>.<\/p>\n<p><strong>Example Filters<\/strong><\/p>\n<p>A good example to start with is modifying the <code>more<\/code> string at the end of excerpts which is &#8220;[&#8230;]&#8221; by default. To modify this you could do something like this:<\/p>\n<div class=\"gist\" data-gist=\"27d3312fa1bdf450c48d1e6c9f3b28b7\" data-gist-file=\"more.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/27d3312fa1bdf450c48d1e6c9f3b28b7.js?file=more.php\">Loading gist 27d3312fa1bdf450c48d1e6c9f3b28b7<\/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 I have not specified the priority and the accepted arguments. This will make the priority 10 and the accepted args 1. I&#8217;m not using the argument passed (the default more text) at all, I&#8217;m just returning a string.<\/p>\n<p>You could use the same method to embed an advertisement within the first paragraph of your single post content. Take a look:<\/p>\n<div class=\"gist\" data-gist=\"74c1f55e20718b36b358f1516ab91579\" data-gist-file=\"contentad.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/74c1f55e20718b36b358f1516ab91579.js?file=contentad.php\">Loading gist 74c1f55e20718b36b358f1516ab91579<\/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>With a little CSS to float the ad to the right, you could have a standard ad block within your content in a just few seconds.<\/p>\n<h3>Defining Hooks<\/h3>\n<p>Learning about how hooks are defined and how to create our own can greatly aid in the understanding of the system. Let&#8217;s say you&#8217;re creating an eCommerce plugin and you&#8217;re adding the functionality to list products, you could do something like this:<\/p>\n<div class=\"gist\" data-gist=\"0de4b8ac06b75009fb9d89c53427aca7\" data-gist-file=\"products.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/0de4b8ac06b75009fb9d89c53427aca7.js?file=products.php\">Loading gist 0de4b8ac06b75009fb9d89c53427aca7<\/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>You&#8217;ve essentially hard-coded that you want to show 10 products. What if someone is creating an extension for your work and wants a view where only three products are shown? If you write your code cleverly, you can allow others to modify it. Let&#8217;s use a hook to allow developers to tap into our work.<\/p>\n<div class=\"gist\" data-gist=\"9f296d5d3e6bfc31293e4aecdcc90478\" data-gist-file=\"product-hooks.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/9f296d5d3e6bfc31293e4aecdcc90478.js?file=product-hooks.php\">Loading gist 9f296d5d3e6bfc31293e4aecdcc90478<\/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>By using the <code>apply_filters()<\/code> function we&#8217;re telling WordPress that we have a hook named &#8220;product_count&#8221; and we want to run all functions hooked to it. In any other plugin, someone could change this value to three with the following method:<\/p>\n<div class=\"gist\" data-gist=\"8be0d36778a5ee9988675b1789b66df4\" data-gist-file=\"product-count-mod.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/8be0d36778a5ee9988675b1789b66df4.js?file=product-count-mod.php\">Loading gist 8be0d36778a5ee9988675b1789b66df4<\/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 Basics of Plugin Creation<\/h3>\n<p>Now that we know all about hooks we need to know where to put them. Let&#8217;s take a step back and look at plugins in general.<\/p>\n<p>Plugins reside in the main plugins directory of your WordPress site, which is usually found in <code>wp-content\/plugins<\/code>. As an example, let&#8217;s create a plugin that adds a tweet link below posts.<\/p>\n<p>First, create a folder in your plugins directory and name it\u00a0<code>tweet-plugin-tutorial<\/code>. Create a file within this folder and name it\u00a0<code>tweet-plugin-tutorial.php<\/code>. Open the file and paste in the following code:<\/p>\n<div class=\"gist\" data-gist=\"fa668fa2913e64f557a474cfddda4bd6\" data-gist-file=\"plugin-info.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/fa668fa2913e64f557a474cfddda4bd6.js?file=plugin-info.php\">Loading gist fa668fa2913e64f557a474cfddda4bd6<\/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 information is displayed in the backend admin of your site in the plugins section. Once you save the file you should see your new plugin listed; you&#8217;ve just created a perfectly functioning plugin. It doesn&#8217;t do anything just yet, but it can be activated. Go ahead and do that now.<\/p>\n<p>We&#8217;ve actually done 90% of the work. All we need to do now is find a way to add our link to the end of the post content. You can think of this as modifying the post content by appending some text to it. This means we&#8217;ll need to use the <code>the_content<\/code> hook, like before:<\/p>\n<div class=\"gist\" data-gist=\"922bce0d9c58160a34a2f4eba5860069\" data-gist-file=\"tweet-link.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/922bce0d9c58160a34a2f4eba5860069.js?file=tweet-link.php\">Loading gist 922bce0d9c58160a34a2f4eba5860069<\/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 will add a link after our content, which will allow users to tweet and the link will already be filled in the tweet box.<\/p>\n<figure id=\"attachment_150024\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-150024\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/12\/Screen-Shot-2015-12-10-at-11.51.28.png\" alt=\"Tweet link in Twenty Sixteen\" width=\"735\" height=\"580\" \/><figcaption class=\"wp-caption-text\">Tweet link in Twenty Sixteen<\/figcaption><\/figure>\n<p>That&#8217;s actually all there is to know about plugin creation. All plugins are a mixture of functions and hooks that determine where these functions are executed. From now on, all you need to focus on is learning various sub-systems like the <a href=\"https:\/\/codex.wordpress.org\/Options_API\" target=\"_blank\">Options API<\/a>, <a href=\"https:\/\/codex.wordpress.org\/Metadata_API\" target=\"_blank\">Metadata API<\/a> and so on.<\/p>\n<h3>Adding Theme Options to Plugins<\/h3>\n<p>There are many ways to add options to your themes. Let&#8217;s look at the default way that is contained in the <a href=\"http:\/\/codex.wordpress.org\/Creating_Options_Pages\" target=\"_blank\">WordPress Codex<\/a>.<\/p>\n<p>We&#8217;ll\u00a0start off by creating a page in the admin that will hold the form:<\/p>\n<div class=\"gist\" data-gist=\"9cce6fbf118806100585b5ac9a7f6c3f\" data-gist-file=\"settings-page.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/9cce6fbf118806100585b5ac9a7f6c3f.js?file=settings-page.php\">Loading gist 9cce6fbf118806100585b5ac9a7f6c3f<\/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 <code>tweetlink_settings_menu()<\/code> function is hooked to <code>admin_menu<\/code>.\u00a0According to the Codex, this is how menu entries must be created. The bulk of the work is done by the <code>add_menu_page()<\/code> function, which takes a bunch of arguments to create a top level page. The arguments in order are:<\/p>\n<ul>\n<li>Page title \u2013 used in the title tag<\/li>\n<li>Menu title \u2013 used in the left-hand menu<\/li>\n<li>Capability \u2013 sets the minimum capability for visibility<\/li>\n<li>Menu slug \u2013 slug used in the URL<\/li>\n<li>Function \u2013 the function that controls the output<\/li>\n<li>Icon \u2013 An image URL or a dashicons string<\/li>\n<li>Position \u2013 Item position within the menu<\/li>\n<\/ul>\n<p>Here&#8217;s what our options page looks like so far on the front-end:<\/p>\n<figure id=\"attachment_150025\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-150025\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/12\/options-page.png\" alt=\"Our new options page\" width=\"735\" height=\"559\" \/><figcaption class=\"wp-caption-text\">Our new options page<\/figcaption><\/figure>\n<p>While this may look cool and all, it&#8217;s overkill for our small plugin and just clutters the interface. Always consider placing your options pages <em>inside<\/em> an existing menu. This page would be best placed within the <strong>Settings<\/strong> section using the <code><a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/add_options_page\" target=\"_blank\">add_options_page()<\/a><\/code> function.<\/p>\n<p>The next step is to let WordPress know about our tweet settings. This consists of using the <code>register_settings()<\/code> function inside a function hooked to <code>admin_init()<\/code>. Here&#8217;s what the code for this looks like:<\/p>\n<div class=\"gist\" data-gist=\"1734f9c54b043b242acd5c9d5cb69b5b\" data-gist-file=\"register-settings.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/1734f9c54b043b242acd5c9d5cb69b5b.js?file=register-settings.php\">Loading gist 1734f9c54b043b242acd5c9d5cb69b5b<\/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>All done. The final step is to add a form that uses our options. Use the following code as a template to create your own settings. Don&#8217;t forget to use the <code>settings_fields()<\/code> and <code>do_settings_sections()<\/code> functions to ensure WordPress saves your data for you.<\/p>\n<div class=\"gist\" data-gist=\"cde697202a17d6348cc4a356a78b78b9\" data-gist-file=\"settings-content.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/cde697202a17d6348cc4a356a78b78b9.js?file=settings-content.php\">Loading gist cde697202a17d6348cc4a356a78b78b9<\/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 the end of the process you should see a new settings field which you can fill out and save. You can then use <code>get_option( 'twitter_account' )<\/code> to retrieve the value anywhere within your plugin.<\/p>\n<figure id=\"attachment_150026\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-150026\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2015\/12\/twitter-name.png\" alt=\"Twitter account setting\" width=\"735\" height=\"559\" \/><figcaption class=\"wp-caption-text\">Twitter account setting<\/figcaption><\/figure>\n<p>We can then modify our tweet link to add &#8220;via @username&#8221; if the user has filled in their Twitter account name in the options.<\/p>\n<p>Here&#8217;s how I modified the <code>tweet_link()<\/code> function to accommodate:<\/p>\n<div class=\"gist\" data-gist=\"8998256cf834e1501314b154ab0a2b00\" data-gist-file=\"tweet-via.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/8998256cf834e1501314b154ab0a2b00.js?file=tweet-via.php\">Loading gist 8998256cf834e1501314b154ab0a2b00<\/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>Further Reading and Study<\/h3>\n<p>That concludes our series on WordPress development for beginners. In this article, we learned how to create a basic plugin and hopefully you feel psyched about making your own!<\/p>\n<p>As clich\u00e9 as it sounds, this is just the start of your journey as a WordPress developer. If you&#8217;ve followed along the series since it started five weeks ago, you now having a greater understanding of:<\/p>\n<ul>\n<li>How WordPress core, themes\u00a0and plugins work,<\/li>\n<li>A basic grasp of PHP, the foundational language of WordPress,<\/li>\n<li>How to put together your own basic theme,<\/li>\n<li>How to add features like widgets and menus to themes, and<\/li>\n<li>How to start building your own plugins<\/li>\n<\/ul>\n<p>As I mentioned back in part one of this series,\u00a0I can\u2019t stress enough how important it is not to be discouraged. Everyone has to start somewhere and no one is perfect. You will make mistakes along the way, struggled with understanding concepts, and get frustrated when code doesn&#8217;t work like\u00a0it ought to. Just remember, determination separated the good coders from the bad.<\/p>\n<p>While this is the last post in this series, it doesn&#8217;t mean you should stop learning. I would encourage you to review the tutorials in this series, as well as the accompanying further reading that comes with each post, and\u00a0continue experimenting with PHP and building on the theme and plugin you started building. It&#8217;s only through experimentation and persistence that developing for WordPress will get easier and you will graduate from tinkerer to developer.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Interested in creating your own plugin for WordPress? Coding your own plugin if you haven\u2019t done it before may feel like you\u2019re venturing into no man\u2019s land, especially if you\u2019re not super confident about your PHP skills. In this tutorial, we&#8217;ll show you how to get started building a plugin.<\/p>\n","protected":false},"author":344049,"featured_media":151843,"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":[],"tutorials_categories":[],"class_list":["post-150020","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","category-tutorials"],"_links":{"self":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/150020","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=150020"}],"version-history":[{"count":17,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/150020\/revisions"}],"predecessor-version":[{"id":209708,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/150020\/revisions\/209708"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media\/151843"}],"wp:attachment":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media?parent=150020"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/categories?post=150020"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tags?post=150020"},{"taxonomy":"tutorials_categories","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tutorials_categories?post=150020"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}