Phase 7 · Advanced & PortfolioModule 43~52 min read

CMS & WordPress Development

Apply professional PHP practices to themes, plugins, hooks, data APIs, security, and maintainable CMS extensions.

What you'll learn

Apply modern PHP discipline inside WordPress's hook-driven lifecycle. Build a namespaced plugin, separate registration from behavior, use core data APIs, and combine capabilities, nonces, sanitization, and contextual escaping.

By the end of this lesson, you'll be able to:

  • Structure a maintainable plugin
  • Use actions, filters, and WordPress data APIs
  • Secure admin and public extension points

Core mental model

Professional PHP is less about memorizing APIs and more about choosing a clear boundary for each responsibility. Use this table as a decision guide while reading the examples.

ConceptWhat it protectsDecision rule
ActionLifecycle side effectRegister behavior at the documented event and priority.
FilterValue transformationReturn the transformed value without unrelated side effects.
CapabilityServer-side authorizationCheck before every privileged operation, with a nonce for CSRF.

Professional workflow

Build the feature in small, verifiable steps. Each step leaves the system in a state you can test.

  1. Describe the WordPress extension boundary boundary: its inputs, outputs, invariants, and expected failures.
  2. Implement the smallest happy path behind an explicit contract.
  3. Add validation and translate low-level failures into language the caller understands.
  4. Exercise the boundary with realistic data, then inspect output, logs, and resource cleanup.
  5. Refactor only after behavior is protected by a repeatable check.

Make the boundary visible

Name inputs, outputs, side effects, and failure cases before adding framework or infrastructure code. That habit keeps advanced PHP understandable as the application grows.

Guided code lab

Bootstrap a namespaced plugin

The entry file performs WordPress registration; a service object owns the behavior.

academy-tools.php
<?php
/** Plugin Name: Academy Tools */
declare(strict_types=1);

namespace Academy\WordPress;

final class Plugin
{
    public function register(): void
    {
        add_action('init', [$this, 'registerCourseType']);
        add_filter('the_content', [$this, 'appendCourseMeta']);
    }
    public function registerCourseType(): void
    {
        register_post_type('academy_course', ['public' => true, 'show_in_rest' => true]);
    }
}

(new Plugin())->register();

Secure an admin update

Authorization, CSRF, validation, and storage escaping are separate steps.

save-settings.php
<?php
function saveSettings(): void
{
    if (!current_user_can('manage_options')) wp_die('Forbidden', status: 403);
    check_admin_referer('academy_save_settings');

    $label = sanitize_text_field(wp_unslash($_POST['course_label'] ?? ''));
    if ($label === '') add_settings_error('academy', 'label', 'Label is required.');
    else update_option('academy_course_label', $label);
}

echo esc_html((string) get_option('academy_course_label', 'Courses'));

Production practice

Contract

Keep WordPress globals and hooks in adapter code; put reusable business behavior in ordinary namespaced PHP services.

Verification

Test pure services quickly, then integration-test hooks, permissions, nonces, REST behavior, activation, and uninstall cleanup.

Operations

Declare supported WordPress/PHP versions, update dependencies, avoid slow work in frequent hooks, and provide safe migrations.

Common failure mode

A nonce proves request intent, not permission. Always pair nonce verification with a capability check on privileged actions.

Independent workshop

Create a production-ready course companion plugin with a custom post type, REST field, settings page, and enrollment report.

Your finished workshop must include:

  • Namespaced Composer structure and hook registration
  • Capabilities, nonces, sanitization, escaping, and prepared queries
  • Activation/migration/uninstall strategy and test plan

Definition of done

Run the happy path and at least two failure paths, explain one design tradeoff in a short README, and leave the code formatted and ready for review.

Recap & quick check

Key takeaways

  • Hooks integrate with the WordPress lifecycle.
  • Actions perform; filters transform.
  • Capabilities authorize and nonces reduce CSRF.
  • Contextual escaping happens at output.

Quick check

1. What must a filter callback return?

2. Does a nonce authorize an admin action?

3. Which function escapes plain HTML text?

Keep the workshop: later phases deliberately build on these boundaries, so today's small example can become part of your portfolio architecture.