DEV Community

MD. Samrat Hossen
MD. Samrat Hossen

Posted on

Plugin Admin Menu - Developer Guide

This guide explains how the WeLabs Plugin admin menu is built with PHP and React, how settings are saved via the WordPress REST API, and how you can extend it.

Overview

  • PHP registers a top-level admin menu and submenus, and renders root containers for React.
  • React mounts on those containers to render Dashboard, Settings, Analytics, Tools, and Help.
  • REST API endpoints handle plugin settings and analytics.
  • Security relies on nonces and capability checks.

Key files

  • includes/Admin/AdminMenu.php – menu registration, enqueue assets, print HTML roots
  • includes/Admin/Settings.php – settings page and script localization
  • includes/Admin/REST/*Controller.php – REST endpoints
  • src/admin.js – bootstraps React
  • src/Components/* – React components

Highlights for Reliability

  • Menu Registration & Enqueue – Only enqueue scripts/styles on plugin pages; localize REST URL, nonce, and current page slug for consistent JS context.
  • React Bootstrapping – Check that DOM IDs printed in PHP match IDs queried in JS to avoid silent mount failures.
  • REST API Usage – Always sanitize (sanitize_text_field, absint) and check capabilities (manage_options) in controllers.
  • Build Process – Run npm run build before pushing; ensure PHP paths point to assets/build/admin/*.
  • Testing – Log REST responses, verify nonces with apiFetch.createNonceMiddleware, and test on a fresh WP install or local environment.

📄 Full Guide (.md)

`

Plugin Admin Menu – Developer Guide

This guide walks you through how the WeLabs Plugin admin menu is built with PHP and powered by React, how settings are saved via the WordPress REST API, and how to extend it.


Overview

  • PHP registers a top-level admin menu with multiple submenus and renders "root" containers for React.
  • React mounts on those root containers and renders pages (Dashboard, Settings, Analytics, Tools, Help).
  • REST API endpoints handle read/write of plugin settings and other data.
  • Security uses nonces and capability checks.

Folder highlights:

  • includes/Admin/AdminMenu.php – menu registration, enqueue assets, HTML containers
  • includes/Admin/Settings.php – classic settings page and script localization
  • includes/Admin/REST/SettingsController.php – settings REST routes (read/update)
  • includes/Admin/REST/AnalyticsController.php – analytics REST routes (demo data)
  • src/admin.js – React bootstrapping for each page
  • src/Components/* – React components

1) Register the Admin Menu in PHP

Key file: includes/Admin/AdminMenu.php

What it does:

  • Registers a top-level menu WeLabs Plugin and submenus Dashboard, Settings, Analytics, Tools, Help & Support.
  • Enqueues the compiled script/style only on these pages.
  • Localizes data (REST URL, nonce, current page) to JS.

Important parts to look at:

  • register_admin_menu() – adds menu and submenus
  • enqueue_admin_scripts( $hook ) – enqueues assets/build/admin/script.js and admin.css
  • render_*_page() – prints a wrapper with a unique root div (e.g., #welabs-plugin-dashboard)
  • get_current_page_slug() – helps JS know which submenu is active

Extending:

  • Add another submenu with add_submenu_page( 'welabs-plugin', 'Title', 'Menu', 'manage_options', 'welabs-plugin-new', [ $this, 'render_new_page' ] );
  • Add a matching render_new_page() method that outputs a unique root container div for React.

2) Enqueue and Localize Admin Assets

Key files:

  • includes/Admin/AdminMenu.php (WeLabs menu pages)
  • includes/Admin/Settings.php (classic settings page)

Both enqueue the admin script built to assets/build/admin/script.js and localize:

  • apiUrl or apiRoot – REST base URL
  • nonce – used to authenticate REST requests
  • currentPage – helps JS know which page it's on

Security note:

  • Nonce is created with wp_create_nonce( 'wp_rest' ) and used in JS via @wordpress/api-fetch nonce middleware.

3) React Bootstrapping

Key file: src/admin.js

What it does:

  • Configures apiFetch to use the localized REST nonce and root URL:

`js
import apiFetch from '@wordpress/api-fetch';

if ( window.welabsSettings ) {
apiFetch.use( apiFetch.createNonceMiddleware( window.welabsSettings.nonce ) );
apiFetch.use( apiFetch.createRootURLMiddleware( window.welabsSettings.apiRoot ) );
}
`

  • Mounts React apps to DOM nodes printed by PHP:

`js
const dashboardContainer = document.getElementById( 'welabs-plugin-dashboard' );
if ( dashboardContainer ) { /* render */ }

const settingsContainer = document.getElementById( 'CustomizedPluginWithReactSettings' );
if ( settingsContainer ) { /* render with routes */ }
`

Extending:

  • Create a new component under src/Components/ and mount it to a new root div you print in PHP.

4) Settings REST API (Read/Write)

Key file: includes/Admin/REST/SettingsController.php

Routes:

  • GET /customized-plugin-with-react/v1/settings – fetch current settings
  • POST /customized-plugin-with-react/v1/settings – update settings

Security:

  • Capability check via current_user_can( 'manage_options' )
  • Input sanitized with sanitize_text_field()

Example React usage (simplified):

`js
import apiFetch from '@wordpress/api-fetch';

// Read settings
const settings = await apiFetch( { path: '/customized-plugin-with-react/v1/settings' } );

// Write settings
await apiFetch( {
path: '/customized-plugin-with-react/v1/settings',
method: 'POST',
data: {
customized_plugin_with_react_page_title: 'My Title',
customized_plugin_with_react_product_per_page: '12',
},
} );
`


5) Additional REST (Analytics)

Key file: includes/Admin/REST/AnalyticsController.php

Demo route:

  • GET /customized-plugin-with-react/v1/analytics?time_range=7|30|90|365

How to add your own:

  1. Create a new controller in includes/Admin/REST/ following the WP_REST_Controller pattern.
  2. Register endpoints in register_routes().
  3. Initialize the controller in includes/CustomizedPluginWithReact.phpinit_classes() and register in register_rest_route().

6) Security Checklist

  • Always check capabilities (current_user_can( 'manage_options' )) for admin actions.
  • Use nonces for REST (wp_create_nonce( 'wp_rest' ) + apiFetch.createNonceMiddleware).
  • Sanitize all incoming data (sanitize_text_field(), absint(), etc.).
  • Escape output in PHP (esc_html__, esc_attr, esc_url).

7) Build & Assets

Build command (runs @wordpress/scripts):

bash
npm run build

What it produces:

  • JS: assets/build/admin/script.js
  • CSS: assets/build/admin.css
  • Asset manifest: assets/build/admin/script.asset.php

Ensure PHP points to these files when enqueuing.


8) Common Pitfalls & Fixes

  • "Class not found" – Confirm PSR-4 autoload and namespaces match composer.json and file paths.
  • React not mounting – Verify the root div IDs printed in PHP match document.getElementById(...) in src/admin.js.
  • 401/403 on REST – Ensure nonce is localized and apiFetch nonce middleware is configured; confirm you are logged in and have manage_options capability.
  • Assets not loading – Run npm run build and confirm assets/build/* exists; verify enqueue paths.

9) How to Add a New Submenu + React Page (Quick Recipe)

1) PHP – Add submenu and render method in AdminMenu.php:

`php
add_submenu_page(
'welabs-plugin',
_( 'My Page', 'customized-plugin-with-react' ),
_
( 'My Page', 'customized-plugin-with-react' ),
'manage_options',
'welabs-plugin-my-page',
[ $this, 'render_my_page' ]
);

public function render_my_page() {
?>


<?php esc_html_e( 'My Page', 'customized-plugin-with-react' ); ?>




<?php
}
`

2) React – Create src/Components/MyPage.js and mount it in src/admin.js:

`js
import MyPage from './Components/MyPage';

const myPageContainer = document.getElementById( 'welabs-plugin-my-page' );
if ( myPageContainer ) {
const root = createRoot( myPageContainer );
root.render( );
}
`

3) Build assets and test:

bash
npm run build

That's it! You now have a new submenu powered by React with REST-ready plumbing.
`

Top comments (0)