WordPress

PHP Functions Every WordPress Developer Must Know

Arshad Shah
May 30, 2026
WordPress

WordPress is built on PHP — and while the block editor, REST API, and JavaScript are all increasingly central to the platform in 2026, PHP remains the backbone of every theme, plugin, and customisation that makes a WordPress site actually work. Understanding the right PHP functions is not optional for serious WordPress development. It is the difference between writing code that is clean, secure, and maintainable — and writing code that breaks on updates, opens security holes, or queries the database fifty times per page load.

This guide covers the PHP functions every WordPress developer uses regularly — grouped by category, with real code examples and clear explanations of when and why to use each one. Whether you are just starting out with WordPress development or have been building sites professionally for years, these are the functions worth knowing deeply.

Category 1: Hook Functions — The Core of WordPress Architecture

WordPress hooks — actions and filters — are the foundation of everything. They are how plugins and themes modify WordPress behaviour without touching core files. Every serious WordPress developer must understand these four functions completely.

add_action()

add_action( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 );

Attaches a function to a specific action hook. WordPress fires action hooks at defined points during execution — when a post is saved, when the page header loads, when a plugin is activated. Your callback function runs when that point is reached.

// Enqueue a stylesheet on the frontend
function arshadws_enqueue_styles() {
    wp_enqueue_style(
        'arshadws-main',
        get_stylesheet_uri(),
        array(),
        '1.0.0'
    );
}
add_action( 'wp_enqueue_scripts', 'arshadws_enqueue_styles' );

// Run code when a post is saved
function arshadws_on_post_save( $post_id ) {
    if ( wp_is_post_revision( $post_id ) ) {
        return;
    }
    // Your logic here
}
add_action( 'save_post', 'arshadws_on_post_save' );

add_filter()

add_filter( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 );

Attaches a function to a filter hook. Unlike actions, filters receive a value, modify it, and return the modified version. They are how you change data as it passes through WordPress — post content, titles, query arguments, email subjects.

// Add a custom class to body tag
function arshadws_body_classes( $classes ) {
    if ( is_single() ) {
        $classes[] = 'arshadws-single-post';
    }
    return $classes;
}
add_filter( 'body_class', 'arshadws_body_classes' );

// Modify the excerpt length
function arshadws_excerpt_length( $length ) {
    return 25;
}
add_filter( 'excerpt_length', 'arshadws_excerpt_length' );

do_action() and apply_filters()

These are the counterparts to add_action() and add_filter() — they fire the hook rather than attach to it. You use these when writing plugins or themes that other developers can extend.

// Fire a custom action hook in your plugin
do_action( 'arshadws_before_card_output', $post_id );

// Apply a custom filter hook in your plugin
$card_title = apply_filters( 'arshadws_card_title', get_the_title( $post_id ), $post_id );
echo esc_html( $card_title );

remove_action() and remove_filter()

// Remove a default WordPress action
remove_action( 'wp_head', 'wp_generator' );

// Remove a filter added by a plugin
// Priority must match the original add_filter() call
remove_filter( 'the_content', array( $plugin_instance, 'modify_content' ), 10 );

Category 2: Query Functions — Retrieving Posts and Data

WP_Query

WP_Query is the most powerful and flexible way to retrieve posts from the WordPress database. It supports hundreds of parameters and should be your default choice for any custom post retrieval.

$args = array(
    'post_type'      => 'portfolio',
    'posts_per_page' => 6,
    'orderby'        => 'date',
    'order'          => 'DESC',
    'tax_query'      => array(
        array(
            'taxonomy' => 'portfolio_category',
            'field'    => 'slug',
            'terms'    => 'web-design',
        ),
    ),
);

$query = new WP_Query( $args );

if ( $query->have_posts() ) {
    while ( $query->have_posts() ) {
        $query->the_post();
        echo '' . esc_html( get_the_title() ) . '';
    }
    wp_reset_postdata(); // Always reset after a custom query
} else {
    echo 'No projects found.';
}

Always call wp_reset_postdata() after a custom WP_Query loop. Forgetting this is one of the most common causes of unexpected behaviour in WordPress templates — it restores the global $post object after your custom query.

get_posts()

A simpler wrapper around WP_Query for situations where you just need an array of post objects and do not need a full loop. Best for small, simple queries where the overhead of a full WP_Query loop is unnecessary.

$recent_posts = get_posts( array(
    'post_type'      => 'post',
    'posts_per_page' => 3,
    'orderby'        => 'date',
    'order'          => 'DESC',
) );

foreach ( $recent_posts as $post ) {
    setup_postdata( $post );
    echo '' . esc_html( get_the_title( $post->ID ) ) . '';
}
wp_reset_postdata();

get_post() and get_post_field()

// Get a full post object by ID
$post = get_post( 42 );
echo esc_html( $post->post_title );

// Get a single field from a post
$title   = get_post_field( 'post_title', 42 );
$content = get_post_field( 'post_content', 42 );
$status  = get_post_field( 'post_status', 42 );

Category 3: Security Functions — Never Skip These

Security functions are the most important category on this list. Every piece of data that enters your WordPress site needs to be sanitised. Every piece of data that leaves it needs to be escaped. No exceptions.

Sanitization — Clean Input

Sanitize data before saving it to the database or processing it. Use the most specific sanitization function available for the data type.

// Sanitize plain text input
$name = sanitize_text_field( $_POST['name'] );

// Sanitize a textarea (strips tags, normalizes whitespace)
$message = sanitize_textarea_field( $_POST['message'] );

// Sanitize an email address
$email = sanitize_email( $_POST['email'] );

// Sanitize a URL
$website = esc_url_raw( $_POST['website'] );

// Sanitize an integer
$post_id = absint( $_POST['post_id'] );

// Sanitize a slug
$slug = sanitize_title( $_POST['slug'] );

// Sanitize a CSS class
$css_class = sanitize_html_class( $_POST['class'] );

Escaping — Clean Output

Escape data immediately before outputting it — as late as possible, as close to the output as possible. Use the most specific escaping function for the context.

// Escape plain text for HTML output
echo esc_html( $title );

// Escape a URL for use in href or src attributes
echo '' . esc_html( $text ) . '';

// Escape a value for use inside an HTML attribute
echo '';

// Escape content that may contain allowed HTML tags
echo wp_kses_post( $rich_content );

// Escape a URL for use in JavaScript
echo '';

// Escape for use in a CSS context
echo '';

Nonce Functions — Verify Intent

Nonces (numbers used once) verify that a form submission or AJAX request originated from your site and from an authorised user. Always use nonces on forms and AJAX handlers.

// Generate a nonce field inside a form
function arshadws_my_form() {
    echo '';
    wp_nonce_field( 'arshadws_save_action', 'arshadws_nonce_field' );
    echo '';
    echo '';
}

// Verify the nonce when the form is submitted
function arshadws_handle_form_submission() {
    if ( ! isset( $_POST['arshadws_nonce_field'] )
        || ! wp_verify_nonce( $_POST['arshadws_nonce_field'], 'arshadws_save_action' )
    ) {
        wp_die( 'Security check failed.' );
    }

    // Verify user capability
    if ( ! current_user_can( 'edit_posts' ) ) {
        wp_die( 'You do not have permission to do this.' );
    }

    // Safe to process the form now
    $name = sanitize_text_field( $_POST['name'] );
}
add_action( 'admin_post_arshadws_save', 'arshadws_handle_form_submission' );

Category 4: Options API — Storing Plugin and Theme Settings

The Options API is the correct way to store and retrieve plugin and theme settings in WordPress. Never store persistent configuration in flat files or custom database tables when the Options API handles it cleanly.

// Save an option
update_option( 'arshadws_api_key', sanitize_text_field( $api_key ) );

// Retrieve an option with a default fallback
$api_key = get_option( 'arshadws_api_key', '' );

// Delete an option
delete_option( 'arshadws_api_key' );

// Check if an option exists
if ( get_option( 'arshadws_setup_complete' ) ) {
    // Setup has been run
}

// Store an array as an option (WordPress handles serialisation)
$settings = array(
    'enable_feature' => true,
    'items_per_page' => 10,
    'colour_scheme'  => 'dark',
);
update_option( 'arshadws_plugin_settings', $settings );

// Retrieve the array
$settings = get_option( 'arshadws_plugin_settings', array() );

Post Meta Functions

Post meta stores data associated with a specific post — used for everything from ACF field values to custom flags and settings on individual posts.

// Save post meta — always sanitize first
update_post_meta( $post_id, '_arshadws_subtitle', sanitize_text_field( $subtitle ) );

// Retrieve post meta
$subtitle = get_post_meta( $post_id, '_arshadws_subtitle', true );
// Third argument true = return single value (string)
// Third argument false = return array of all values

// Delete post meta
delete_post_meta( $post_id, '_arshadws_subtitle' );

// Check if meta exists
if ( metadata_exists( 'post', $post_id, '_arshadws_subtitle' ) ) {
    $subtitle = get_post_meta( $post_id, '_arshadws_subtitle', true );
}

Prefix your meta keys with an underscore (e.g. _arshadws_key) to hide them from the default custom fields panel in the WordPress editor. Use a unique prefix for your plugin or theme to prevent collisions with other plugins’ meta keys.

Category 5: Template Functions — Building Theme Templates

Content Display Functions

// Display post title (outputs directly)
the_title();

// Get post title as a string (for use in attributes etc.)
$title = get_the_title( $post_id );

// Display post content
the_content();

// Display post excerpt
the_excerpt();

// Display post permalink
the_permalink();

// Get post permalink as a string
$url = get_permalink( $post_id );

// Display featured image
the_post_thumbnail( 'large' );

// Get featured image URL
$image_url = get_the_post_thumbnail_url( $post_id, 'large' );

// Display post date
the_date( 'F j, Y' );

// Display author name
the_author();

Template Part Functions

// Include a template part
// Looks for template-parts/card.php
get_template_part( 'template-parts/card' );

// Include a template part with variant
// Looks for template-parts/card-featured.php first,
// then template-parts/card.php
get_template_part( 'template-parts/card', 'featured' );

// Pass data to a template part (WordPress 5.5+)
get_template_part(
    'template-parts/card',
    'product',
    array(
        'post_id'    => $post_id,
        'show_price' => true,
    )
);
// Access in the template part via $args['post_id'] etc.

Asset Functions

// Enqueue a stylesheet
function arshadws_enqueue_assets() {
    wp_enqueue_style(
        'arshadws-styles',                           // Handle
        get_template_directory_uri() . '/css/main.css', // URL
        array(),                                     // Dependencies
        '1.0.0',                                     // Version
        'all'                                        // Media
    );

    // Enqueue a script
    wp_enqueue_script(
        'arshadws-scripts',
        get_template_directory_uri() . '/js/main.js',
        array( 'jquery' ),   // Dependencies
        '1.0.0',
        true                 // Load in footer
    );

    // Pass PHP data to JavaScript
    wp_localize_script(
        'arshadws-scripts',
        'arshadwsData',
        array(
            'ajaxUrl' => admin_url( 'admin-ajax.php' ),
            'nonce'   => wp_create_nonce( 'arshadws_ajax_nonce' ),
            'siteUrl' => get_site_url(),
        )
    );
}
add_action( 'wp_enqueue_scripts', 'arshadws_enqueue_assets' );

Category 6: User Functions — Managing Users and Capabilities

// Get the current logged-in user
$current_user = wp_get_current_user();
echo esc_html( $current_user->display_name );
echo esc_html( $current_user->user_email );

// Check if a user is logged in
if ( is_user_logged_in() ) {
    // Show content for logged-in users
}

// Check user capabilities
if ( current_user_can( 'manage_options' ) ) {
    // Only admins can do this
}

if ( current_user_can( 'edit_post', $post_id ) ) {
    // User can edit this specific post
}

// Get user data by ID
$user = get_userdata( $user_id );
echo esc_html( $user->user_login );

// Get current user ID
$user_id = get_current_user_id();

// Get user meta
$user_role = get_user_meta( $user_id, 'arshadws_user_tier', true );

// Update user meta
update_user_meta( $user_id, 'arshadws_user_tier', 'premium' );

Category 7: URL and Path Functions — Getting the Right Locations

// Theme directory URL (for assets)
get_template_directory_uri();       // Parent theme URL
get_stylesheet_directory_uri();     // Child theme URL (use this in child themes)

// Theme directory path (for including files)
get_template_directory();           // Parent theme path
get_stylesheet_directory();         // Child theme path

// Plugin directory URL and path
plugin_dir_url( __FILE__ );         // URL
plugin_dir_path( __FILE__ );        // Path

// Site URLs
get_site_url();                     // Home URL with path
get_home_url();                     // Home URL
admin_url( 'admin-ajax.php' );      // Admin URL with path
get_admin_url();                    // Admin URL base

// Includes URL (for WordPress core assets)
includes_url( 'js/jquery/jquery.js' );

Category 8: Utility Functions — Everyday Developer Tools

Conditional Tag Functions

// Post type checks
is_single();         // Single post
is_page();           // Static page
is_archive();        // Archive page
is_home();           // Blog posts index
is_front_page();     // Front page (static or blog)
is_category();       // Category archive
is_tag();            // Tag archive
is_tax();            // Custom taxonomy archive
is_search();         // Search results page
is_404();            // 404 error page
is_admin();          // WordPress admin area

// Context checks
is_user_logged_in(); // Logged-in user
is_plugin_active( 'woocommerce/woocommerce.php' ); // Plugin active check
is_wp_error( $result ); // Check if a result is a WP_Error object

wp_die() and wp_redirect()

// Terminate execution with a message
wp_die(
    esc_html__( 'You do not have permission to access this page.', 'arshadws' ),
    esc_html__( 'Permission Denied', 'arshadws' ),
    array( 'response' => 403 )
);

// Safe redirect (always use wp_redirect over header())
wp_redirect( home_url( '/thank-you/' ), 302 );
exit; // Always call exit after wp_redirect

wp_send_json() — AJAX Responses

// Handle an AJAX request and return JSON
function arshadws_ajax_handler() {
    check_ajax_referer( 'arshadws_ajax_nonce', 'nonce' );

    if ( ! current_user_can( 'edit_posts' ) ) {
        wp_send_json_error( array( 'message' => 'Permission denied.' ), 403 );
    }

    $data = sanitize_text_field( $_POST['data'] );

    // Process the request
    $result = array(
        'message' => 'Success',
        'data'    => $data,
    );

    wp_send_json_success( $result );
    // wp_send_json_success() calls wp_die() automatically
}
add_action( 'wp_ajax_arshadws_action', 'arshadws_ajax_handler' );
add_action( 'wp_ajax_nopriv_arshadws_action', 'arshadws_ajax_handler' );

absint(), wp_parse_args(), and wp_parse_id_list()

// Convert to a non-negative integer — use for IDs
$post_id = absint( $_GET['post_id'] );

// Merge user-supplied arguments with defaults
function arshadws_display_posts( $args = array() ) {
    $defaults = array(
        'post_type'      => 'post',
        'posts_per_page' => 6,
        'orderby'        => 'date',
        'show_excerpt'   => true,
    );
    $args = wp_parse_args( $args, $defaults );

    // $args now has all defaults with any overrides applied
}

// Convert a comma-separated string or array of IDs to clean integers
$ids = wp_parse_id_list( '1, 2, 3, 4' );
// Returns: array( 1, 2, 3, 4 )

Category 9: Custom Post Type and Taxonomy Functions

// Register a custom post type
function arshadws_register_post_types() {
    register_post_type(
        'portfolio',
        array(
            'labels'      => array(
                'name'          => __( 'Portfolio', 'arshadws' ),
                'singular_name' => __( 'Project', 'arshadws' ),
            ),
            'public'      => true,
            'has_archive' => true,
            'supports'    => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
            'menu_icon'   => 'dashicons-portfolio',
            'rewrite'     => array( 'slug' => 'portfolio' ),
            'show_in_rest' => true, // Required for block editor support
        )
    );
}
add_action( 'init', 'arshadws_register_post_types' );

// Register a custom taxonomy
function arshadws_register_taxonomies() {
    register_taxonomy(
        'portfolio_category',
        'portfolio',
        array(
            'labels'       => array(
                'name'          => __( 'Portfolio Categories', 'arshadws' ),
                'singular_name' => __( 'Portfolio Category', 'arshadws' ),
            ),
            'hierarchical'  => true,
            'public'        => true,
            'rewrite'       => array( 'slug' => 'portfolio-category' ),
            'show_in_rest'  => true,
        )
    );
}
add_action( 'init', 'arshadws_register_taxonomies' );

Quick Reference: The Essential Function Cheat Sheet

  • Hooks: add_action(), add_filter(), do_action(), apply_filters(), remove_action(), remove_filter()
  • Queries: WP_Query, get_posts(), get_post(), wp_reset_postdata()
  • Security: sanitize_text_field(), esc_html(), esc_url(), esc_attr(), wp_kses_post(), wp_verify_nonce(), current_user_can()
  • Options API: get_option(), update_option(), get_post_meta(), update_post_meta()
  • Templates: get_template_part(), wp_enqueue_style(), wp_enqueue_script(), wp_localize_script()
  • Users: is_user_logged_in(), current_user_can(), get_current_user_id()
  • Utilities: absint(), wp_parse_args(), wp_send_json_success(), wp_redirect(), wp_die()

Conclusion: Know These Functions Deeply, Not Just Broadly

The developers who write the best WordPress code are not the ones who have memorised every function in the WordPress codex. They are the ones who understand a core set of functions deeply — why they exist, when to use them, and what happens when you use the wrong one for the context.

Sanitising input with the wrong function, escaping output at the wrong time, or forgetting wp_reset_postdata() after a custom query are not beginner mistakes. They are mistakes that happen when you know a function exists but do not understand how it actually works. The code examples in this guide are production-tested patterns — copy them, use them as a foundation, and adapt them to your specific requirements.

At ArshadWebStudio, every WordPress project we deliver is built on these foundations — clean hooks, proper sanitisation and escaping, correct use of the Options API, and code that follows WordPress standards from the first line to the last. If you need a WordPress developer who writes code the right way, get in touch today.

About the Author

Arshad Shah is a freelance WordPress and Shopify developer at arshadwebstudio.com, specialising in custom plugin development, block theme architecture, WooCommerce, and performance optimisation. He builds fast, secure, and maintainable WordPress solutions for clients worldwide.

Comments

No comments yet. Be the first to share your thoughts!

Leave a Comment

Let's Build Something Remarkable

Ready to take your web presence to the next level? Let's talk.