What is WordPress?

WordPress is an open-source Content Management System (CMS) based on PHP and MySQL/MariaDB. Powering over 40% of the web, it has evolved from a simple blogging engine into a highly extensible, enterprise-grade application framework featuring robust plugin/theme ecosystems and modern block-based site building capabilities.

Core Directory Structure

  • A standard WordPress installation separates administration, configuration, and user assets:

File Layout

├── wp-admin/             # Admin dashboard backend core files
├── wp-includes/          # Core libraries, helper functions, and classes
├── wp-content/           # User-space directory (safest place to modify)
│   ├── themes/           # Custom and active themes
│   ├── plugins/          # Custom and active plugins
│   └── uploads/          # Media library items (organized by year/month)
├── wp-config.php         # Database configuration, salts, and debug settings
├── .htaccess             # Apache server configuration (permalink routing rules)
└── index.php             # Main entry point that loads the WordPress core

Database Schema

  • WordPress uses a simple relational database structure consisting of 12 core tables by default:

Core Table Functions

Table NamePurposeKey Columns / Relations
wp_postsStores post types (posts, pages, attachments, menu items, revisions).ID, post_title, post_content, post_type, post_status
wp_postmetaMetadata store (EAV pattern) containing custom fields for posts.meta_id, post_id (FK), meta_key, meta_value
wp_optionsSite-wide configuration settings and transients.option_id, option_name, option_value, autoload
wp_usersRegistered users data.ID, user_login, user_pass (hashed), user_email
wp_usermetaMetadata associated with users (capabilities, preferences).meta_id, user_id (FK), meta_key, meta_value
wp_termsClassification descriptors (categories, tags, custom taxonomies).term_id, name, slug
wp_term_taxonomyGroups terms into taxonomies (e.g., term #1 is a ‘category’).term_taxonomy_id, term_id (FK), taxonomy
wp_term_relationshipsResolves many-to-many links between posts and terms.object_id (Post ID), term_taxonomy_id (FK)
wp_commentsComment list, approvals, and pingbacks.comment_ID, comment_post_ID (FK), comment_author
wp_commentmetaMetadata associated with comments.meta_id, comment_id (FK), meta_key, meta_value

The Hooks System (Actions vs Filters)

  • Hooks are the core mechanism of WordPress extensibility, allowing developers to execute code or modify data without modifying core files.

Key Concepts

  • Actions: Triggered at specific points in the execution cycle. Used to perform tasks (e.g., sending emails, registering custom sidebars, or enqueuing styles).
  • Filters: Triggered to process data before it is rendered, saved to the database, or returned. Always receive data as an argument and must return modified data.

Hooks Execution Cycle

graph TD
    A[WordPress Bootstraps] --> B(do_action 'init')
    B --> C(do_action 'wp_enqueue_scripts')
    C --> D[Run Queries / Load Template]
    D --> E{apply_filters 'the_content'}
    E --> F[Render output to Client]

Actions & Filters Syntax

// 1. ACTION EXAMPLE
// Trigger custom script/style loading
function my_theme_assets() {
    wp_enqueue_style( 'my-style', get_stylesheet_uri() );
}
add_action( 'wp_enqueue_scripts', 'my_theme_assets', 10 );
 
// 2. FILTER EXAMPLE
// Append custom text to all post content
function my_custom_content_footer( $content ) {
    if ( is_single() ) {
        $content .= '<p class="content-sig">Thanks for reading!</p>';
    }
    return $content; // Filters MUST return the input data
}
add_filter( 'the_content', 'my_custom_content_footer', 15 );

Template Hierarchy & The Loop

Hierarchy Flow

  • When a page is requested, WordPress traverses a fallback hierarchy to find the appropriate template file:
  • Single Post (post): single-post.phpsingle.phpsingular.phpindex.php
  • Static Page (page): page-{slug}.phppage-{id}.phppage.phpsingular.phpindex.php
  • Archive (Category): category-{slug}.phpcategory-{id}.phpcategory.phparchive.phpindex.php

The WordPress Loop

  • The fundamental logic blocks used to fetch and display posts:
// The standard global loop
if ( have_posts() ) {
    while ( have_posts() ) {
        the_post(); // Hydrates the global $post object and sets up template tags
        
        echo '<h2>' . get_the_title() . '</h2>';
        the_content();
    }
} else {
    echo '<p>No content found.</p>';
}

Custom Query (WP_Query)

  • For fetching custom data outside the main global query:
$args = array(
    'post_type'      => 'product',
    'posts_per_page' => 5,
    'meta_key'       => 'featured',
    'meta_value'     => 'yes'
);
 
$custom_query = new WP_Query( $args );
 
if ( $custom_query->have_posts() ) {
    while ( $custom_query->have_posts() ) {
        $custom_query->the_post();
        the_title( '<h3>', '</h3>' );
    }
    wp_reset_postdata(); // Restores global $post object to original main query
}

Theme Development

  • A minimal theme requires only two files: style.css (metadata declaration) and index.php (rendering logic).

style.css Header

/*
Theme Name: Developer Reference Theme
Theme URI: https://example.com/ref-theme
Author: Vaibhav Rathod
Description: A minimal, high-performance base theme for developer notes.
Version: 1.0.0
License: GNU General Public License v2 or later
Text Domain: dev-ref-theme
*/

functions.php Setup

  • Used to configure theme support, menus, and assets:
<?php
 
function dev_theme_setup() {
    // Add support for document title tag (handled by WP)
    add_theme_support( 'title-tag' );
    // Add support for post thumbnails (featured images)
    add_theme_support( 'post-thumbnails' );
    
    // Register navigation menus
    register_nav_menus( array(
        'primary-menu' => esc_html__( 'Primary Navigation Menu', 'dev-ref-theme' ),
    ) );
}
add_action( 'after_setup_theme', 'dev_theme_setup' );
 
// Enqueue styles and scripts correctly
function dev_theme_scripts() {
    wp_enqueue_style( 'main-style', get_stylesheet_uri() );
    wp_enqueue_script( 'main-js', get_template_directory_uri() . '/js/main.js', array(), '1.0.0', true );
}
add_action( 'wp_enqueue_scripts', 'dev_theme_scripts' );

Plugin Development & Security

Starter Plugin Header

  • Place this in a file named wp-content/plugins/my-plugin/my-plugin.php:
<?php
/*
Plugin Name: Developer Reference Core Plugin
Plugin URI: https://example.com/ref-plugin
Description: Core custom functionalities, custom post types, and security filters.
Version: 1.0.0
Author: Vaibhav Rathod
License: GPL2
Text Domain: dev-ref-plugin
*/
 
// Prevent direct file access (Crucial Security Check)
if ( ! defined( 'ABSPATH' ) ) {
    exit; 
}

Data Sanitization & Escaping

  • Always assume client inputs are untrusted and output targets must be clean to prevent XSS:
// 1. Sanitizing incoming inputs
$username = sanitize_text_field( $_POST['username'] );
$user_email = sanitize_email( $_POST['email'] );
 
// 2. Escaping output variables
echo '<h3>' . esc_html( $username ) . '</h3>';
echo '<a href="' . esc_url( $profile_url ) . '">View Profile</a>';
echo '<input type="text" name="city" value="' . esc_attr( $city ) . '">';

Database Access ($wpdb)

  • For database mutations, always use $wpdb->prepare to prevent SQL Injection:
global $wpdb;
$table_name = $wpdb->prefix . 'custom_table';
 
$user_status = 'active';
$user_id = 45;
 
// Prepare ensures SQL is fully parameterized and clean
$query = $wpdb->prepare(
    "UPDATE $table_name SET status = %s WHERE id = %d",
    $user_status,
    $user_id
);
 
$wpdb->query( $query );

Modern Block Development (Gutenberg)

  • Modern WordPress uses Block Themes (Full Site Editing) relying on JSON configuration and HTML templates containing block markup rather than raw PHP.

theme.json Structure

  • Defines color palettes, typography, and default layout widths:
{
  "version": 2,
  "settings": {
    "color": {
      "palette": [
        {
          "name": "Primary",
          "slug": "primary",
          "color": "#3858e9"
        },
        {
          "name": "Light",
          "slug": "light",
          "color": "#f8f9fa"
        }
      ]
    },
    "layout": {
      "contentSize": "800px",
      "wideSize": "1200px"
    }
  }
}

Advanced Performance Optimization

The Transients API

  • Used to store parsed/complex data in the database with an expiration time, preventing expensive API calls or database calculations:
// Fetch data, caching it for 1 hour
function get_featured_products_count() {
    $cache_key = 'featured_products_count';
    $count = get_transient( $cache_key );
    
    if ( false === $count ) {
        // Transient expired or doesn't exist, calculate value
        global $wpdb;
        $count = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status = 'publish'" );
        
        // Save for 1 hour (3600 seconds)
        set_transient( $cache_key, $count, HOUR_IN_SECONDS );
    }
    
    return $count;
}
 
// Clear transient on product publish
add_action( 'publish_product', function() {
    delete_transient( 'featured_products_count' );
});

Caching Types

  • Page Cache: Saves the generated HTML output of a webpage. Subsequent visitors receive the static HTML page directly without running PHP or MySQL. Handled via plugins (W3 Total Cache, WP Rocket).
  • Object Cache: Caches individual database query results or computation objects in memory (using Redis or Memcached). Prevents repetitive SQL queries during a single session.

Learning References

Handbooks & Guides