wordpress-core

WordPress Core Development Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "wordpress-core" with this command: npx skills add mikkelkrogsholm/wp-plugins/mikkelkrogsholm-wp-plugins-wordpress-core

WordPress Core Development Skill

Core WordPress plugin development knowledge. Focus on fundamentals, security, and standard patterns.

Target: WordPress 6.8+

WordPress Plugin File Structure

Standard organization for WordPress plugins:

plugin-name/ ├── plugin-name.php # Main plugin file (header, activation) ├── uninstall.php # Uninstall cleanup (optional) ├── includes/ │ ├── class-plugin-name.php # Main plugin class │ ├── class-activator.php # Activation logic │ └── class-deactivator.php # Deactivation logic ├── admin/ │ ├── class-admin.php # Admin-specific functionality │ ├── css/ │ ├── js/ │ └── partials/ # Admin view templates ├── public/ │ ├── class-public.php # Public-facing functionality │ ├── css/ │ ├── js/ │ └── partials/ # Public view templates └── languages/ # Translation files

Key Principles:

  • Main plugin file contains header and initialization only

  • Separate admin and public functionality

  • Use classes for organization (recommended)

  • Follow WordPress naming conventions (lowercase, hyphens)

Plugin Header Format

Every plugin must have a header in the main file:

<?php /**

// If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; }

Required Fields: Plugin Name Recommended: Description, Version, Author, License, Text Domain

Security Principles (CRITICAL)

WordPress security follows three golden rules:

  1. Sanitize Input (Trust Nothing)

Always sanitize data coming from users:

// Text input $clean_text = sanitize_text_field( $_POST['user_input'] );

// Email $clean_email = sanitize_email( $_POST['email'] );

// URL $clean_url = esc_url_raw( $_POST['url'] );

// Integer $clean_id = absint( $_POST['post_id'] );

// Array of text fields $clean_array = array_map( 'sanitize_text_field', $_POST['items'] );

Common Functions:

  • sanitize_text_field()

  • Strips tags, scripts

  • sanitize_email()

  • Validates email format

  • sanitize_key()

  • Lowercase alphanumeric, dashes, underscores

  • sanitize_title()

  • Creates slug-safe string

  • esc_url_raw()

  • Database-safe URL

  • absint()

  • Absolute integer (positive only)

  • intval()

  • Integer conversion

  1. Escape Output (Never Trust Data)

Always escape data when outputting to HTML:

// HTML content echo esc_html( $user_data );

// HTML attributes echo '<input value="' . esc_attr( $value ) . '">';

// URLs echo '<a href="' . esc_url( $link ) . '">Link</a>';

// JavaScript echo '<script>var data = ' . wp_json_encode( $data ) . ';</script>';

// Textarea echo '<textarea>' . esc_textarea( $content ) . '</textarea>';

Common Functions:

  • esc_html()

  • Escapes HTML (converts < > & " ')

  • esc_attr()

  • Escapes HTML attributes

  • esc_url()

  • Escapes URLs for output

  • esc_js()

  • Escapes JavaScript strings

  • esc_textarea()

  • Escapes textarea content

  • wp_kses_post()

  • Allows safe HTML (like posts)

  1. Nonces (Verify Intent)

Use nonces to prevent CSRF attacks:

// Creating a nonce (in form) wp_nonce_field( 'my_action_name', 'my_nonce_field' );

// Verifying a nonce (on submission) if ( ! isset( $_POST['my_nonce_field'] ) || ! wp_verify_nonce( $_POST['my_nonce_field'], 'my_action_name' ) ) { die( 'Security check failed' ); }

// URL nonces $url = wp_nonce_url( 'admin.php?action=delete&id=123', 'delete_item_123' );

// Verify URL nonce if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'delete_item_123' ) ) { die( 'Security check failed' ); }

  1. Capability Checks (Authorization)

Verify user has permission:

// Check if user can perform action if ( ! current_user_can( 'manage_options' ) ) { wp_die( 'You do not have sufficient permissions' ); }

// Common capabilities current_user_can( 'edit_posts' ); current_user_can( 'publish_pages' ); current_user_can( 'edit_others_posts' );

Security Checklist:

  • All user input sanitized

  • All output escaped

  • Nonces verify form submissions

  • Capability checks on all admin actions

  • Direct file access prevented (defined( 'WPINC' ) )

Hooks System (Actions and Filters)

WordPress uses hooks to allow plugins to modify behavior.

Actions (Do Something)

Execute code at specific points:

// Add an action add_action( 'init', 'my_function' ); add_action( 'wp_enqueue_scripts', 'my_enqueue_function' ); add_action( 'admin_menu', 'my_menu_function' );

// Custom action (for your plugin) do_action( 'my_plugin_custom_action', $param1, $param2 );

Common Action Hooks:

  • init

  • WordPress initialized, user authenticated

  • admin_init

  • Admin area initialized

  • admin_menu

  • Time to add admin menu items

  • wp_enqueue_scripts

  • Enqueue public scripts/styles

  • admin_enqueue_scripts

  • Enqueue admin scripts/styles

  • wp_head

  • Output to <head> section

  • wp_footer

  • Output before </body>

  • save_post

  • Post is being saved

  • admin_notices

  • Display admin notices

Filters (Modify Data)

Modify values before they're used:

// Add a filter add_filter( 'the_content', 'my_content_filter' ); add_filter( 'the_title', 'my_title_filter', 10, 2 );

function my_content_filter( $content ) { // Modify and return content return $content . '<p>Added text</p>'; }

// Custom filter (for your plugin) $value = apply_filters( 'my_plugin_custom_filter', $value, $arg1, $arg2 );

Common Filter Hooks:

  • the_content

  • Post content

  • the_title

  • Post title

  • the_excerpt

  • Post excerpt

  • wp_mail

  • Email parameters

  • upload_mimes

  • Allowed upload types

  • login_redirect

  • Where to redirect after login

Priority and Arguments:

// Priority: 10 is default, lower runs earlier add_filter( 'the_title', 'my_filter', 5 ); // Runs early

// Accept multiple arguments add_filter( 'the_title', 'my_filter', 10, 2 ); function my_filter( $title, $post_id ) { return $title; }

Database Interactions (wpdb)

Use $wpdb global for database queries.

Basic Queries

global $wpdb;

// Get single value $count = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts}" );

// Get single row $post = $wpdb->get_row( "SELECT * FROM {$wpdb->posts} WHERE ID = 1" );

// Get multiple rows $posts = $wpdb->get_results( "SELECT * FROM {$wpdb->posts} WHERE post_status = 'publish'" );

// Get column $titles = $wpdb->get_col( "SELECT post_title FROM {$wpdb->posts}" );

Prepared Statements (ALWAYS)

Never use string concatenation with user input:

// WRONG - SQL Injection vulnerability $wpdb->get_results( "SELECT * FROM {$wpdb->posts} WHERE ID = {$_GET['id']}" );

// CORRECT - Prepared statement $id = absint( $_GET['id'] ); $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE ID = %d", $id ) );

// Multiple placeholders $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE post_type = %s AND post_status = %s", $post_type, $status ) );

Placeholders:

  • %s

  • String

  • %d

  • Integer

  • %f

  • Float

Insert/Update/Delete

// Insert $wpdb->insert( $wpdb->prefix . 'my_table', array( 'column1' => 'value1', 'column2' => 123 ), array( '%s', '%d' ) // Format );

// Update $wpdb->update( $wpdb->prefix . 'my_table', array( 'column1' => 'new_value' ), // Data array( 'ID' => 123 ), // Where array( '%s' ), // Data format array( '%d' ) // Where format );

// Delete $wpdb->delete( $wpdb->prefix . 'my_table', array( 'ID' => 123 ), array( '%d' ) );

Table Prefix: Always use $wpdb->prefix for custom tables

WordPress Coding Standards

Follow WordPress PHP coding standards:

Naming Conventions:

  • Functions: lowercase_with_underscores()

  • Classes: Class_Name_With_Underscores

  • Constants: UPPERCASE_WITH_UNDERSCORES

  • Files: lowercase-with-hyphens.php

Indentation: Tabs (not spaces)

Bracing:

if ( condition ) { // Code }

Spacing:

// Always space after control structures if ( condition ) { // Code }

// Space around operators $x = $y + $z;

// No space inside parentheses for function calls my_function( $arg1, $arg2 );

Yoda Conditions (constants on left):

if ( 'yes' === $value ) { // Prevents accidental assignment }

Helper Functions

Plugin paths:

plugin_dir_path( FILE ); // /path/to/wp-content/plugins/my-plugin/ plugin_dir_url( FILE ); // https://example.com/wp-content/plugins/my-plugin/ plugin_basename( FILE ); // my-plugin/my-plugin.php

Get options:

get_option( 'option_name', 'default_value' ); update_option( 'option_name', $new_value ); delete_option( 'option_name' );

Post meta:

get_post_meta( $post_id, 'meta_key', true ); // Single value update_post_meta( $post_id, 'meta_key', $value ); delete_post_meta( $post_id, 'meta_key' );

Transients (temporary cached data):

set_transient( 'my_transient', $value, 3600 ); // 1 hour $value = get_transient( 'my_transient' ); delete_transient( 'my_transient' );

Progressive Disclosure

For advanced topics, see:

  • See {baseDir}/references/security-patterns.md for advanced security patterns

  • See {baseDir}/references/hooks-api.md for comprehensive hooks reference

  • See {baseDir}/references/database-patterns.md for complex database operations

Related Skills

  • wordpress-blocks - Block development, Block Hooks API, Interactivity API

  • wordpress-modern - Performance optimization, modern WP 6.8 features

Best Practices Summary

  • Security First: Sanitize input, escape output, verify nonces, check capabilities

  • Use WordPress APIs: Don't reinvent the wheel, use built-in functions

  • Follow Standards: WordPress coding standards for consistency

  • Prepare Statements: Always use $wpdb->prepare() for queries

  • Prefix Everything: Avoid naming conflicts with unique prefixes

  • Test: Test activation, deactivation, different user roles

  • Document: Comment complex logic, use PHPDoc blocks

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

shadcn-ui

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

meilisearch

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

zod

No summary provided by upstream source.

Repository SourceNeeds Review