<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: GP Web Dev</title>
    <description>The latest articles on DEV Community by GP Web Dev (@gp-webdev).</description>
    <link>https://dev.to/gp-webdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2806667%2Fa5bd6e08-bb05-4953-a057-ed9187afd38e.jpg</url>
      <title>DEV Community: GP Web Dev</title>
      <link>https://dev.to/gp-webdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gp-webdev"/>
    <language>en</language>
    <item>
      <title>WordPress and Components</title>
      <dc:creator>GP Web Dev</dc:creator>
      <pubDate>Thu, 27 Feb 2025 23:32:27 +0000</pubDate>
      <link>https://dev.to/gp-webdev/wordpress-and-components-1e4d</link>
      <guid>https://dev.to/gp-webdev/wordpress-and-components-1e4d</guid>
      <description>&lt;p&gt;Even though WordPress has been around for 22+ years (released on May 27, 2003), it is by no means an aged CMS framework.&lt;/p&gt;

&lt;p&gt;Two recent improvements in its core showed us that the community behind WordPress is looking to modernize the most popular CMS. Those are the inclusion of JavaScript-based &lt;a href="https://make.wordpress.org/core/components/editor/" rel="noopener noreferrer"&gt;Gutenberg editor&lt;/a&gt; as part of the core and the upgrade of &lt;a href="https://wordpress.org/about/requirements/" rel="noopener noreferrer"&gt;minimum PHP version&lt;/a&gt; to 7.4 or greater.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Editor
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://wordpress.org/gutenberg/" rel="noopener noreferrer"&gt;Gutenberg&lt;/a&gt; as part of the core has added modern capabilities for building sites on the frontend. Blocks, a high-level &lt;strong&gt;component&lt;/strong&gt; resembling React’s, are the basic unit to build a webpage’s frontend nowadays. In my opinion, shortcodes, custom fields and metaboxes will soon be a thing of the past, while Gutenberg will probably take over as a &lt;a href="https://developer.wordpress.org/block-editor/how-to-guides/platform/" rel="noopener noreferrer"&gt;full development platform&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updated PHP min version
&lt;/h3&gt;

&lt;p&gt;By raising the required minimum version of PHP, the WordPress backend has access to the whole collection of PHP’s Object-Oriented Programming features (such as &lt;a href="https://www.smashingmagazine.com/2019/02/wordpress-modern-php/" rel="noopener noreferrer"&gt;classes and objects, interfaces, traits and namespaces&lt;/a&gt;). All these modern PHP features make up of a &lt;strong&gt;component&lt;/strong&gt; coding approach. No more sub-optimal code because of a backwards compatible PHP version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;p&gt;A component is not always just an implementation, like in React, but more of a programming approach. A coding concept that applies to frontend (CSS like Bootsrap, Bulma or JS like React, Vue) as well as to the backend. The ability to package a specific functionality, decoupling it from the main the application, allows it to be tested and bug-fixed very easily, thus making the application more maintainable in the long term. Improving our productivity by not having to reinvent the wheel each single time is something well known already, so I will not get into more details about packaging, modularization and &lt;a href="https://www.smashingmagazine.com/2019/01/introducing-component-based-api/#building-a-site-through-components" rel="noopener noreferrer"&gt;componetizing a website&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Composer &amp;amp; Packagist
&lt;/h3&gt;

&lt;p&gt;Composer and Packagist have become key tools for establishing the foundations of PHP-based applications. &lt;a href="https://packagist.org/" rel="noopener noreferrer"&gt;Packagist&lt;/a&gt; is essentially a directory containing PHP code out of which &lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt;, a PHP-dependency manager, retrieves packages. Their ease of use and exceptional features simplify the process of importing and managing own and third-party components into our PHP projects.&lt;/p&gt;

&lt;p&gt;Composer allows to declare the libraries the project depends on and it will manage (install/update) them recursively. Similar to NPM, &lt;code&gt;package.json&lt;/code&gt; file and &lt;code&gt;node_modules&lt;/code&gt; directory, Composer only needs a &lt;code&gt;composer.json&lt;/code&gt; file and the &lt;code&gt;vendor/&lt;/code&gt; directory to be ignored in our git to have the project dependencies under version control. This keeps our project’s code thoroughly decoupled from external libraries.&lt;/p&gt;

&lt;p&gt;Composer offers plenty of additional features, which are properly described in the &lt;a href="https://getcomposer.org/doc/00-intro.md" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, and even in its most basic use, offers developers unlimited power for managing the project’s dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter WPackagist
&lt;/h3&gt;

&lt;p&gt;Similar to Packagist, &lt;a href="https://wpackagist.org/" rel="noopener noreferrer"&gt;WPackagist&lt;/a&gt; is a PHP package repository. It contains all the themes and plugins hosted on the WordPress &lt;a href="https://wordpress.org/plugins/" rel="noopener noreferrer"&gt;plugin&lt;/a&gt; and &lt;a href="https://wordpress.org/themes/" rel="noopener noreferrer"&gt;theme&lt;/a&gt; directories, making them available to be managed through Composer.&lt;/p&gt;

&lt;p&gt;Packages available in WPackagist have been given the &lt;a href="https://getcomposer.org/doc/04-schema.md#type" rel="noopener noreferrer"&gt;type&lt;/a&gt; “wordpress-plugin” or “wordpress-theme”. As a consequence, after running &lt;code&gt;composer update&lt;/code&gt;, instead of installing the corresponding themes and plugins under the default folder &lt;code&gt;vendor/&lt;/code&gt;, these will be installed where WordPress expects them: under folders &lt;code&gt;wp-content/themes/&lt;/code&gt; and &lt;code&gt;wp-content/plugins/&lt;/code&gt; respectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;Composer makes it a breeze to manage a PHP project’s dependencies. However, WordPress’ core hasn’t adopted it as its dependency management tool of choice yet, so it is outperformed by newer frameworks like Laravel that incorporate Composer (&lt;a href="https://en.wikipedia.org/wiki/Laravel#History" rel="noopener noreferrer"&gt;since 2013&lt;/a&gt;) as part of their architecture.&lt;/p&gt;

&lt;p&gt;How deep we can integrate WordPress and Composer together depends on the freedom we have as developers on the project. If the developer can have absolute control of how the software will be updated, e.g. by managing the site for the client, or providing training on how to do it, then we can &lt;a href="https://composer.rarst.net/" rel="noopener noreferrer"&gt;incorporate Composer in WordPress&lt;/a&gt; with no problems.&lt;/p&gt;

&lt;p&gt;However, WordPress focuses primarily on the needs of the end users first, and only then on the needs of the developers. For example, a developer can create and launch the website using Composer, and then hand the site over to the end user who might use the standard procedures for installing themes and plugins, bypassing Composer. Since we can’t ask end users to execute a command such as &lt;code&gt;composer install&lt;/code&gt; for this, we need to release plugins with all of their dependencies bundled in. That defeats the whole components approach and Composer itself.&lt;/p&gt;

&lt;p&gt;In our own websites though, where we have full control on the deployment of updates, Composer can be used for managing the site completely.&lt;/p&gt;

&lt;p&gt;As opposed to traditional WordPress setups, Composer treats WP core as a site’s dependency and not as the site itself, that’s why it installs it in a sub-directory. To make it easier to completely manage WordPress with Composer, several projects have taken the stance of installing WordPress in a subfolder. &lt;a href="https://roots.io/" rel="noopener noreferrer"&gt;Roots&lt;/a&gt; provides a WordPress boilerplate called &lt;a href="https://roots.io/bedrock/" rel="noopener noreferrer"&gt;Bedrock&lt;/a&gt;, that I can personally vouch for since we’ve used it on a large multisite WP network for the past 3 years.&lt;/p&gt;

&lt;h3&gt;
  
  
  WordPress through Bedrock or manually
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://roots.io/bedrock/" rel="noopener noreferrer"&gt;Bedrock&lt;/a&gt; is a WordPress boilerplate with an improved folder structure, which looks like this:&lt;/p&gt;

&lt;p&gt;├── composer.json&lt;br&gt;&lt;br&gt;
├── config&lt;br&gt;&lt;br&gt;
│ ├── application.php&lt;br&gt;&lt;br&gt;
│ └── environments&lt;br&gt;&lt;br&gt;
│ ├── development.php&lt;br&gt;&lt;br&gt;
│ ├── staging.php&lt;br&gt;&lt;br&gt;
│ └── production.php&lt;br&gt;&lt;br&gt;
├── vendor&lt;br&gt;&lt;br&gt;
└── web&lt;br&gt;&lt;br&gt;
├── app&lt;br&gt;&lt;br&gt;
│ ├── mu-plugins&lt;br&gt;&lt;br&gt;
│ ├── plugins&lt;br&gt;&lt;br&gt;
│ ├── themes&lt;br&gt;&lt;br&gt;
│ └── uploads&lt;br&gt;&lt;br&gt;
├── wp-config.php&lt;br&gt;&lt;br&gt;
├── index.php&lt;br&gt;&lt;br&gt;
└── wp&lt;/p&gt;

&lt;p&gt;There are many improvements introduced here that are out of the scope of this page. The people behind Roots chose this folder structure in order to make WordPress embrace the &lt;a href="http://12factor.net/" rel="noopener noreferrer"&gt;Twelve Factor App&lt;/a&gt;, and they elaborate how this is accomplished through &lt;a href="https://roots.io/twelve-factor-wordpress/" rel="noopener noreferrer"&gt;a series of blog posts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Managing WP with Composer can also be done manually by setting our &lt;em&gt;composer.json&lt;/em&gt; file, following &lt;a href="https://composer.rarst.net/recipe/site-stack/" rel="noopener noreferrer"&gt;this awesome recipe&lt;/a&gt; based on core contributor John P. Bloch’s mirror &lt;a href="https://github.com/johnpbloch/wordpress-core" rel="noopener noreferrer"&gt;of WordPress’ core&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Either way, and with the freedom to shape the project’s folder structure, we can achieve our requirement of completely managing a WordPress site, including the installation of the core, themes, and plugins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Composer, first released in 2012, is not what we would call “new” software, however, it has not been incorporated to WordPress’ core due to a few incompatibilities between WordPress’ architecture and Composer’s requirements. And of course, due to the fact that WordPress allows end users to install/update dependencies (plugins), even edit code files directly in &lt;code&gt;wp-admin&lt;/code&gt;. That freedom is what made WP so popular but that freedom comes with a cost.&lt;/p&gt;

&lt;p&gt;With the launch of Gutenberg and the bumping up of PHP’s minimum required version, WordPress has entered an era of modernization which provides a great opportunity to rethink how we build WordPress sites to make the most out of newer tools and technologies. Composer, Packagist, and WPackagist are such tools which can help us produce better WordPress code, with an emphasis on reusable components to produce modular applications which are easy to test and bugfix.&lt;/p&gt;

&lt;p&gt;But that means taking back some of our clients freedom.&lt;/p&gt;




</description>
      <category>wordpress</category>
      <category>composer</category>
      <category>webcomponents</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Introduction to WordPress REST API</title>
      <dc:creator>GP Web Dev</dc:creator>
      <pubDate>Thu, 27 Feb 2025 23:30:40 +0000</pubDate>
      <link>https://dev.to/gp-webdev/introduction-to-wordpress-rest-api-32pn</link>
      <guid>https://dev.to/gp-webdev/introduction-to-wordpress-rest-api-32pn</guid>
      <description>&lt;p&gt;The initial goal of &lt;a href="https://developer.wordpress.org/rest-api/" rel="noopener noreferrer"&gt;the REST API in WordPress&lt;/a&gt; is to provide a way for others to interact with WordPress sites by sending and receiving data. The REST API in WordPress, if setting up the endpoints correctly, should be agnostic about what system is pinging the API. As a result, we can use WordPress as an application framework and build the client in whatever programming language we desire.&lt;/p&gt;

&lt;p&gt;One main use of the WordPress REST API is the new block editor (Gutenberg). It’s useful to query and store data when creating custom blocks. As mentioned in the &lt;a href="https://developer.wordpress.org/rest-api/" rel="noopener noreferrer"&gt;official documentation of WordPress&lt;/a&gt;, the REST API is language agnostic:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any programming language which can make HTTP requests and interpret JSON can use the REST API to interact with WordPress, from PHP, Node.js, Go, and Java, to Swift, Kotlin, and beyond.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simple words we can use any programming language to send data to an endpoint and expect a JSON response in which we can parse on the client-side. In the context of Ajax, we’re sending a payload to the REST API, and then parsing this data in JavaScript and perhaps displaying an output to the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  WP-AJAX vs WP REST API
&lt;/h2&gt;

&lt;p&gt;Since the introduction of the &lt;a href="http://v2.wp-api.org/" rel="noopener noreferrer"&gt;WordPress REST API&lt;/a&gt;, many plugin developers have started converting their plugins to use the REST API instead of the older AJAX API (&lt;code&gt;admin-ajax.php&lt;/code&gt;). Aside from the REST API simply being newer technology, it is also faster and more reliable than the older endpoints due to the fact that not as much of WordPress is loaded during a typical REST request.&lt;/p&gt;

&lt;p&gt;The REST API was merged in core more recently than Admin-AJAX. It is perfect to be used in mobile apps and API developments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REST-API PROS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Simplicity. Simple to write, develop and debug&lt;/li&gt;
&lt;li&gt;  Does not need separate functions for logged-in and non-logged-in users&lt;/li&gt;
&lt;li&gt;  The core already has built-in handlers that speed up the development process&lt;/li&gt;
&lt;li&gt;  The response can easily be used in applications or platforms that do not run on WordPress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;REST-API CONS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It does not produce any user-friendly response. The output is always in pure JSON. Some might find this an advantage&lt;/li&gt;
&lt;li&gt;  Working with JavaScript and JSON needs more knowledge than handling a simple text output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Admin AJAX existed in the core from the beginning and it is the way the core itself deals with the requests in the admin area.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Admin-AJAX PROS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It directly outputs the content (JSON, text, HTML, XML etc.) ready to be used anywhere.&lt;/li&gt;
&lt;li&gt;  It has separate functions for logged-in and logged-out users. While you can do this with a conditional in the REST-API, some may find this useful&lt;/li&gt;
&lt;li&gt;  Working with the response is easier, since you have already formatted it in your handler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Admin-AJAX CONS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Since the output is plain HTML (by default ) it shouldn’t be used in APIs and application development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are both useful handlers and if any of them wasn’t secure, it certainly would not have existed in the core for so many years. It’s rather performance, type of request, and development platform that decides which one should be used.&lt;/p&gt;

&lt;p&gt;From a performance standpoint, it’s clear that there is a slight advantage when using REST API. Adding custom API endpoints is incredibly easy, and since it doesn’t have to load as much of WordPress core (including the admin area and the commonly-used &lt;code&gt;admin_init&lt;/code&gt; hook), it will likely be faster than using &lt;code&gt;admin-ajax.php&lt;/code&gt; in most cases.&lt;/p&gt;

&lt;p&gt;In terms of reliability, the REST API still depends on the quality and integrity of our code. A poorly coded plugin could still easily interfere with REST requests. Overall, it’s definitely a good idea to at least consider using the REST API. Adding custom API endpoints is incredibly easy, and it doesn’t take much to switch over existing code either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Endpoints
&lt;/h2&gt;

&lt;p&gt;In the WordPress REST API, routes are a list of available endpoints in the REST API. An endpoint is a final destination for the route. We can visit &lt;a href="https://yoursite.com/wp-json/" rel="noopener noreferrer"&gt;https://yoursite.com/wp-json/&lt;/a&gt; to see the available routes and endpoints we already have in our website.&lt;/p&gt;

&lt;p&gt;Some useful examples could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Posts List &lt;a href="https://yoursite.com/wp-json/wp/v2/posts/" rel="noopener noreferrer"&gt;https://yoursite.com/wp-json/wp/v2/posts/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Pages List &lt;a href="https://yoursite.com/wp-json/wp/v2/pages/" rel="noopener noreferrer"&gt;https://yoursite.com/wp-json/wp/v2/pages/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Taxonomies &lt;a href="https://yoursite.com/wp-json/wp/v2/taxonomies/" rel="noopener noreferrer"&gt;https://yoursite.com/wp-json/wp/v2/taxonomies/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  CPTs &lt;a href="https://yoursite.com/wp-json/wp/v2/cpt%5C_name/cpt%5C_ID/" rel="noopener noreferrer"&gt;https://yoursite.com/wp-json/wp/v2/cpt\_name/cpt\_ID/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://developer.wordpress.org/rest-api/" rel="noopener noreferrer"&gt;REST API Handbook&lt;/a&gt; provides all necessary information on how to utilize it, along with &lt;a href="https://developer.wordpress.org/rest-api/frequently-asked-questions/" rel="noopener noreferrer"&gt;frequently asked questions&lt;/a&gt;, &lt;a href="https://developer.wordpress.org/rest-api/using-the-rest-api/" rel="noopener noreferrer"&gt;usage examples&lt;/a&gt; and &lt;a href="https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/" rel="noopener noreferrer"&gt;how to extend it&lt;/a&gt;.&lt;/p&gt;




</description>
      <category>wordpress</category>
      <category>restapi</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>WP Query Functions – What to use and when</title>
      <dc:creator>GP Web Dev</dc:creator>
      <pubDate>Thu, 27 Feb 2025 23:25:16 +0000</pubDate>
      <link>https://dev.to/gp-webdev/wordpress-query-functions-what-to-use-and-when-4dbc</link>
      <guid>https://dev.to/gp-webdev/wordpress-query-functions-what-to-use-and-when-4dbc</guid>
      <description>&lt;p&gt;Core WordPress functions and classes are generally excellent regarding to performance and security.&lt;/p&gt;

&lt;p&gt;When it comes to retrieving data from the database, the &lt;code&gt;WP_Query&lt;/code&gt; class and its methods provide us with a safe and efficient way to do it, avoiding complex SQL queries. There are some additional wrappers of &lt;a href="https://developer.wordpress.org/reference/classes/wp_query/" rel="noopener noreferrer"&gt;&lt;code&gt;WP_Query&lt;/code&gt;&lt;/a&gt;, like &lt;a href="https://developer.wordpress.org/reference/functions/query_posts/" rel="noopener noreferrer"&gt;&lt;code&gt;query_posts()&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://developer.wordpress.org/reference/functions/get_posts/" rel="noopener noreferrer"&gt;&lt;code&gt;get_posts()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  query_posts
&lt;/h2&gt;

&lt;p&gt;WordPress Codex explicitly says “&lt;em&gt;Its overly-simplistic approach to modifying the main query can be problematic and &lt;strong&gt;should be avoided&lt;/strong&gt; wherever possible&lt;/em&gt;“.&lt;/p&gt;

&lt;p&gt;This query wrapper is inefficient (re-runs SQL queries) and will fail in some circumstances, especially when dealing with posts pagination. It instantiates a new WP_Query object and reassigns that to the &lt;code&gt;global wp_query&lt;/code&gt;, breaking the main query that many plugins, themes and custom scripts rely on. For secondary queries (custom loops) instantiate your own WP_Query.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;new WP_Query&lt;/code&gt; or &lt;code&gt;get_posts()&lt;/code&gt; which are pretty much interchangeable (latter is thin wrapper for former). If you do want to alter the main query, then use the &lt;a href="https://wordpress.stackexchange.com/questions/50761/when-to-use-wp-query-query-posts-and-pre-get-posts" rel="noopener noreferrer"&gt;&lt;code&gt;pre_get_posts&lt;/code&gt;&lt;/a&gt; hook with &lt;code&gt;$query-&amp;gt;is_main_query()&lt;/code&gt; check. &lt;a href="http://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts" rel="noopener noreferrer"&gt;&lt;code&gt;pre_get_posts&lt;/code&gt;&lt;/a&gt; is a filter for altering any query and it is most often used to alter the ‘main query’. This is the &lt;a href="https://core.trac.wordpress.org/ticket/19631" rel="noopener noreferrer"&gt;trac&lt;/a&gt; about the deprecation of &lt;code&gt;query_posts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Therefore:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You should &lt;strong&gt;never&lt;/strong&gt; use &lt;a href="https://developer.wordpress.org/reference/functions/query_posts/" rel="noopener noreferrer"&gt;&lt;code&gt;query_posts()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  get_posts
&lt;/h2&gt;

&lt;p&gt;This is essentially a wrapper for a separate instance of a &lt;code&gt;WP_Query&lt;/code&gt; object. This isn’t a ‘Loop’, it simply returns an array of post objects.&lt;/p&gt;

&lt;p&gt;It accepts the same arguments as WP_Query, doesn’t modify global variables and is safe to use anywhere. It passes &lt;code&gt;'no_found_rows' =&amp;gt; true&lt;/code&gt; by default so it is used for non paginated queries only. It ignores sticky posts, needs just a foreach loop to display the $post property and requires a &lt;code&gt;setup_postdata( $post )&lt;/code&gt; to make the template tags available. &lt;code&gt;WP_Query&lt;/code&gt; uses the loop and template tags are available by default.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use &lt;a href="https://developer.wordpress.org/reference/functions/get_posts/" rel="noopener noreferrer"&gt;&lt;code&gt;get_posts()&lt;/code&gt;&lt;/a&gt; for some quick, non-paginated, data fetch.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  WP_Query
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://codex.wordpress.org/Function_Reference/WP_Query" rel="noopener noreferrer"&gt;&lt;code&gt;WP_Query&lt;/code&gt;&lt;/a&gt; is the class behind both the above functions. The power of &lt;code&gt;WP_Query&lt;/code&gt; derives from the possibility to create and work with your own instance of it. It is more of a general purpose tool, similar to directly writing MySQL, for a detailed custom query script.&lt;/p&gt;

&lt;p&gt;A bit more complex with fewer restrictions, thus making it more powerful while being safe to use anywhere.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use a &lt;code&gt;new WP_Query&lt;/code&gt; for an in-depth, flexible query script.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Reset/Cleanup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Use &lt;code&gt;wp_reset_query()&lt;/code&gt; if you’ve used &lt;code&gt;query_posts()&lt;/code&gt; or altered global &lt;code&gt;$wp_query&lt;/code&gt; directly – hopefully you will never need to.&lt;/li&gt;
&lt;li&gt;  Use &lt;code&gt;wp_reset_postdata()&lt;/code&gt; if you’ve used &lt;code&gt;the_post()&lt;/code&gt; or &lt;code&gt;setup_postdata()&lt;/code&gt; to restore initial state of global $post.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;All queries are eventually wrappers of &lt;code&gt;WP_Query&lt;/code&gt;, and while some are better than other (never use &lt;code&gt;query_posts&lt;/code&gt;), the performance differences of &lt;code&gt;get_posts&lt;/code&gt; vs &lt;code&gt;WP_Query&lt;/code&gt; are negligible. The &lt;code&gt;WP_Query&lt;/code&gt; is faster than &lt;code&gt;get_posts&lt;/code&gt; by a very small margin.&lt;/p&gt;

&lt;p&gt;However parameters provided by the &lt;code&gt;WP_Query&lt;/code&gt; class can specifically optimize SQL queries, reducing execution time and resource consumption. (Ref. &lt;a href="https://kinsta.com/blog/wp-query/" rel="noopener noreferrer"&gt;1&lt;/a&gt; | &lt;a href="https://wordpress.stackexchange.com/a/363394/160985" rel="noopener noreferrer"&gt;2&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When we don’t need pagination, we should set &lt;code&gt;no_found_rows&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;, making the query run dramatically faster.&lt;/li&gt;
&lt;li&gt;  When specific fields are not required, limit the returned fields to IDs: &lt;code&gt;'fields' =&amp;gt; 'ids'&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>wordpress</category>
      <category>performance</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Data Validation and Sanitization in WordPress</title>
      <dc:creator>GP Web Dev</dc:creator>
      <pubDate>Thu, 27 Feb 2025 23:20:43 +0000</pubDate>
      <link>https://dev.to/gp-webdev/data-validation-and-sanitization-in-wordpress-3on9</link>
      <guid>https://dev.to/gp-webdev/data-validation-and-sanitization-in-wordpress-3on9</guid>
      <description>&lt;p&gt;When developing for WordPress, appropriate data validation and sanitization is critical for proper security of our themes and plugins.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the difference?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Validation&lt;/strong&gt; – Check to see that the data we have received is what it should be. Example: check that an e-mail looks like an e-mail address, that a date is in date format and that a number is (or is casted as) an integer/decimal.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Sanitization / Escaping&lt;/strong&gt; – Apply filters to data to make it ‘safe’ in a specific context. Example: to display HTML code in a text area all HTML tags must be replaced by entity equivalents, otherwise browser will render the HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rule No. 1: Do not trust users
&lt;/h2&gt;

&lt;p&gt;Never assume that any data entered by the user is safe. Also never assume that data coming from database is safe – even if you had made it ‘safe’ prior to inserting it there. This applies to frontend forms and WP admin dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule No. 2: Validate Early, Escape Late
&lt;/h2&gt;

&lt;p&gt;Validate on data input early, as soon as you receive it from the user. Escape (or sanitize) on output late, just before you use, display or return data. What form this sanitization takes, depends entirely on the context you are using it in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule No. 3: Do trust WordPress
&lt;/h2&gt;

&lt;p&gt;As opposed to direct SQL queries, when using native WordPress functions data is properly sanitized (for the appropriate context) by WP core. One more reason to always prefer using native functions, wherever possible, instead of custom code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Data Validation
&lt;/h2&gt;

&lt;p&gt;The first concern when receiving data from a user is not safety but rather validity. What ‘valid’ means is up to you and if you’re doing it right, WordPress will take care of safely adding the data to the database. Validity could mean a valid email address, a positive integer, text of a limited length, or one of an array of specified options. WordPress offers &lt;a href="https://codex.wordpress.org/Data_Validation#Other" rel="noopener noreferrer"&gt;a lot of functions&lt;/a&gt; that can help with any validity we require.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Numbers&lt;/strong&gt; – When expecting numeric data, it’s possible to it with &lt;a href="http://php.net/manual/en/function.is-int.php" rel="noopener noreferrer"&gt;&lt;code&gt;is_int&lt;/code&gt;&lt;/a&gt; or &lt;a href="http://php.net/manual/en/function.is-float.php" rel="noopener noreferrer"&gt;&lt;code&gt;is_float&lt;/code&gt;&lt;/a&gt; and it is usually sufficient to simply cast the data as numeric with: &lt;a href="http://php.net/manual/en/function.intval.php" rel="noopener noreferrer"&gt;&lt;code&gt;intval&lt;/code&gt;&lt;/a&gt; or &lt;a href="http://php.net/manual/en/function.floatval.php" rel="noopener noreferrer"&gt;&lt;code&gt;floatval&lt;/code&gt;&lt;/a&gt;. For zero padding, WordPress provides the function &lt;a href="http://codex.wordpress.org/Function_Reference/zeroise" rel="noopener noreferrer"&gt;&lt;code&gt;zeroise()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;E-mails&lt;/strong&gt; – To check the validity of e-mails, WordPress has the &lt;a href="http://codex.wordpress.org/Function_Reference/is_email" rel="noopener noreferrer"&gt;&lt;code&gt;is_email()&lt;/code&gt;&lt;/a&gt; function.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;HTML&lt;/strong&gt; – WordPress provides a family of functions of the form &lt;a href="http://codex.wordpress.org/Function_Reference/wp_kses" rel="noopener noreferrer"&gt;&lt;code&gt;wp_kses_*&lt;/code&gt;&lt;/a&gt; . The &lt;code&gt;wp_kses()&lt;/code&gt; is a very flexible function, allowing you to remove unwanted tags, or just unwanted attributes from tags. Specifying every allowed tag and attribute can be a laborious task so WordPress provides &lt;code&gt;wp_kses&lt;/code&gt; with pre-set allowed tags and protocols:

&lt;ul&gt;
&lt;li&gt;  &lt;a href="http://codex.wordpress.org/Function_Reference/wp_kses_post" rel="noopener noreferrer"&gt;&lt;code&gt;wp_kses_post()&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="http://codex.wordpress.org/Function_Reference/wp_kses_data" rel="noopener noreferrer"&gt;&lt;code&gt;wp_kses_data()&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Filenames&lt;/strong&gt; – &lt;a href="http://codex.wordpress.org/Function_Reference/sanitize_file_name" rel="noopener noreferrer"&gt;&lt;code&gt;sanitize_file_name( $filename )&lt;/code&gt;&lt;/a&gt; sanitizes by removing characters that are illegal in filenames. Replaces spaces with dashes and consecutive dashes with a single dash and removes periods, dashes and underscores from the beginning and end of the filename. &lt;a href="http://codex.wordpress.org/Function_Reference/wp_unique_filename" rel="noopener noreferrer"&gt;&lt;code&gt;wp_unique_filename( $dir, $filename )&lt;/code&gt;&lt;/a&gt; returns a unique (for directory &lt;code&gt;$dir&lt;/code&gt;), sanitized filename (it uses &lt;code&gt;sanitize_file_name&lt;/code&gt;).&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Text Fields&lt;/strong&gt; – WordPress provides &lt;a href="http://queryposts.com/function/sanitize_text_field/" rel="noopener noreferrer"&gt;&lt;code&gt;sanitize_text_field()&lt;/code&gt;&lt;/a&gt; to strip out extra white spaces, tabs and line breaks, as well as stripping out any tags when receiving data from a text field.&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Keys&lt;/strong&gt; – WordPress also provides &lt;a href="http://queryposts.com/function/sanitize_key/" rel="noopener noreferrer"&gt;&lt;code&gt;sanitize_key&lt;/code&gt;&lt;/a&gt; that ensures the returned variable contains only lower-case alpha-numerics, dashes, and underscores.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Further information about Validating Data can &lt;a href="https://developer.wordpress.org/apis/security/data-validation/#validation-functions" rel="noopener noreferrer"&gt;be found here&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Data Sanitization
&lt;/h2&gt;

&lt;p&gt;While validation is about making sure data is valid – data sanitization is about making it safe. While some of the validation functions might be useful in making sure data is safe – in general, it is not sufficient. Even ‘valid’ data might be unsafe in certain contexts. What is safe to use in one context, is not necessarily safe in another. This is why WordPress often provides several functions for the same content, for instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="http://codex.wordpress.org/Function_Reference/the_title" rel="noopener noreferrer"&gt;&lt;code&gt;the_title&lt;/code&gt;&lt;/a&gt; – for using the title in standard HTML (inside header tags, for example)&lt;/li&gt;
&lt;li&gt;  &lt;a href="http://codex.wordpress.org/Function_Reference/the_title_attribute" rel="noopener noreferrer"&gt;&lt;code&gt;the_title_attribute&lt;/code&gt;&lt;/a&gt; – for using the title as an attribute value (usually the title attribute in &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags)&lt;/li&gt;
&lt;li&gt;  &lt;a href="http://codex.wordpress.org/Function_Reference/get_the_title_rss" rel="noopener noreferrer"&gt;&lt;code&gt;the_title_rss&lt;/code&gt;&lt;/a&gt; – for using the title in RSS feeds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes though, we’ll need to perform our own sanitization – often because we have custom input beyond the standard post title, permalink, content etc. that WordPress handles for us.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Escape HTML&lt;/strong&gt; – to avoid &lt;strong&gt;Cross-site scripting&lt;/strong&gt; with injected scripts, WordPress provides the well known &lt;a href="http://codex.wordpress.org/Function_Reference/esc_html" rel="noopener noreferrer"&gt;&lt;code&gt;esc_html&lt;/code&gt;&lt;/a&gt; function. This should always be used when printing variables: &lt;code&gt;&amp;lt;h1&amp;gt; &amp;lt;?php&lt;/code&gt; &lt;code&gt;echo&lt;/code&gt; &lt;code&gt;esc_html(&lt;/code&gt;&lt;code&gt;$title&lt;/code&gt;&lt;code&gt;); ?&amp;gt; &amp;lt;/h1&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Escape Attributes&lt;/strong&gt; – to escape unsafe characters (such as quotes and double-quotes), WordPress provides the function &lt;a href="http://codex.wordpress.org/Function_Reference/esc_attr" rel="noopener noreferrer"&gt;&lt;code&gt;esc_attr&lt;/code&gt;&lt;/a&gt;. Like &lt;code&gt;esc_html&lt;/code&gt; it replaces ‘unsafe’ characters by their entity equivalents. Example: &lt;code&gt;&amp;lt;input type="text" name="myInput" value="&amp;lt;?php echo esc_attr($value);?&amp;gt;"/&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Translated Escapes&lt;/strong&gt; – Both &lt;code&gt;esc_html&lt;/code&gt; and &lt;code&gt;esc_attr&lt;/code&gt; also come with &lt;code&gt;__&lt;/code&gt;, &lt;code&gt;_e&lt;/code&gt;, and &lt;code&gt;_x&lt;/code&gt; variants.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;HTML Class Names&lt;/strong&gt; – WordPress provides &lt;a href="http://queryposts.com/function/sanitize_html_class/" rel="noopener noreferrer"&gt;&lt;code&gt;sanitize_html_class&lt;/code&gt;&lt;/a&gt; – this escapes variables for use in class names, simply by restricting the returned value to alpha-numerics, hyphens and underscores.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Escape URLs&lt;/strong&gt; – When printing variables into the &lt;code&gt;href&lt;/code&gt; attribute you should use:

&lt;ul&gt;
&lt;li&gt;  &lt;a href="http://codex.wordpress.org/Function_Reference/esc_url" rel="noopener noreferrer"&gt;&lt;code&gt;esc_url&lt;/code&gt;&lt;/a&gt; – for escaping URLs that will be printed to the page.&lt;/li&gt;
&lt;li&gt;  &lt;a href="http://codex.wordpress.org/Function_Reference/esc_url_raw" rel="noopener noreferrer"&gt;&lt;code&gt;esc_url_raw&lt;/code&gt;&lt;/a&gt; – for escaping URLs to save to the database or use in URL redirecting.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Escape JS&lt;/strong&gt; – When you want to print PHP variables in JavaScript you should be using &lt;a href="http://codex.wordpress.org/Function_Reference/wp_localize_script" rel="noopener noreferrer"&gt;&lt;code&gt;wp_localize_script()&lt;/code&gt;&lt;/a&gt; – which handles sanitization for you. In the case you do want to do directly then you can use the &lt;a href="http://queryposts.com/function/esc_js/" rel="noopener noreferrer"&gt;&lt;code&gt;esc_js&lt;/code&gt;&lt;/a&gt; function to make it safe: &lt;code&gt;&amp;lt;script&amp;gt; var myVar = '&amp;lt;?php echo esc_js($variable); ?&amp;gt;'; &amp;lt;/script&amp;gt;&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Escape Textarea&lt;/strong&gt; – For this WordPress provides &lt;a href="http://codex.wordpress.org/Function_Reference/esc_textarea" rel="noopener noreferrer"&gt;&lt;code&gt;esc_textarea&lt;/code&gt;&lt;/a&gt;, which is almost identical to &lt;code&gt;esc_html&lt;/code&gt;, but does double encode entities. Essentially it is little more than a wrapper for &lt;a href="http://php.net/manual/en/function.htmlspecialchars.php" rel="noopener noreferrer"&gt;&lt;code&gt;htmlspecialchars&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Antispambot&lt;/strong&gt; – WordPress provides &lt;a href="http://codex.wordpress.org/Function_Reference/antispambot" rel="noopener noreferrer"&gt;&lt;code&gt;antispambot&lt;/code&gt;&lt;/a&gt;, which encodes random parts of the e-mail address into their HTML entities and protects them from e-mail harvesters.&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Query Strings&lt;/strong&gt; – the safest and easiest way is to use &lt;a href="http://codex.wordpress.org/Function_Reference/add_query_arg" rel="noopener noreferrer"&gt;&lt;code&gt;add_query_arg&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://codex.wordpress.org/Function_Reference/remove_query_arg" rel="noopener noreferrer"&gt;&lt;code&gt;remove_query_arg&lt;/code&gt;&lt;/a&gt;. These functions handle all the necessary escaping for for the arguments and their values for use in the URL.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;More info about Sanitizing Data can &lt;a href="https://developer.wordpress.org/apis/security/sanitizing/#sanitization-functions" rel="noopener noreferrer"&gt;be found here&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Database Escaping
&lt;/h2&gt;

&lt;p&gt;When using functions such as &lt;code&gt;get_posts&lt;/code&gt; or classes such as &lt;code&gt;WP_Query&lt;/code&gt; and &lt;code&gt;WP_User_Query&lt;/code&gt;, WordPress takes care of the necessary sanitization in querying the database. However, when retrieving data from a custom table, or otherwise performing a direct SQL query on the database – proper sanitization is then up to you. WordPress, however, provides a helpful class, the &lt;a href="https://developer.wordpress.org/reference/classes/wpdb/" rel="noopener noreferrer"&gt;&lt;code&gt;$wpdb&lt;/code&gt;&lt;/a&gt; class, that helps with escaping SQL queries.&lt;/p&gt;

&lt;p&gt;For a more complete overview of SQL escaping in WordPress, see &lt;a href="https://codex.wordpress.org/Data_Validation#Database" rel="noopener noreferrer"&gt;database Data Validation&lt;/a&gt;.&lt;/p&gt;




</description>
      <category>wordpress</category>
      <category>security</category>
      <category>data</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
