{"id":134024,"date":"2014-11-19T08:00:13","date_gmt":"2014-11-19T13:00:13","guid":{"rendered":"http:\/\/premium.wpmudev.org\/blog\/?p=134024"},"modified":"2015-05-28T16:35:06","modified_gmt":"2015-05-28T20:35:06","slug":"common-wordpress-code-issues","status":"publish","type":"post","link":"https:\/\/wpmudev.com\/blog\/common-wordpress-code-issues\/","title":{"rendered":"Nine Common WordPress Code Issues to Avoid"},"content":{"rendered":"<p>There are\u00a0many\u00a0articles out there about fixing WordPress code errors and many more on mistakes to avoid as WordPress users.<\/p>\n<p>In today&#8217;s article, I thought it would be\u00a0helpful\u00a0to take a look at some coding issues which work, but would be considered inefficient, bad code or bad practice.<\/p>\n<p>I&#8217;ll focus on some of the most common problems I&#8217;ve seen around and some errors which I&#8217;m ashamed to say I&#8217;ve committed in the past myself.<\/p>\n<figure id=\"attachment_134034\" class=\"wp-caption aligncenter\" data-caption=\"true\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-134034\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2014\/11\/cleaners.jpg\" alt=\"A cleaner sign\" width=\"800\" height=\"220\" \/><figcaption class=\"wp-caption-text\">Let&#8217;s take our mistakes to the cleaners!<\/figcaption><\/figure>\n<h2>1. Not Enqueueing Google Fonts<\/h2>\n<p>Google fonts are added to a theme or plugin either by hardcoding them, or by allowing users to choose them. If you allow users to choose the fonts, the code behind it can get a bit complex and you may forget that adding a link in the header is not the way forward. Enqueueing them is just as easy as any other stylesheet:<\/p>\n<div class=\"gist\" data-gist=\"8ebd75d7f59f3cca2cc8f5fd40d18fcf\" data-gist-file=\"enqueue-google-fonts.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/8ebd75d7f59f3cca2cc8f5fd40d18fcf.js?file=enqueue-google-fonts.php\">Loading gist 8ebd75d7f59f3cca2cc8f5fd40d18fcf<\/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 the fonts should only be included on pages they are actually used on. See the next section for more information.<\/p>\n<h2>2. Enqueueing Resources Where They Are Not Needed<\/h2>\n<p>Another common practice is to use the enqueues like the example above, but without regard to when they are actually needed.<\/p>\n<p>On the front-end you will probably want to use your fonts on all pages, but on the admin side you may\u00a0only be using them\u00a0on your plugin&#8217;s setting page.<\/p>\n<p>Let&#8217;s take a look at some ways to target enqueued assets better:<\/p>\n<h3>Front-End Targeting<\/h3>\n<p>On the user-facing side of your website,\u00a0<a href=\"http:\/\/codex.wordpress.org\/Template_Tags\" target=\"_blank\">template tags<\/a> are your friend. The Twenty Fourteen default WordPress theme gives us a great example when enqueueing the comment reply script, which gives us the inline comment form:<\/p>\n<div class=\"gist\" data-gist=\"76deb54833963523419f89038e18ac88\" data-gist-file=\"twentyfourteen-comment.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/76deb54833963523419f89038e18ac88.js?file=twentyfourteen-comment.php\">Loading gist 76deb54833963523419f89038e18ac88<\/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 script is loaded only when three conditions are met at once: We must be on a single post, comments must be open, and the <code>thread_comments<\/code> must not be empty. This makes sure that the script is only used when it is truly needed.<\/p>\n<p>Another example I like to mention as often as possible is how you can enqueue scripts and styles for shortcodes. If you have assets which are only needed when the shortcode is actually displayed you can register the assets as usual, but only enqueue them in the shortcode. Here&#8217;s a quick example:<\/p>\n<div class=\"gist\" data-gist=\"49db9d32d42be1a91f725b38af5770b7\" data-gist-file=\"shortcode.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/49db9d32d42be1a91f725b38af5770b7.js?file=shortcode.php\">Loading gist 49db9d32d42be1a91f725b38af5770b7<\/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>Admin Targeting<\/h3>\n<p>Admin assets can be targeted in two ways. Functions hooked into <code>admin_enqueue_script<\/code> receive the file name of the current screen you are viewing.<\/p>\n<div class=\"gist\" data-gist=\"ae6c982a7bf228aa58e3929c799e350f\" data-gist-file=\"admin-targeting-hook.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/ae6c982a7bf228aa58e3929c799e350f.js?file=admin-targeting-hook.php\">Loading gist ae6c982a7bf228aa58e3929c799e350f<\/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>Hook is an extremely confusing name for this parameter, but I have left it in since the WordPress Codex uses this convention.<\/p>\n<p>This is a good way to go about things if you want to target a specific page, but what if you want to target the edit page for a single page (and not a post)? Both instances would be <code>edit.php<\/code> with our example above. In these cases you can use the <code>get_current_screen()<\/code> function.<\/p>\n<p>This gives you a <em>lot<\/em> more info about where you are so you can target pages more effectively. To target only edit pages for the page post type, you could use the following:<\/p>\n<div class=\"gist\" data-gist=\"8dc4b4359fcdcd056779be7fac2f5c05\" data-gist-file=\"get_screen.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/8dc4b4359fcdcd056779be7fac2f5c05.js?file=get_screen.php\">Loading gist 8dc4b4359fcdcd056779be7fac2f5c05<\/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<h2>3. Using The init Hooks For Everything<\/h2>\n<p><code>init<\/code> and <code>admin_init<\/code> is the first hook available after WordPress has loaded but headers haven&#8217;t been sent. As such, they are the go-to solution for all our pre-header needs. From legitimate uses of adding post types and text domains, to unnecessary upgrade routines and functionality specific things like enqueuing and adding menus, developers use them for everything.<\/p>\n<p>One great way to determine what hook you should use is to look at the codex. If the codex creates admin menus by hooking into <code>admin_init<\/code> (it doesn&#8217;t), then go for it. Since it&#8217;s apparent that admin menus use a dedicated <code>admin_menu<\/code>, that is what should be used.<\/p>\n<p>Often your features will work no matter which pre-header hook you choose. This doesn&#8217;t mean you are writing good code. If a developer wants to modify your code or you come back a year later you will have no idea why your <code>remove_action()<\/code> call isn&#8217;t working.<\/p>\n<h2>4. Too Many Options<\/h2>\n<p>If you are creating a plugin and you end up adding a great number of entries into the options table, you are doing something wrong. The solution here is to save all your options as an array. Remember, you don&#8217;t have to worry about saving your data as a string, WordPress takes care of all that behind the scenes.<\/p>\n<div class=\"gist\" data-gist=\"ec0511bf9fa89756c96154a16921b27e\" data-gist-file=\"plugin-options.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/ec0511bf9fa89756c96154a16921b27e.js?file=plugin-options.php\">Loading gist ec0511bf9fa89756c96154a16921b27e<\/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 time you should use multiple options is if you have sets of options which really aren&#8217;t needed all the time. If you only need some options on an admin options panel, you could create a separate options field for that and specifying that it should not be auto-loaded.<\/p>\n<div class=\"gist\" data-gist=\"70dfebd7b6bf218ee717502913e12b61\" data-gist-file=\"no-autoload.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/70dfebd7b6bf218ee717502913e12b61.js?file=no-autoload.php\">Loading gist 70dfebd7b6bf218ee717502913e12b61<\/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<h2>5. Reinventing The Wheel<\/h2>\n<p>If something seems like there should be a function for it, more often than not, there is. I&#8217;ve seen people shy away from using <code>WP_Query<\/code> because it pulls so much data \u2013 they just need IDs. So they end up writing something like this:<\/p>\n<div class=\"gist\" data-gist=\"769c77010b02229bda6cf35eaed4d4e1\" data-gist-file=\"id-query.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/769c77010b02229bda6cf35eaed4d4e1.js?file=id-query.php\">Loading gist 769c77010b02229bda6cf35eaed4d4e1<\/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 has the drawback of being completely un-modifiable by hooks as well as doing something WordPress can do on its own:<\/p>\n<div class=\"gist\" data-gist=\"2dfdedb623766c2ca6eb4870bc0dc6df\" data-gist-file=\"id-wpquery.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/2dfdedb623766c2ca6eb4870bc0dc6df.js?file=id-wpquery.php\">Loading gist 2dfdedb623766c2ca6eb4870bc0dc6df<\/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 can be applied to many, many use cases. From pagination to uploading files and obfuscating email address, WordPress has functions for tons of things.<\/p>\n<p>Part of the reason people try to reinvent the wheel is not knowing a function is there. This is fine, after a few Google searches these problems are solved. The other reason is optimization. The urge to &#8220;return only IDs instead of post data&#8221; drives people to try and write more efficient code.<\/p>\n<p>What people forget is that in 99 percent of cases convention should win over configuration. WordPress is by no means perfect, but it is well-optimized. The speed gain from most of these ventures is negligible compared to the loss of code clarity and standardization.<\/p>\n<h2>6. Database Clutter<\/h2>\n<p>This has to do with making sure that your plugin cleans up after itself. If your plugin is deleted it should leave no trace of its existence in the file system or in the database. Make sure to remove all options and other data \u00a0you&#8217;ve created.<\/p>\n<p>There are two ways to go: The uninstall hook or the inclusion of uninstall.php. Since uninstall.php is recommended, I will not go into detail about the hook itself. To read more about this, take a look at <a href=\"http:\/\/wptavern.com\/plugin-developers-use-uninstall-php-please\" target=\"_blank\">Plugin Developers \u2013 Use Uninstall.php Please<\/a>\u00a0at WP Tavern.<\/p>\n<div class=\"gist\" data-gist=\"f4df814d6ce01ec1fe1c20f8ec19bdbc\" data-gist-file=\"uninstall.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/f4df814d6ce01ec1fe1c20f8ec19bdbc.js?file=uninstall.php\">Loading gist f4df814d6ce01ec1fe1c20f8ec19bdbc<\/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<h2>7. Not Using Child Themes<\/h2>\n<p>This is one of my pet peeves as it has caused me a lot of headaches with users before. Even if you are changing a single line of CSS or you are just increasing the excerpt size of a downloaded theme, <strong>use a child theme<\/strong>.<\/p>\n<p>Child themes provide the only way of being able to update a theme after you&#8217;ve modified it (without loosing your changes). Child themes\u00a0will always use the files of their parent theme, unless that file is specified inside the child theme.<\/p>\n<p>One notable exception is the functions.php file, which is loaded <em>before<\/em> the parent&#8217;s functions file to ensure it can overwrite it.<\/p>\n<p>Child themes are so easy to create. If you want to modify Twenty Fourteen, just create a directory in your themes folder, name it anything you want and add a stylesheet with the following content:<\/p>\n<div class=\"gist\" data-gist=\"338e48b1b28ab1538c2dc63090fafbd3\" data-gist-file=\"child-theme.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/338e48b1b28ab1538c2dc63090fafbd3.js?file=child-theme.php\">Loading gist 338e48b1b28ab1538c2dc63090fafbd3<\/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>Create a <code>functions.php<\/code> and use enqueuing to pull the stylesheet of the parent:<\/p>\n<div class=\"gist\" data-gist=\"3678ad971161aab33b2d43fba8c7bef4\" data-gist-file=\"child-theme-enqueue.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/3678ad971161aab33b2d43fba8c7bef4.js?file=child-theme-enqueue.php\">Loading gist 3678ad971161aab33b2d43fba8c7bef4<\/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<h2>8. Not Supporting Child Themes<\/h2>\n<p>On the flip\u00a0side of the coin are themes which have poor child theme support. There are roughly two things you need to do here: Make sure to use <code>get_stylesheet_directory_url()<\/code> instead of <code>get_template_directory_url()<\/code> where appropriate, and wrap overwritable functions in &#8220;if&#8221; statements.<\/p>\n<div class=\"gist\" data-gist=\"6b0482831738f0f02c1ba2f1290e69ff\" data-gist-file=\"child-theme-support.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/6b0482831738f0f02c1ba2f1290e69ff.js?file=child-theme-support.php\">Loading gist 6b0482831738f0f02c1ba2f1290e69ff<\/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 above 2-in-1 example shows how you can make sure child themes can re-define your functions and how the usage of <code>get_stylesheet_directory_url()<\/code> is helpful. Otherwise WordPress would always look for the image in the parent directory.<\/p>\n<h2>9. Incorrect\/Missing Language Support<\/h2>\n<p>In this day and age of our interconnected society, there&#8217;s just not reason not to make your work multilingual. It&#8217;s so easy to do, all you need is to use the language functions and make sure WordPress uses the language files if they exist.<\/p>\n<div class=\"gist\" data-gist=\"56d4eec61184f8a2e342f3fe1928a3f5\" data-gist-file=\"languages.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/56d4eec61184f8a2e342f3fe1928a3f5.js?file=languages.php\">Loading gist 56d4eec61184f8a2e342f3fe1928a3f5<\/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>To make a string translatable simply wrap it in the <code>__()<\/code> function or the <code>_e()<\/code> function if you&#8217;re echoing it, and make sure to add your text domain:<\/p>\n<div class=\"gist\" data-gist=\"35dba85400239bf09b0bff1ac059fd98\" data-gist-file=\"translatable.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/35dba85400239bf09b0bff1ac059fd98.js?file=translatable.php\">Loading gist 35dba85400239bf09b0bff1ac059fd98<\/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>For more information on how translation works and how you can generate the language files, take a look at the <a href=\"http:\/\/codex.wordpress.org\/I18n_for_WordPress_Developers\" target=\"_blank\">l18n for WordPress Developers<\/a> article in the Codex.<\/p>\n<h2>The List Goes On?<\/h2>\n<p>There are a lot of little tidbits\u00a0WordPress users\u00a0\u2013 including myself \u2013 do wrong. If you have any pet peeves of your own, or you know of something major I&#8217;ve left out please do let us know in the comments.<\/p>\n<p><em>Image Credit: Pete Zarria from <a href=\"https:\/\/flic.kr\/p\/8JR3zX\" target=\"_blank\">Flickr<\/a>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are\u00a0many\u00a0articles out there about fixing WordPress code errors and many more on mistakes to avoid as WordPress users. In today&#8217;s article, I thought it would be\u00a0helpful\u00a0to take a look at some coding issues which work, but would be considered inefficient, bad code or bad practice. I&#8217;ll focus on some of the most common problems [&hellip;]<\/p>\n","protected":false},"author":344049,"featured_media":207995,"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":[263],"tags":[],"tutorials_categories":[],"class_list":["post-134024","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials"],"_links":{"self":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/134024","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=134024"}],"version-history":[{"count":5,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/134024\/revisions"}],"predecessor-version":[{"id":141700,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/134024\/revisions\/141700"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media\/207995"}],"wp:attachment":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media?parent=134024"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/categories?post=134024"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tags?post=134024"},{"taxonomy":"tutorials_categories","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tutorials_categories?post=134024"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}