Useful WordPress Functions Every Developer Must Know (With Examples) | CloudyWP Australia
WordPress has thousands of built-in functions. You don’t need to memorize all of them — but there’s a core set of around 70 functions that real WordPress developers use every single day. Master these and you can build almost any custom theme, plugin, or feature without ever leaving the WordPress ecosystem.
This guide is that exact list — organized by category, each with a real working code example you can copy and paste. Bookmark this page; you’ll come back to it constantly.
How to Use This Guide
Each function below includes:
- 📌 What it does in plain English
- ⚙️ Function signature (parameters)
- 💻 A real code example you can drop into a theme or plugin
- 💡 Tips and gotchas where they matter
Jump to a section:
- The Loop & Post Data —
have_posts(),the_title(),the_content()… - Custom Queries —
WP_Query,get_posts(),wp_reset_postdata() - Post Meta / Custom Fields —
get_post_meta(),update_post_meta() - Site & URL Functions —
home_url(),get_template_directory_uri() - Conditional Tags —
is_home(),is_single(),is_user_logged_in() - Template Includes —
get_header(),get_template_part() - Enqueuing Scripts & Styles —
wp_enqueue_script(),wp_enqueue_style() - Hooks: Actions & Filters —
add_action(),add_filter() - Options API —
get_option(),update_option() - User Functions —
wp_get_current_user(),current_user_can() - Security & Escaping —
esc_html(),sanitize_text_field() - Nonces (CSRF Protection) —
wp_nonce_field(),wp_verify_nonce() - Database (
$wpdb) —$wpdb->insert(),$wpdb->get_results() - Menus & Sidebars —
wp_nav_menu(),register_sidebar() - Featured Images & Media —
the_post_thumbnail(),wp_get_attachment_image_src() - Comments —
comments_template(),comment_form() - Pagination —
the_posts_pagination(),paginate_links() - Categories, Tags & Terms —
get_categories(),get_terms() - Custom Post Types & Taxonomies —
register_post_type() - AJAX —
wp_localize_script(),wp_send_json_success()
1. The Loop & Post Data
These are the absolute basics — used in every theme on every page.
have_posts() and the_post()
What it does: Together they form “The Loop” — WordPress’s standard way of iterating over posts.
if (have_posts()) :
while (have_posts()) : the_post();
the_title('<h2>', '</h2>');
the_content();
endwhile;
else :
echo '<p>No posts found.</p>';
endif;
the_title()
What it does: Echoes the current post’s title. Accepts optional before/after HTML.
the_title('<h1 class="post-title">', '</h1>');
// Output: <h1 class="post-title">My Blog Post</h1>
get_the_title()
What it does: Same as the_title() but returns the value instead of echoing it.
$title = get_the_title();
$shortened = substr($title, 0, 50) . '...';
echo $shortened;
the_content()
What it does: Echoes the full post content (with shortcodes processed and embeds rendered).
the_content('Continue reading →');
// The argument is the "more" link text for posts with <!--more--> tags
the_excerpt() and get_the_excerpt()
What it does: Echoes (or returns) the post excerpt — manual excerpt if set, otherwise auto-generated from content.
<p class="card-summary"><?php echo get_the_excerpt(); ?></p>
the_permalink() and get_permalink()
What it does: Echoes/returns the URL to the current post.
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
get_the_ID() and the_ID()
What it does: Returns/echoes the current post ID.
$post_id = get_the_ID();
$views = get_post_meta($post_id, 'view_count', true);
the_author() and get_the_author()
<p>Written by <?php the_author(); ?></p>
the_date() and get_the_date()
What it does: Echoes/returns the post’s publish date with optional PHP date format.
<time><?php echo get_the_date('F j, Y'); ?></time>
// Output: <time>March 15, 2026</time>
the_category()
<p>Filed under: <?php the_category(', '); ?></p>
the_tags()
<?php the_tags('Tags: ', ', ', ''); ?>
// Output: Tags: design, css, frontend
2. Custom Queries
The Loop runs on the “main query” automatically. For custom queries (e.g., “show 3 latest products”), use these.
WP_Query
What it does: The flagship custom-query class. Most powerful and most-used.
$args = [
'post_type' => 'post',
'posts_per_page' => 5,
'category_name' => 'tutorials',
'orderby' => 'date',
'order' => 'DESC',
];
$query = new WP_Query($args);
if ($query->have_posts()) :
while ($query->have_posts()) : $query->the_post();
?>
<article>
<h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<p><?php echo get_the_excerpt(); ?></p>
</article>
<?php
endwhile;
wp_reset_postdata();
endif;
⚠️ Always call wp_reset_postdata() after a custom query — otherwise WordPress thinks the last post in your custom query is the “current post.”
get_posts()
What it does: Simpler than WP_Query. Returns an array of post objects (no loop needed).
$posts = get_posts([
'numberposts' => 3,
'category' => 5,
'orderby' => 'rand',
]);
foreach ($posts as $post) :
setup_postdata($post);
?>
<h3><?php the_title(); ?></h3>
<?php
endforeach;
wp_reset_postdata();
wp_reset_postdata()
What it does: Restores the global $post to the main query’s current post. Critical after every custom query.
query_posts() ⚠️
Don’t use this. It overrides the main query and breaks pagination and other features. Use WP_Query or pre_get_posts instead.
3. Post Meta / Custom Fields
Custom fields let you attach extra data to any post.
get_post_meta()
What it does: Retrieves a custom field value.
// Get single value
$price = get_post_meta(get_the_ID(), 'product_price', true);
echo '$' . esc_html($price);
// Get array of all values for that key
$gallery = get_post_meta(get_the_ID(), 'gallery_images', false);
The 3rd parameter (
true/false) is the most-asked-about.true= return single value.false= return array.
update_post_meta()
What it does: Adds OR updates a custom field. Smart — creates if missing, updates if exists.
update_post_meta(get_the_ID(), 'view_count', 42);
update_post_meta($post_id, 'last_viewed', current_time('mysql'));
add_post_meta()
What it does: Adds a new custom field. Use when you want multiple values for the same key.
add_post_meta($post_id, 'tagged_user', 'alice');
add_post_meta($post_id, 'tagged_user', 'bob');
// Now 'tagged_user' has 2 entries
delete_post_meta()
delete_post_meta($post_id, 'old_field');
4. Site & URL Functions
Never hard-code URLs. Use these functions so your site works when moved.
home_url()
What it does: Returns the site’s home URL.
<a href="<?php echo esc_url(home_url('/')); ?>">Home</a>
<a href="<?php echo esc_url(home_url('/contact')); ?>">Contact</a>
site_url() vs home_url()
| Function | Returns |
|---|---|
home_url() |
The site’s homepage URL (what users see) |
site_url() |
Where WordPress files live (often the same as home_url, but can differ in WordPress-in-subdirectory setups) |
Use home_url() for user-facing links. Use site_url() for admin/internal stuff.
admin_url()
$dashboard = admin_url('index.php');
$new_post = admin_url('post-new.php');
get_template_directory_uri()
What it does: Returns the URL to the active theme’s folder. Use for assets.
<link rel="stylesheet" href="<?php echo get_template_directory_uri(); ?>/css/main.css">
<img src="<?php echo get_template_directory_uri(); ?>/img/logo.png">
get_template_directory()
What it does: Returns the file path (not URL) to the theme folder. Use for PHP includes.
require get_template_directory() . '/inc/custom-functions.php';
get_stylesheet_uri()
What it does: Returns the URL to the active theme’s style.css.
<link rel="stylesheet" href="<?php echo get_stylesheet_uri(); ?>">
bloginfo()
What it does: Echoes various pieces of site info.
<title><?php bloginfo('name'); ?></title>
<meta name="description" content="<?php bloginfo('description'); ?>">
<meta charset="<?php bloginfo('charset'); ?>">
5. Conditional Tags
Check what page is currently being displayed. Essential for functions.php and template files.
if (is_home()) // Blog index page
if (is_front_page()) // Site homepage
if (is_single()) // Single blog post
if (is_page()) // Static page
if (is_page('about')) // Specific page by slug
if (is_category()) // Category archive
if (is_archive()) // Any archive page
if (is_search()) // Search results
if (is_404()) // 404 page
if (is_admin()) // WP admin area
if (is_user_logged_in()) // Logged-in user
if (is_singular('product')) // Single post of post type "product"
Real-world example:
// Show sidebar only on blog posts and pages, not on homepage
if (is_single() || is_page()) {
get_sidebar();
}
6. Template Includes
Reuse template parts across pages.
get_header(), get_footer(), get_sidebar()
<?php get_header(); ?>
<main>...content...</main>
<?php get_sidebar(); ?>
<?php get_footer(); ?>
You can also load named variants:
get_header('shop'); // Loads header-shop.php
get_footer('minimal'); // Loads footer-minimal.php
get_template_part()
What it does: Loads a custom template fragment. The cleanest way to keep code DRY.
// Loads content-card.php
get_template_part('content', 'card');
// Pass data with the 3rd argument (WP 5.5+)
get_template_part('content', 'card', ['featured' => true]);
comments_template()
if (comments_open() || get_comments_number()) {
comments_template();
}
7. Enqueuing Scripts & Styles
Never hard-code <link> or <script> tags. Use these functions for proper caching, dependencies, and plugin compatibility.
wp_enqueue_style()
function my_theme_styles() {
wp_enqueue_style(
'main-style', // Handle (unique name)
get_template_directory_uri() . '/css/main.css', // URL
[], // Dependencies
'1.0.0', // Version (for cache-busting)
'all' // Media: all, screen, print
);
}
add_action('wp_enqueue_scripts', 'my_theme_styles');
wp_enqueue_script()
function my_theme_scripts() {
wp_enqueue_script(
'main-js', // Handle
get_template_directory_uri() . '/js/main.js',
['jquery'], // Dependencies
'1.0.0', // Version
true // Load in footer? (true recommended)
);
}
add_action('wp_enqueue_scripts', 'my_theme_scripts');
wp_localize_script()
What it does: Pass PHP variables to JavaScript. Essential for AJAX.
wp_enqueue_script('main-js', '/js/main.js', ['jquery'], '1.0', true);
wp_localize_script('main-js', 'myAjax', [
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('my_ajax_action'),
'home' => home_url(),
]);
// In JavaScript: myAjax.ajaxurl, myAjax.nonce, myAjax.home
wp_dequeue_style() / wp_dequeue_script()
What it does: Remove styles/scripts added by another plugin or theme.
function remove_woo_styles() {
wp_dequeue_style('woocommerce-general');
}
add_action('wp_enqueue_scripts', 'remove_woo_styles', 100);
8. Hooks: Actions & Filters
The single most important concept in WordPress development.
| Hook type | What it does |
|---|---|
| Action | Runs your code at a specific moment (e.g., “when WordPress loads”, “before sending email”) |
| Filter | Modifies data before WordPress uses it (e.g., change post title before display) |
add_action()
function send_welcome_email($user_id) {
$user = get_userdata($user_id);
wp_mail($user->user_email, 'Welcome!', 'Thanks for joining.');
}
add_action('user_register', 'send_welcome_email');
add_filter()
function add_emoji_to_title($title) {
return '🚀 ' . $title;
}
add_filter('the_title', 'add_emoji_to_title');
do_action() / apply_filters()
What it does: Lets YOUR plugin/theme create its own hooks for others to extend.
// In your plugin
function my_plugin_render_widget() {
echo '<div class="my-widget">';
do_action('my_plugin_before_content');
echo '<p>The widget content</p>';
do_action('my_plugin_after_content');
echo '</div>';
}
// Now anyone can hook into your plugin
add_action('my_plugin_after_content', function() {
echo '<small>Powered by My Plugin</small>';
});
remove_action() / remove_filter()
remove_action('wp_head', 'wp_generator'); // Hide WordPress version from <head>
9. Options API
Store and retrieve site-wide settings without touching the database directly.
get_option()
$site_name = get_option('blogname');
$admin_email = get_option('admin_email');
$my_setting = get_option('my_plugin_setting', 'default-value');
update_option()
update_option('my_plugin_setting', 'new-value');
update_option('my_array_setting', ['enabled' => true, 'count' => 5]);
add_option()
What it does: Only adds if it doesn’t exist. Use for plugin install defaults.
add_option('my_plugin_version', '1.0.0');
delete_option()
delete_option('old_setting');
10. User Functions
wp_get_current_user()
$user = wp_get_current_user();
if ($user->ID) {
echo 'Hello, ' . esc_html($user->display_name);
echo 'Your email: ' . esc_html($user->user_email);
echo 'Your roles: ' . implode(', ', $user->roles);
}
is_user_logged_in()
if (is_user_logged_in()) {
echo 'Welcome back!';
} else {
echo '<a href="' . esc_url(wp_login_url()) . '">Log in</a>';
}
current_user_can()
What it does: Check user permissions. Use this before allowing any admin action.
if (current_user_can('edit_posts')) {
// Show edit button
}
if (current_user_can('manage_options')) {
// Show admin settings
}
if (current_user_can('edit_post', $post_id)) {
// Check on a specific post
}
get_userdata() / get_user_by()
$user = get_userdata(5);
$user = get_user_by('email', '[email protected]');
$user = get_user_by('login', 'alice');
wp_create_user() / wp_insert_user()
$user_id = wp_create_user('newuser', 'password123', '[email protected]');
if (!is_wp_error($user_id)) {
echo 'User created with ID ' . $user_id;
}
11. Security & Escaping
Always escape output. Always sanitize input. This prevents XSS, SQL injection, and most security vulnerabilities.
Output escaping
| Function | Use case |
|---|---|
esc_html() |
Plain text output inside HTML |
esc_attr() |
HTML attribute values |
esc_url() |
URLs in href, src |
esc_js() |
Strings inside inline JS |
esc_textarea() |
Content inside <textarea> |
wp_kses_post() |
HTML that can contain safe tags (like post content) |
<a href="<?php echo esc_url($link); ?>" title="<?php echo esc_attr($title); ?>">
<?php echo esc_html($name); ?>
</a>
Input sanitization
| Function | Use case |
|---|---|
sanitize_text_field() |
Single-line text input |
sanitize_textarea_field() |
Multi-line text |
sanitize_email() |
Email addresses |
sanitize_title() |
Slugs / URL-friendly text |
sanitize_key() |
Identifiers (lowercase, alphanumeric only) |
absint() |
Positive integers |
wp_kses_post() |
Allow safe HTML, strip dangerous tags |
$name = sanitize_text_field($_POST['name']);
$email = sanitize_email($_POST['email']);
$bio = wp_kses_post($_POST['bio']);
$age = absint($_POST['age']);
12. Nonces (CSRF Protection)
Nonces protect against cross-site request forgery. Use them in every form and AJAX request.
wp_nonce_field()
<form method="post" action="">
<?php wp_nonce_field('save_my_form', 'my_form_nonce'); ?>
<input type="text" name="email">
<input type="submit" value="Save">
</form>
wp_verify_nonce() / check_admin_referer()
// In your form handler
if (!isset($_POST['my_form_nonce']) ||
!wp_verify_nonce($_POST['my_form_nonce'], 'save_my_form')) {
wp_die('Security check failed.');
}
// Now safe to process
$email = sanitize_email($_POST['email']);
wp_create_nonce()
Use for AJAX:
wp_localize_script('main-js', 'myAjax', [
'nonce' => wp_create_nonce('my_ajax_action'),
]);
// In JS
fetch(myAjax.ajaxurl, {
method: 'POST',
body: new URLSearchParams({
action: 'my_handler',
nonce: myAjax.nonce,
}),
});
// In handler
add_action('wp_ajax_my_handler', function() {
check_ajax_referer('my_ajax_action', 'nonce');
wp_send_json_success(['message' => 'Saved!']);
});
13. Database ($wpdb)
For custom queries that can’t be done with WP_Query. Always use $wpdb->prepare() to prevent SQL injection.
$wpdb->insert()
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'my_table',
[
'name' => 'Alice',
'email' => '[email protected]',
'date' => current_time('mysql'),
],
['%s', '%s', '%s'] // Format: %s string, %d integer, %f float
);
$new_id = $wpdb->insert_id;
$wpdb->update()
$wpdb->update(
$wpdb->prefix . 'my_table',
['name' => 'Alice Smith'], // SET
['id' => 5], // WHERE
['%s'], // Format for SET
['%d'] // Format for WHERE
);
$wpdb->delete()
$wpdb->delete(
$wpdb->prefix . 'my_table',
['id' => 5],
['%d']
);
$wpdb->get_results() and prepare()
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}my_table WHERE status = %s AND views > %d",
'published',
100
)
);
foreach ($results as $row) {
echo esc_html($row->name);
}
$wpdb->get_var() and $wpdb->get_row()
// Get single value
$count = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts}");
// Get single row
$row = $wpdb->get_row(
$wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE ID = %d", 5)
);
dbDelta()
What it does: Creates or updates database tables. Use in plugin activation hooks.
register_activation_hook(FILE, 'my_plugin_install');
function my_plugin_install() {
global $wpdb;
$table_name = $wpdb->prefix . 'my_table';
$charset = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
email varchar(100) NOT NULL,
date datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (id)
) $charset;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($sql);
}
14. Menus & Sidebars
register_nav_menus() (in functions.php)
function my_theme_menus() {
register_nav_menus([
'primary' => ('Primary Menu', 'my-theme'),
'footer' => ('Footer Menu', 'my-theme'),
]);
}
add_action('after_setup_theme', 'my_theme_menus');
wp_nav_menu() (in template)
<?php
wp_nav_menu([
'theme_location' => 'primary',
'menu_class' => 'nav-list',
'container' => 'nav',
'container_class' => 'main-nav',
'depth' => 2,
]);
?>
register_sidebar()
function my_theme_sidebars() {
register_sidebar([
'name' => ('Main Sidebar', 'my-theme'),
'id' => 'main-sidebar',
'description' => 'Appears on blog posts',
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h3 class="widget-title">',
'after_title' => '</h3>',
]);
}
add_action('widgets_init', 'my_theme_sidebars');
dynamic_sidebar() (in template)
<?php if (is_active_sidebar('main-sidebar')) : ?>
<aside><?php dynamic_sidebar('main-sidebar'); ?></aside>
<?php endif; ?>
15. Featured Images & Media
has_post_thumbnail()
if (has_post_thumbnail()) {
the_post_thumbnail('large');
}
the_post_thumbnail() and get_the_post_thumbnail()
the_post_thumbnail('medium', ['class' => 'rounded shadow']);
// Sizes: thumbnail, medium, large, full, or custom
wp_get_attachment_image_src()
What it does: Get the URL of an attachment.
$thumbnail_id = get_post_thumbnail_id();
$image = wp_get_attachment_image_src($thumbnail_id, 'full');
if ($image) {
echo '<img src="' . esc_url($image[0]) . '" width="' . $image[1] . '" height="' . $image[2] . '">';
}
add_image_size() (in functions.php)
add_action('after_setup_theme', function() {
add_theme_support('post-thumbnails');
add_image_size('card-thumb', 400, 300, true); // 400x300 cropped
add_image_size('hero-banner', 1920, 800, true);
});
// Use in template:
the_post_thumbnail('card-thumb');
wp_get_attachment_url()
$url = wp_get_attachment_url($attachment_id);
16. Comments
comments_template()
if (comments_open() || get_comments_number()) {
comments_template();
}
comment_form() with custom args
comment_form([
'title_reply' => 'Leave a Comment',
'label_submit' => 'Post Comment',
'class_submit' => 'btn btn-primary',
'comment_field' => '<p><textarea name="comment" rows="5" required></textarea></p>',
]);
wp_list_comments()
if (have_comments()) :
?>
<ol class="comment-list">
<?php
wp_list_comments([
'style' => 'ol',
'short_ping' => true,
'avatar_size' => 60,
]);
?>
</ol>
<?php
endif;
comments_open() / get_comments_number()
if (comments_open()) {
echo 'Comments are open';
}
echo get_comments_number() . ' comments';
17. Pagination
the_posts_pagination()
the_posts_pagination([
'prev_text' => '← Previous',
'next_text' => 'Next →',
'mid_size' => 2,
'screen_reader_text' => 'Posts navigation',
]);
paginate_links() (for custom queries)
$args = ['posts_per_page' => 10, 'paged' => get_query_var('paged') ?: 1];
$query = new WP_Query($args);
// ...loop...
echo paginate_links([
'total' => $query->max_num_pages,
'current' => max(1, get_query_var('paged')),
'format' => '?paged=%#%',
]);
wp_reset_postdata();
previous_post_link() / next_post_link()
<div class="post-nav">
<?php previous_post_link('<span class="prev">← %link</span>'); ?>
<?php next_post_link('<span class="next">%link →</span>'); ?>
</div>
18. Categories, Tags & Terms
get_categories()
$categories = get_categories([
'orderby' => 'name',
'hide_empty' => true,
]);
foreach ($categories as $cat) :
echo '<a href="' . esc_url(get_category_link($cat->term_id)) . '">'
. esc_html($cat->name) . ' (' . $cat->count . ')</a><br>';
endforeach;
get_tags()
$tags = get_tags(['hide_empty' => true]);
foreach ($tags as $tag) {
echo '<a href="' . esc_url(get_tag_link($tag->term_id)) . '">#' . esc_html($tag->name) . '</a> ';
}
get_terms() (for custom taxonomies)
$terms = get_terms([
'taxonomy' => 'product_category',
'hide_empty' => false,
]);
foreach ($terms as $term) {
echo esc_html($term->name);
}
wp_get_post_terms()
// Get all categories of a post
$post_cats = wp_get_post_terms(get_the_ID(), 'category');
// Get custom taxonomy terms
$brands = wp_get_post_terms(get_the_ID(), 'brand');
the_category() / the_tags() (display in loop)
the_category(', '); // Comma-separated list
the_tags('Tags: ', ', '); // With "Tags:" prefix
19. Custom Post Types & Taxonomies
register_post_type()
function register_my_cpt() {
register_post_type('product', [
'labels' => [
'name' => 'Products',
'singular_name' => 'Product',
'add_new' => 'Add Product',
'add_new_item' => 'Add New Product',
'edit_item' => 'Edit Product',
],
'public' => true,
'has_archive' => true,
'show_in_rest' => true, // For Gutenberg
'supports' => ['title', 'editor', 'thumbnail', 'excerpt', 'custom-fields'],
'menu_icon' => 'dashicons-cart',
'rewrite' => ['slug' => 'products'],
]);
}
add_action('init', 'register_my_cpt');
register_taxonomy()
function register_my_taxonomies() {
register_taxonomy('product_category', 'product', [
'labels' => [
'name' => 'Product Categories',
'singular_name' => 'Product Category',
],
'hierarchical' => true, // true = like categories, false = like tags
'show_in_rest' => true,
'rewrite' => ['slug' => 'product-category'],
]);
}
add_action('init', 'register_my_taxonomies');
20. AJAX
WordPress has a built-in AJAX system. Don’t roll your own.
Setup in PHP
// 1. Enqueue your JS and pass the AJAX URL + nonce
function my_ajax_setup() {
wp_enqueue_script('my-ajax', get_template_directory_uri() . '/js/ajax.js', ['jquery'], '1.0', true);
wp_localize_script('my-ajax', 'myAjax', [
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('my_ajax_nonce'),
]);
}
add_action('wp_enqueue_scripts', 'my_ajax_setup');
// 2. Handle the AJAX request
add_action('wp_ajax_save_form', 'handle_save_form'); // Logged-in users
add_action('wp_ajax_nopriv_save_form', 'handle_save_form'); // Visitors
function handle_save_form() {
check_ajax_referer('my_ajax_nonce', 'nonce');
$name = sanitize_text_field($_POST['name']);
$email = sanitize_email($_POST['email']);
if (empty($name) || empty($email)) {
wp_send_json_error(['message' => 'All fields are required']);
}
// Save to database...
wp_send_json_success(['message' => 'Saved!', 'id' => 42]);
}
JavaScript side
fetch(myAjax.ajaxurl, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
action: 'save_form', // Matches wp_ajax_save_form
nonce: myAjax.nonce,
name: 'Alice',
email: '[email protected]',
}),
})
.then(r => r.json())
.then(data => {
if (data.success) {
console.log('Saved!', data.data.message);
} else {
console.error(data.data.message);
}
});
wp_send_json_success() / wp_send_json_error()
These automatically set headers, encode JSON, and exit. Always use them in AJAX handlers.
Top 20 Daily-Use Cheat Sheet
If you only memorize these, you can build 80% of WordPress projects:
| Function | Use case |
|---|---|
have_posts() + the_post() |
The Loop |
the_title() / the_content() / the_permalink() |
Display post data |
get_the_ID() |
Current post ID |
WP_Query |
Custom queries |
wp_reset_postdata() |
After custom queries |
get_post_meta($id, 'key', true) |
Custom fields |
update_post_meta() |
Save custom fields |
home_url() / get_template_directory_uri() |
URLs |
is_home() / is_single() / is_page() |
Conditional checks |
get_header() / get_footer() |
Template includes |
wp_enqueue_style() / wp_enqueue_script() |
Load CSS/JS |
add_action() / add_filter() |
Hooks |
get_option() / update_option() |
Site settings |
current_user_can('capability') |
Permission checks |
esc_html() / esc_url() / esc_attr() |
Output escaping |
sanitize_text_field() |
Input sanitization |
wp_nonce_field() / wp_verify_nonce() |
Form security |
wp_nav_menu() |
Display menus |
the_post_thumbnail() |
Featured image |
the_posts_pagination() |
Pagination |
Common Mistakes to Avoid
| Mistake | Why it’s bad | Fix |
|---|---|---|
Using query_posts() |
Breaks main query & pagination | Use WP_Query or pre_get_posts filter |
Forgetting wp_reset_postdata() |
Breaks subsequent loops | Always reset after WP_Query |
| Hard-coding URLs | Breaks when site moves | Use home_url(), get_template_directory_uri() |
Hard-coding <link>/<script> tags |
No caching, no dependency management | Use wp_enqueue_style/script() |
Echoing $_POST data directly |
XSS vulnerability | Sanitize input, escape output |
| Not using nonces | CSRF vulnerability | Add wp_nonce_field() to all forms |
Direct $_GET/$_POST SQL queries |
SQL injection | Use $wpdb->prepare() |
update_option() on every page load |
Slow + DB bloat | Cache via transients or autoload |
Putting CPTs in functions.php |
Data lost when theme changes | Put in plugin or MU plugin |
Forgetting wp_head() / wp_footer() |
Plugins break | Always include both in templates |
Wrapping Up
You don’t need to memorize 70 functions today. Start with the Top 20 cheat sheet above — you’ll use those daily. Add the rest as you encounter use cases. Within a few months you’ll have them all in muscle memory.
WordPress’s API is huge, but consistent. Once you understand the patterns — hooks, escaping, the loop, custom queries — you can build virtually anything: blogs, e-commerce, membership sites, headless apps, custom admin panels.
💡 Pro tip: When you forget a function name or syntax, the WordPress Code Reference is the official documentation. Search there before Stack Overflow — it’s faster and always up to date.
Recommended next reads
- WordPress Theme Development from Scratch — see all these functions in action in a real theme
- Useful Docker Commands — set up a fast local WordPress dev environment
- WordPress Hooks Explained: Actions vs Filters (coming soon)
Related reading on this blog: [wordpress-theme-development-from-scratch], [wsl-docker-php-setup], [useful-docker-commands]
Be the first to comment