Wednesday, November 12, 2025

Welcome to RMC online Tutorials

WordPress Plugin Development – Full Course Index

WordPress Plugin Development
12-Module Learning Portal

#12 🧩 Module 12 – Plugin Security, Performance & Best Practices

Module 12 – Plugin Security, Performance & Best Practices

🧩 Module 12 – Plugin Security, Performance & Best Practices

In this final module, you’ll learn how to keep your WordPress plugin secure, fast, and reliable. We’ll cover sanitization, escaping, nonces, database safety, and performance tips.


Step 1 – Sanitize User Input

Always clean any data from users before saving to the database or displaying on screen.

$user_input = $_POST['username'] ?? ''; $clean_input = sanitize_text_field( $user_input ); // Example: Save safely update_option( 'mfp_username', $clean_input );

Step 2 – Escape Output

When printing values on a page, escape them to prevent XSS (Cross-Site Scripting).

$name = get_option('mfp_username'); echo '<h3>Hello, ' . esc_html( $name ) . '!</h3>';

Step 3 – Use Nonces for Form Security

Nonces ensure only valid requests modify data.

<form method="post"> <?php wp_nonce_field( 'mfp_save_data', 'mfp_nonce' ); ?> <input type="text" name="username"> <input type="submit" value="Save"> </form> <?php if ( isset($_POST['mfp_nonce']) && wp_verify_nonce($_POST['mfp_nonce'], 'mfp_save_data') ) { $username = sanitize_text_field($_POST['username']); update_option('mfp_username', $username); echo '<p style="color:#00ffa3">Saved!</p>'; } ?>

Step 4 – Use Prepared Statements for SQL

Avoid building SQL queries with string concatenation — use the $wpdb->prepare() method.

global $wpdb; $username = 'admin'; $results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->users} WHERE user_login = %s", $username ) );

Step 5 – Performance Tips

  • ✅ Use transients to cache data from APIs or heavy DB queries.
  • ✅ Load scripts only when necessary using admin_enqueue_scripts conditions.
  • ✅ Use filemtime() for cache-busting only when scripts truly change.
  • ✅ Avoid loading large CSS/JS on pages where your plugin isn’t used.
// Example: conditional script load function myplugin_enqueue_scripts($hook) { if ( $hook !== 'toplevel_page_myplugin' ) return; wp_enqueue_script( 'myplugin-admin', plugin_dir_url(__FILE__) . 'admin.js', array('jquery'), filemtime(__FILE__), true ); } add_action('admin_enqueue_scripts', 'myplugin_enqueue_scripts');

Step 6 – Follow Coding Standards

  • Use snake_case for functions and variables.
  • Prefix everything (e.g., mfp_) to avoid name collisions.
  • Document your code with clear comments.
  • Validate your plugin with the WordPress Plugin Check tool.

Step 7 – Prepare for Distribution

  • Add readme.txt with description, version, author, and license.
  • Use proper folder structure (includes/, assets/, etc.).
  • Provide translation support with load_plugin_textdomain().
  • Keep plugin lightweight – load only what’s needed.

🎯 Wrap-Up

Congratulations! You’ve now built a full-featured WordPress plugin suite — from login systems, AJAX, REST API, Gutenberg blocks, widgets, to now secure and performant production-ready plugins.

✔ Next Steps: publish your plugin to WordPress.org or your own GitHub repository!

#11 Module 11 – Custom Widgets & Sidebars Integration next, using the same glowing interactive format

Module 11 – Custom Widgets & Sidebars Integration

🧩 Module 11 – Custom Widgets & Sidebars Integration

In this module, we’ll create a custom widget that displays a personalized message, and we’ll register a new sidebar where this widget can be placed.


Step 1 — Create the Plugin File

Create a new folder: my-custom-widget Then inside, create my-custom-widget.php:

<?php /** * Plugin Name: My Custom Widget * Description: Adds a simple custom widget and a sidebar to WordPress. * Version: 1.0 * Author: Your Name */ if ( ! defined( 'ABSPATH' ) ) exit; class My_Custom_Widget extends WP_Widget { function __construct() { parent::__construct( 'my_custom_widget', __( 'My Custom Widget', 'text_domain' ), array( 'description' => __( 'Displays a custom message', 'text_domain' ) ) ); } // Widget front-end display public function widget( $args, $instance ) { echo $args['before_widget']; echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title']; echo '<p style="color:#00ffa3;">' . esc_html( $instance['message'] ) . '</p>'; echo $args['after_widget']; } // Widget backend form public function form( $instance ) { $title = !empty( $instance['title'] ) ? $instance['title'] : __( 'My Widget', 'text_domain' ); $message = !empty( $instance['message'] ) ? $instance['message'] : __( 'Hello, World!', 'text_domain' ); ?> <p> <label>Title:</label> <input class="widefat" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" /> </p> <p> <label>Message:</label> <input class="widefat" name="<?php echo $this->get_field_name('message'); ?>" type="text" value="<?php echo esc_attr( $message ); ?>" /> </p> <?php } // Save widget form values public function update( $new_instance, $old_instance ) { $instance = array(); $instance['title'] = sanitize_text_field( $new_instance['title'] ); $instance['message'] = sanitize_text_field( $new_instance['message'] ); return $instance; } } // Register the widget function register_my_custom_widget() { register_widget( 'My_Custom_Widget' ); } add_action( 'widgets_init', 'register_my_custom_widget' ); // Register a custom sidebar function my_custom_sidebar() { register_sidebar( array( 'name' => __( 'Custom Sidebar', 'text_domain' ), 'id' => 'custom_sidebar', 'before_widget' => '<div class="widget-container">', 'after_widget' => '</div>', 'before_title' => '<h3 class="widget-title">', 'after_title' => '</h3>', ) ); } add_action( 'widgets_init', 'my_custom_sidebar' ); ?>

Step 2 — Activate and Test

  1. Place the folder my-custom-widget inside wp-content/plugins/.
  2. Go to Plugins → Activate "My Custom Widget".
  3. Go to Appearance → Widgets (or the block-based widget editor in newer WP).
  4. Find “My Custom Widget” and drag it into “Custom Sidebar.”
  5. Set your custom title and message, then save.
  6. To display sidebar in your theme, add this to sidebar.php or similar:
<?php if ( is_active_sidebar( 'custom_sidebar' ) ) : ?> <aside id="secondary"> <?php dynamic_sidebar( 'custom_sidebar' ); ?> </aside> <?php endif; ?>

✅ Output

When placed in the sidebar, your widget will show:

  • Widget Title (editable from admin)
  • Custom message (editable)
  • Styled automatically by your theme

💡 Notes

  • Widgets are great for dynamic content areas (sidebars, footers, etc.).
  • You can register multiple widgets using the same structure.
  • Widgets can include forms, data from APIs, or even shortcodes.

#10 Module 10 Implentation Steps

 Nice — here’s a clear, practical, step-by-step implementation for Module 10 — Creating Gutenberg (Block Editor) Blocks. I give a no-build approach (works immediately — no npm or build tools) plus an optional modern build path (recommended for production). Follow the steps exactly and you’ll have a working “Hello Block” in the editor.


Quick summary (what you’ll create)

Folder: my-block-plugin/
Files:

  • my-block-plugin.php — plugin bootstrap (registers scripts & block)

  • block/index.js — block editor script (no-build version)

  • block/editor.css — styles for the editor

  • block/style.css — front-end styles


❗ Prerequisites

  • WordPress site with admin access

  • PHP & WP (no extra tooling required for the no-build version)

  • If you want the modern build path: Node.js + npm (optional)


STEP-BY-STEP — No-build approach (fastest)

1) Create plugin folder

Path:

wp-content/plugins/my-block-plugin/

2) Create my-block-plugin.php

File: wp-content/plugins/my-block-plugin/my-block-plugin.php
Paste this full code:

<?php
/**
 * Plugin Name: My Gutenberg Block
 * Description: Adds a simple "Hello Block" (no-build example).
 * Version: 1.0
 * Author: Your Name
 */

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

function mgb_register_block() {
    // register editor script (no build - using WordPress provided globals)
    wp_register_script(
        'mgb-block-js',
        plugins_url( 'block/index.js', __FILE__ ),
        array( 'wp-blocks', 'wp-element', 'wp-editor' ), // dependencies
        filemtime( plugin_dir_path( __FILE__ ) . 'block/index.js' )
    );

    wp_register_style(
        'mgb-block-editor-style',
        plugins_url( 'block/editor.css', __FILE__ ),
        array(),
        filemtime( plugin_dir_path( __FILE__ ) . 'block/editor.css' )
    );

    wp_register_style(
        'mgb-block-style',
        plugins_url( 'block/style.css', __FILE__ ),
        array(),
        filemtime( plugin_dir_path( __FILE__ ) . 'block/style.css' )
    );

    register_block_type( 'mgb/hello-block', array(
        'editor_script' => 'mgb-block-js',
        'editor_style'  => 'mgb-block-editor-style',
        'style'         => 'mgb-block-style',
    ) );
}
add_action( 'init', 'mgb_register_block' );

Explanation: this registers the JS and CSS, and declares the block type mgb/hello-block. filemtime() forces browsers to reload when you change files.


3) Create block/index.js (no-build, uses wp.* globals)

File: wp-content/plugins/my-block-plugin/block/index.js
Paste:

( function ( wp ) {
    const el = wp.element.createElement;
    const registerBlockType = wp.blocks.registerBlockType;
    const { RichText } = wp.blockEditor || wp.editor; // compatibility

    registerBlockType( 'mgb/hello-block', {
        title: 'Hello Block',
        icon: 'smiley',
        category: 'widgets',
        attributes: {
            content: {
                type: 'string',
                source: 'html',
                selector: 'p'
            }
        },
        edit: function ( props ) {
            const content = props.attributes.content;
            return el(
                'div',
                { className: 'mgb-hello-block' },
                el( RichText, {
                    tagName: 'p',
                    onChange: function ( value ) { props.setAttributes( { content: value } ); },
                    value: content,
                    placeholder: 'Say hello... 👋'
                } )
            );
        },
        save: function ( props ) {
            return el( wp.blockEditor.RichText.Content || wp.RichText.Content, {
                tagName: 'p',
                value: props.attributes.content
            } );
        }
    } );
} )( window.wp );

Notes:

  • This file uses WordPress global wp object — no bundler needed.

  • Compatible with many WP versions by checking blockEditor vs editor.


4) Create editor & front-end CSS

block/editor.css (editor view styling):

.mgb-hello-block {
  background: #002b36;
  border-radius: 10px;
  padding: 10px;
  color: #00ffa3;
}

block/style.css (front-end styling):

.mgb-hello-block p {
  font-size: 18px;
  color: #00d4ff;
  margin: 0;
}

5) Activate plugin & test

  1. Zip or copy folder to wp-content/plugins/ (already done).

  2. In WP Admin: Plugins → Activate “My Gutenberg Block”.

  3. Edit or create a post: Add block → search “Hello Block” (category: Widgets).

  4. Type text in the block, save/update post, view on front-end.

If block does not appear: flush caches, ensure WP version >= 5.x (Gutenberg built-in).


Troubleshooting (no-build)

  • If block fails to load, open browser console — missing wp globals indicate block script loaded on front-end instead of editor. Ensure editor_script is registered — you used register_block_type() correctly.

  • If icons or editor UI missing, check dependencies: 'wp-blocks','wp-element','wp-editor'. For newer WP, consider 'wp-block-editor' too.

  • If CSS not loading: check file paths and permissions.


OPTIONAL: Modern build path (recommended for production)

If you want JSX, ESNext, and modules — use @wordpress/scripts. Short steps:

  1. cd my-block-plugin/block

  2. npm init -y

  3. npm install @wordpress/scripts --save-dev

  4. Create src/index.js (JSX) and build/index.js generated by the tool.

  5. Add package.json scripts:

"scripts": {
  "build": "wp-scripts build",
  "start": "wp-scripts start"
}
  1. Example src/index.js (JSX version):

import { registerBlockType } from '@wordpress/blocks';
import { RichText } from '@wordpress/block-editor';
import { createElement } from '@wordpress/element';

registerBlockType('mgb/hello-block', {
  title: 'Hello Block',
  icon: 'smiley',
  category: 'widgets',
  attributes: {
    content: { type: 'string', source: 'html', selector: 'p' }
  },
  edit: ({ attributes, setAttributes }) => (
    createElement('div', { className: 'mgb-hello-block' },
      createElement(RichText, {
        tagName: 'p',
        onChange: value => setAttributes({ content: value }),
        value: attributes.content,
        placeholder: 'Say hello... 👋'
      })
    )
  ),
  save: ({ attributes }) => (
    createElement(RichText.Content, {
      tagName: 'p',
      value: attributes.content
    })
  )
});
  1. Run npm run build → this produces build/index.js. Update PHP to point to block/build/index.js instead of block/index.js.

Advantages: cleaner code, JSX, compatibility with future WP patterns.


Extra tips & best practices

  • Use editor_style and style keys in register_block_type() to keep editor and front-end styles separate.

  • Use attributes carefully — define types and sources to keep data serializable.

  • For complex blocks, use InspectorControls to add sidebar controls.

  • For localization, wrap strings with __() and load textdomain in PHP if you plan to translate.


Quick checklist before testing

  • Files in correct places

  • Plugin activated

  • Browser console clear of errors

  • WP version supports block editor

  • Clear caches if styles or scripts don’t update


If you want, I can:

  • Generate the exact plugin ZIP you can download and install, or

  • Convert the no-build JS to a modern @wordpress/scripts project with package.json and full src/ build files ready to npm install + npm run build.

Which next?

#10 Module 10 – Creating Gutenberg (Block Editor) Blocks for Your Plugin

Module 10 – Gutenberg Blocks for Your Plugin | WordPress Plugin Development

🧱 Module 10: Creating Gutenberg Blocks for Your Plugin

Gutenberg (the Block Editor) allows you to add **custom content blocks** visually in WordPress posts and pages. In this module, we’ll build a **“Hello Block”** that you can insert directly into the editor — all powered by your plugin.

Step 1 – Folder Setup

Create a new folder inside your plugin:

my-block-plugin/ │ ├── my-block-plugin.php └── block/ ├── index.js ├── editor.css └── style.css

These files handle the PHP registration, block editor JavaScript, and styles.

Step 2 – Register the Block Script in PHP

'mgb-block-js', 'style' => 'mgb-block-style', )); } add_action('init', 'mgb_register_block'); ?>

📘 This registers your JS and declares the block type mgb/hello-block.

Step 3 – Create the Block JavaScript (index.js)

const { registerBlockType } = wp.blocks; const { RichText } = wp.blockEditor; registerBlockType('mgb/hello-block', { title: 'Hello Block', icon: 'smiley', category: 'widgets', attributes: { content: { type: 'string', source: 'html', selector: 'p' } }, edit: (props) => { const { attributes: { content }, setAttributes } = props; return ( wp.element.createElement( 'div', { className: 'mgb-hello-block' }, wp.element.createElement(RichText, { tagName: 'p', onChange: (value) => setAttributes({ content: value }), value: content, placeholder: 'Say hello... 👋' }) ) ); }, save: (props) => { return wp.element.createElement(RichText.Content, { tagName: 'p', value: props.attributes.content }); } });

📘 You now have a block that lets users type text and see it saved to the post!

Step 4 – Add Simple Styles

editor.css (for the block editor):

.mgb-hello-block { background: #002b36; border-radius: 10px; padding: 10px; color: #00ffa3; }

style.css (front-end):

.mgb-hello-block p { font-size: 18px; color: #00d4ff; }

Step 5 – Test the Block

  1. Go to Plugins → Activate “My Gutenberg Block”.
  2. Open the block editor for any post/page.
  3. Click ➕ → Search “Hello Block”.
  4. Type your text → Update the page → View it live.

✅ You’ve built a working custom Gutenberg block!

Bonus – Register Multiple Blocks

You can register more by repeating registerBlockType() in index.js with different names.

✅ Code copied!
© 2025 WordPress Plugin Tutorial | Module 10 – Gutenberg Blocks

#9 Module 9 Implementaion Steps

 Absolutely 👍 — here’s a clear, practical step-by-step guide to implement everything from Module 9 – Using the REST API & Fetch Requests, directly in your WordPress plugin.

You can follow this in your existing plugin folder (like my-first-plugin) or a new one such as mfp-rest-api.


Module 9 — REST API & Fetch Requests Implementation Steps

🧩 Goal:

You’ll learn to:

  • Create custom REST API endpoints (GET & POST)

  • Fetch data dynamically with JavaScript (fetch())

  • Send form data to your WordPress backend via REST API


Step 1: Create or Open Your Plugin File

Go to:
/wp-content/plugins/mfp-rest-api/mfp-rest-api.php

Paste the following header:

<?php
/*
Plugin Name: MFP REST API Example
Description: A simple example of custom REST API + Fetch integration.
Version: 1.0
Author: Your Name
*/

Step 2: Register a REST API GET Endpoint

Add this code to the same file:

function mfp_register_rest_endpoint() {
    register_rest_route('mfp/v1', '/message', array(
        'methods' => 'GET',
        'callback' => 'mfp_get_message'
    ));
}
add_action('rest_api_init', 'mfp_register_rest_endpoint');

function mfp_get_message() {
    return array('message' => 'Hello from the REST API 🚀');
}

🔍 Test it:

  1. Activate your plugin in WordPress → Plugins.

  2. Visit this URL in your browser:

    https://your-site.com/wp-json/mfp/v1/message
    
  3. You’ll see:

    {"message": "Hello from the REST API 🚀"}
    

Step 3: Create a Shortcode to Display API Data on Front-End

Now we’ll create a shortcode that fetches the above data dynamically.

function mfp_fetch_example_shortcode() {
    ob_start(); ?>
    <div id="mfp-api-output" style="color:#00ffa3;">Loading message...</div>
    <script>
        fetch('<?php echo site_url('/wp-json/mfp/v1/message'); ?>')
            .then(response => response.json())
            .then(data => {
                document.getElementById('mfp-api-output').innerHTML =
                    '<strong>API Says:</strong> ' + data.message;
            })
            .catch(error => {
                document.getElementById('mfp-api-output').innerHTML = 'Error loading API data 😢';
            });
    </script>
    <?php
    return ob_get_clean();
}
add_shortcode('mfp_api_demo', 'mfp_fetch_example_shortcode');

🔍 Test it:

Add this shortcode in any page or post:

[mfp_api_demo]

You’ll see live data from your REST API displayed on the front-end.


Step 4: Create a REST API POST Endpoint

Now, let’s make an endpoint that accepts user data.

function mfp_register_post_endpoint() {
    register_rest_route('mfp/v1', '/submit', array(
        'methods' => 'POST',
        'callback' => 'mfp_submit_data'
    ));
}
add_action('rest_api_init', 'mfp_register_post_endpoint');

function mfp_submit_data($data) {
    $params = $data->get_json_params();
    $name = sanitize_text_field($params['name']);
    return array('response' => 'Hi ' . $name . ', your data was received ✅');
}

🔍 Test it (manually with cURL or Postman):

POST to:

https://your-site.com/wp-json/mfp/v1/submit

Body (JSON):

{ "name": "Ravi" }

You should get:

{ "response": "Hi Ravi, your data was received ✅" }

Step 5: Front-End Form to Submit Data via Fetch

Now add this shortcode:

function mfp_api_post_form_shortcode() {
    ob_start(); ?>
    <form id="mfp-post-form">
        <label>Your Name:</label><br>
        <input type="text" id="mfp_name" required><br><br>
        <button type="submit">Send via REST API</button>
    </form>
    <div id="mfp_result" style="color:#00ffa3;margin-top:10px;"></div>

    <script>
    document.getElementById('mfp-post-form').addEventListener('submit', function(e) {
        e.preventDefault();
        const name = document.getElementById('mfp_name').value;

        fetch('<?php echo site_url('/wp-json/mfp/v1/submit'); ?>', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({ name: name })
        })
        .then(response => response.json())
        .then(data => {
            document.getElementById('mfp_result').innerHTML = data.response;
        })
        .catch(err => {
            document.getElementById('mfp_result').innerHTML = '❌ Error sending data.';
        });
    });
    </script>
    <?php
    return ob_get_clean();
}
add_shortcode('mfp_api_form', 'mfp_api_post_form_shortcode');

🔍 Test it:

Add this shortcode to any WordPress page:

[mfp_api_form]

Type your name → click “Send via REST API”
✅ It will instantly show your personalized response from the API.


Step 6: Secure Your Endpoints (Optional)

To restrict access to logged-in users only, modify the route like:

register_rest_route('mfp/v1', '/submit', array(
    'methods' => 'POST',
    'callback' => 'mfp_submit_data',
    'permission_callback' => function() {
        return is_user_logged_in();
    }
));

🧠 Concepts You’ve Learned

Concept Description
register_rest_route() Create custom API endpoints
wp-json/ Default REST API base URL
fetch() JavaScript method to call APIs
sanitize_text_field() Clean user input
add_shortcode() Display dynamic API data on front-end
POST vs GET Sending vs retrieving data

💡 Use Cases

  • Build dynamic dashboards

  • Create single-page plugin interfaces

  • Build React/Vue front-ends powered by WordPress

  • Send or receive data from mobile apps


Would you like me to continue with Module 10 – Creating Gutenberg (Block Editor) Blocks for Your Plugin next, in the same glowing interactive HTML format?

#9 Module 9 – Using the REST API & Fetch Requests

Module 9 – Using the REST API & Fetch Requests | WordPress Plugin Tutorial

🌐 Module 9: Using the REST API & Fetch Requests

The WordPress REST API lets you send and receive data via HTTP — perfect for dynamic front-end interactions without reloading the page. In this module, you’ll create a custom REST API endpoint and connect it to JavaScript using the fetch() API.

Step 1 – Register a Custom REST API Endpoint

(📋 You can copy or edit directly below)

    
function mfp_register_rest_endpoint() { register_rest_route('mfp/v1', '/message', array( 'methods' => 'GET', 'callback' => 'mfp_get_message' )); } add_action('rest_api_init', 'mfp_register_rest_endpoint'); function mfp_get_message($data) { return array('message' => 'Hello from the REST API 🚀'); }

📘 This registers a new API endpoint at https://yourwebsite.com/wp-json/mfp/v1/message Visit it in your browser to see the JSON response.

Step 2 – Create a Front-End Shortcode with JavaScript Fetch

    
function mfp_fetch_example_shortcode() { ob_start(); ?> <div id="mfp-api-output" style="padding:10px;color:#00ffa3;"> Loading message... </div> <script> fetch('') .then(response => response.json()) .then(data => { document.getElementById('mfp-api-output').innerHTML = '<strong>API Says:</strong> ' + data.message; }) .catch(error => { document.getElementById('mfp-api-output').innerHTML = 'Error loading API data 😢'; console.error(error); }); </script> <?php return ob_get_clean(); } add_shortcode('mfp_api_demo', 'mfp_fetch_example_shortcode');

📘 Use the shortcode [mfp_api_demo] in a page or post to see your REST API data displayed live via JavaScript.

Step 3 – Add a POST Endpoint (Send Data from JS)

    
function mfp_register_post_endpoint() { register_rest_route('mfp/v1', '/submit', array( 'methods' => 'POST', 'callback' => 'mfp_submit_data' )); } add_action('rest_api_init', 'mfp_register_post_endpoint'); function mfp_submit_data($data) { $params = $data->get_json_params(); $name = sanitize_text_field($params['name']); return array('response' => 'Hi ' . $name . ', your data was received ✅'); }

📘 Now you can POST data to /wp-json/mfp/v1/submit and get a JSON response!

Step 4 – Connect Front-End Form to the POST API

    
function mfp_api_post_form_shortcode() { ob_start(); ?> <form id="mfp-post-form"> <label>Your Name:</label><br> <input type="text" id="mfp_name" required /><br><br> <button type="submit">Send via REST API</button> </form> <div id="mfp_result" style="color:#00ffa3;margin-top:10px;"></div> <script> document.getElementById('mfp-post-form').addEventListener('submit', function(e) { e.preventDefault(); const name = document.getElementById('mfp_name').value; fetch('', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ name: name }) }) .then(response => response.json()) .then(data => { document.getElementById('mfp_result').innerHTML = data.response; }) .catch(err => { document.getElementById('mfp_result').innerHTML = '❌ Error sending data.'; console.error(err); }); }); </script> <?php return ob_get_clean(); } add_shortcode('mfp_api_form', 'mfp_api_post_form_shortcode');

📘 Use [mfp_api_form] in a page — it sends data to the REST API and displays the result instantly.

✅ Code copied to clipboard!
© 2025 WordPress Plugin Tutorial | Module 9 – Using the REST API & Fetch Requests

Welcome to RMC online Tutorials

WordPress Plugin Development – Full Course Index WordPress Plugin Development 12-Module Learning Portal Mod...