Create WordPress Plugin Tutorial in 2022

Create WordPress plugin

For those who are in a hurry, I offer an empty WordPress plugin under the following button, which is also a great replacement for a functions.php.

In this tutorial we will create a WordPress plugin together. Creating a WordPress plugin is as simple as defining any unused name and details for the WordPress plugin within a PHP file located in a “zipped” folder.

That’s already all it takes to be able to activate the plugin in the backend of WordPress. The name and details are defined using the following PHP code.

<?php
 /*
 Plugin Name: WordPress Plugin
 Description: Custom Plugin
 Version: 1.0
 Author: Pascal Cabart
 Author URI: https://www.studentenwebdesign.de
 / / Start Adding Functions Below this Line */

Step by step

Create PHP file

Creating a PHP file is different for each operating system. To make it easy for us, I offer you an empty PHP file with a click on this link. All you have to do is unzip this file.

Activate WordPress plugin

Now open this PHP file with a text editor of your choice, I recommend Atom from GitHub. Copy the code from above into this file and save it. In order to make the plugin work now, we only need a folder in which we put our PHP file. Give the PHP file and the folder the same name, otherwise errors may occur.

This folder still needs to be “zipped” and that’s it. If you haven’t made it this far, I’ll provide you with the finished version so far here. Now all you have to do is upload and activate the plugin through your WordPress backend. Your plugin should now appear in your plugin directory.

Plugins VS functions.php

The plugin doesn’t do anything yet, because nothing is defined except for the name. We can now define all possible functions in this plugin and they will work exactly as if we write them in the functions.php.

Everything that is in the functions.php file could also be in a plugin and vice versa. In a way, you don’t need to set up a child theme, you could just create a new WordPress plugin in which you can house all the individual functions, which also has many advantages.

task

Our test task is now as follows: The link “older/newer posts” is displayed by default on the blog pages. The name cannot be changed via the WordPress backend, only via PHP functions.

A separate plugin should be created in which the user can insert any link text within the settings menu via the WordPress backend and this will then overwrite the “older/newer posts” link.

Techniques to be used

To create the plugin we need the following techniques:

  • Creation of individual menu entries in the WordPress backend
  • Function to save the entry in the WordPress database
  • Function to read the saved data from the WordPress database
  • the function to replace the desired text

recognize problem

WordPress plugins are often programmed in an object-oriented manner. Object-oriented programming is ideal for complex programs. In our context, however, we will program the plugin functionally. First of all, let’s write the function we need to replace the “older/newer posts” link. The appropriate function may vary from theme to theme.

In this context I will now use the Divi Theme from Elegant Themes. To create the function we need, we first need to figure out which function is returning the “older/newer posts” link. It is a good idea to check the WordPress documentation for this.

A light Google search for “next posts link wordpress” gives you an instant reference. Now you have to be careful for a moment, because there is the “next_post_link” function and the “next_posts_link” (plural) function. We need the next_posts_link function because we’re looking for the link below the blog, not the link below the posts.

Now we look in the Divi theme how this function is called. Most functions in most themes are in functions.php. However, Divi doesn’t have to adhere to WordPress best practices and has its own structure. The name of the individual PHP files already indicates where the function you are looking for might be located. Divi comes with a separate navigation.php file that houses our function we’re looking for:

<div class="pagination clearfix">
	<div class="alignleft"><?php next_posts_link(esc_html__('&laquo; Older Entries','Divi')); ?></div>
	<div class="alignright"><?php previous_posts_link(esc_html__('Next Entries &raquo;', 'Divi')); ?></div>
</div>

approach

Now there are several ways to solve our problem. You could just overwrite this navigation.php file in a child theme and the problem would have already been solved. But there is another method. To do this, we are now looking for the place where navigation.php is called.

The navigation.php is in a subfolder, so it is added by a function through the path “includes/navigation”. We must therefore look for this abbreviation. A first glance at index.php already provides the function you are looking for.

<?php
endwhile;
     if ( function_exists( 'wp_pagenavi' ) )
	wp_pagenavi();
	else
	    get_template_part( 'includes/navigation', 'index' );
        else :
	   get_template_part( 'includes/no-results', 'index' );
	endif;
?>


Solve problem: develop plugin

Here we can already see that navigation.php is only called if there is no function called wp_pagenavi. This if condition is used so that the plugin WP_Pagenavi could replace navigation.php without any problems. We don’t use the plugin now, so we can just create our own function called wp_pagenavi and replace Divi’s navigation.php with it. We can easily add this function to our plugin.

<?php
/**
* Plugin Name: Rename old/new posts
* Plugin URI: http://studentenwebdesign.de/
* Description: Plugin with Settings for renaming the old/new post link
* Version: 1.0
* Author: Pascal Cabart
* Author URI: studentenwebdesign
* License: free
*/

/**
* function to rename the "old/ new posts" Text
* uses the if-condition for an existing wp_pagenavi function (only tested with divi)
*/

function wp_pagenavi(){

}
?>

The function doesn’t do anything at the moment, but we can now simply copy Divi’s navigation.php there and then adapt it as we like. So the included navigation.php will not be called by Divi, only our code.

<?php
/**
* Plugin Name: Rename old/new posts
* Plugin URI: http://studentenwebdesign.de/
* Description: Plugin with Settings for renaming the old/new post link
* Version: 1.0
* Author: Pascal Cabart
* Author URI: studentenwebdesign
* License: free
*/

/**
* function to rename the "old/ new posts" Text
* uses the if-condition for an existing wp_pagenavi function (only tested with divi)
*/


function wp_pagenavi(){
?>
<div class="pagination clearfix">
	<div class="alignleft"><?php next_posts_link(esc_html__('&laquo; Older Entries','Divi')); ?></div>
	<div class="alignright"><?php previous_posts_link(esc_html__('Next Entries &raquo;', 'Divi')); ?></div>
</div>
<?php
}
?>

In line 21 and 22 we can already see where the “older/newer posts” text is defined. We can simply enter our own values ​​there, replacing the entire line “esc_html__(‘« Older Entries’,’Divi’)”.

translation functions

Esc_html__ is a function that returns a text to be translated. Depending on the language of the WordPress installation, the specified text will be translated into another language. There are quite a few translation functions, all taking slightly different arguments, this one now also includes the name Divi, as a translation aid.

test function

If we now replace the line “esc_html__(‘« Older Entries’,’Divi’)” with an arbitrary sentence, we can test whether our plugin works. We will now rename the link to “This is a test link” as a test.

<?php
/**
* Plugin Name: Rename old/new posts
* Plugin URI: http://studentenwebdesign.de/
* Description: Plugin with Settings for renaming the old/new post link
* Version: 1.0
* Author: Pascal Cabart
* Author URI: studentenwebdesign
* License: free
*/
 
/**
* function to rename the "old/ new posts" Text
* uses the if-condition for an existing wp_pagenavi function (only tested with divi)
*/
 
function wp_pagenavi(){
?> 

<div class="pagination clearfix">
<div class="alignleft"><?php next_posts_link('Dies ist ein Testlink'); ?></div>
<div class="alignright"><?php previous_posts_link(esc_html__('Next Entries &raquo;', 'Divi')); ?></div>
</div>
<?php
}
?>

If the plugin is now activated and contains the code, we can already see the changed link under our blog.

Create individual menu items

We now have the function we need. We could now just leave the plugin in the programmer-friendly version and change the name of the links to whatever we want. However, we want to make the plugin user-friendly and give the user the opportunity to freely choose the link name via the WordPress backend within the settings.

For this we need more information from the WordPress codex. We need the information on how to register individual menu items, how to customize the pages of those items, and then how the entered information is stored in the WordPress database.

After a short search in the WordPress codex, you can find the right reference. On the page are given 2 good examples how to accomplish our task. On the one hand, the sample code for creating individual menu items is given:

<?php
/** Step 2 (from text above). */
add_action( 'admin_menu', 'my_plugin_menu' );

/** Step 1. */
function my_plugin_menu() {
	add_options_page( 'My Plugin Options', 'My Plugin', 'manage_options', 'my-unique-identifier', 'my_plugin_options' );
}

/** Step 3. */
function my_plugin_options() {
	if ( !current_user_can( 'manage_options' ) )  {
		wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
	}
	echo '<div class="wrap">';
	echo '<p>Here is where the form would go if I actually had options.</p>';
	echo '</div>';
}
?>

On the other hand, an example of the design of the menu entry is given:

// mt_settings_page() displays the page content for the Test Settings submenu
function mt_settings_page() {

    //must check that the user has the required capability 
    if (!current_user_can('manage_options'))
    {
      wp_die( __('You do not have sufficient permissions to access this page.') );
    }

    // variables for the field and option names 
    $opt_name="mt_favorite_color";
    $hidden_field_name="mt_submit_hidden";
    $data_field_name="mt_favorite_color";

    // Read in existing option value from database
    $opt_val = get_option( $opt_name );

    // See if the user has posted us some information
    // If they did, this hidden field will be set to 'Y'
    if( isset($_POST[ $hidden_field_name ]) && $_POST[ $hidden_field_name ] == 'Y' ) {
        // Read their posted value
        $opt_val = $_POST[ $data_field_name ];

        // Save the posted value in the database
        update_option( $opt_name, $opt_val );

        // Put a "settings saved" message on the screen

?>
<div class="updated"><p><strong><?php _e('settings saved.', 'menu-test' ); ?></strong></p></div>
<?php

    }

    // Now display the settings editing screen

    echo '<div class="wrap">';

    // header

    echo "<h2>" . __( 'Menu Test Plugin Settings', 'menu-test' ) . "</h2>";

    // settings form
    
    ?>

<form name="form1" method="post" action="">
<input type="hidden" name="<?php echo $hidden_field_name; ?>" value="Y">

<p><?php _e("Favorite Color:", 'menu-test' ); ?> 
<input type="text" name="<?php echo $data_field_name; ?>" value="<?php echo $opt_val; ?>" size="20">
</p><hr />

<p class="submit">
<input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e('Save Changes') ?>" />
</p>

</form>
</div>

<?php
 
}

We now need to combine these two functions so that our menu item directly represents the example menu page. All we have to do is replace the function content of the my_plugin_options function from the penultimate code with the function content of the mt_settings_page function from the last code.

<?php
/** Step 2 (from text above). */
add_action( 'admin_menu', 'my_plugin_menu' );

/** Step 1. */
function my_plugin_menu() {
	add_options_page( 'My Plugin Options', 'My Plugin', 'manage_options', 'my-unique-identifier', 'my_plugin_options' );
}

/** Step 3. */
function my_plugin_options() {
    //must check that the user has the required capability 
    if (!current_user_can('manage_options'))
    {
      wp_die( __('You do not have sufficient permissions to access this page.') );
    }

    // variables for the field and option names 
    $opt_name="mt_favorite_color";
    $hidden_field_name="mt_submit_hidden";
    $data_field_name="mt_favorite_color";

    // Read in existing option value from database
    $opt_val = get_option( $opt_name );

    // See if the user has posted us some information
    // If they did, this hidden field will be set to 'Y'
    if( isset($_POST[ $hidden_field_name ]) && $_POST[ $hidden_field_name ] == 'Y' ) {
        // Read their posted value
        $opt_val = $_POST[ $data_field_name ];

        // Save the posted value in the database
        update_option( $opt_name, $opt_val );

        // Put a "settings saved" message on the screen

?>
<div class="updated"><p><strong><?php _e('settings saved.', 'menu-test' ); ?></strong></p></div>
<?php

    }

    // Now display the settings editing screen

    echo '<div class="wrap">';

    // header

    echo "<h2>" . __( 'Menu Test Plugin Settings', 'menu-test' ) . "</h2>";

    // settings form
    
    ?>

<form name="form1" method="post" action="">
<input type="hidden" name="<?php echo $hidden_field_name; ?>" value="Y">

<p><?php _e("Favorite Color:", 'menu-test' ); ?> 
<input type="text" name="<?php echo $data_field_name; ?>" value="<?php echo $opt_val; ?>" size="20">
</p><hr />

<p class="submit">
<input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e('Save Changes') ?>" />
</p>

</form>
</div>

<?php
}
?>

We can now simply add this code to the end of our plugin and our individual menu item with the example page will appear in the WordPress backend:

<?php
/**
* Plugin Name: Rename old/new posts
* Plugin URI: http://studentenwebdesign.de/
* Description: Plugin with Settings for renaming the old/new post link
* Version: 1.0
* Author: Pascal Cabart
* Author URI: studentenwebdesign
* License: free
*/
/**
* function to rename the "old/ new posts" Text
* uses the if-condition for an existing wp_pagenavi function (only tested with divi)
*/
function wp_pagenavi(){
?>
 
<div class="pagination clearfix">
<div class="alignleft"><?php next_posts_link('Dies ist ein Testlink'); ?></div>
<div class="alignright"><?php previous_posts_link(esc_html__('Next Entries &raquo;', 'Divi')); ?></div>
</div>
<?php
}
?>
<?php
/** Step 2 (from text above). */
add_action( 'admin_menu', 'my_plugin_menu' );
 
/** Step 1. */
function my_plugin_menu() {
add_options_page( 'My Plugin Options', 'My Plugin', 'manage_options', 'my-unique-identifier', 'my_plugin_options' );
}
 
/** Step 3. */
function my_plugin_options() {
    //must check that the user has the required capability
    if (!current_user_can('manage_options'))
    {
      wp_die( __('You do not have sufficient permissions to access this page.') );
    }
 
    // variables for the field and option names
    $opt_name="mt_favorite_color";
    $hidden_field_name="mt_submit_hidden";
    $data_field_name="mt_favorite_color";
 
    // Read in existing option value from database
    $opt_val = get_option( $opt_name );
 
    // See if the user has posted us some information
    // If they did, this hidden field will be set to 'Y'
    if( isset($_POST[ $hidden_field_name ]) && $_POST[ $hidden_field_name ] == 'Y' ) {
        // Read their posted value
        $opt_val = $_POST[ $data_field_name ];
 
        // Save the posted value in the database
        update_option( $opt_name, $opt_val );
 
        // Put a "settings saved" message on the screen
 
?>
<div class="updated"><p><strong><?php _e('settings saved.', 'menu-test' ); ?></strong></p></div>
<?php
 
    }
 
    // Now display the settings editing screen
 
    echo '<div class="wrap">';
 
    // header
 
    echo "<h2>" . __( 'Menu Test Plugin Settings', 'menu-test' ) . "</h2>";
 
    // settings form
    
    ?>
 
<form name="form1" method="post" action="">
<input type="hidden" name="<?php echo $hidden_field_name; ?>" value="Y">
 
<p><?php _e("Favorite Color:", 'menu-test' ); ?>
<input type="text" name="<?php echo $data_field_name; ?>" value="<?php echo $opt_val; ?>" size="20">
</p><hr />
 
<p class="submit">
<input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e('Save Changes') ?>" />
</p>
 
</form>
</div>
 
<?php
}
?>

You can now test the plugin and see the new menu item. We’re almost there now. We now have a plugin that changes the “older/newer posts” link, creates a custom menu item, and stores a custom variable in the WordPress database.

All we need now is a function that reads the saved text string from the database and inserts it into our function that replaces the “older/newer posts” link. To do this, we need to take a closer look at the code. The entered variable is saved in the database by the update_option function.

Now we can use the get_option function to read out the variable we are looking for. All we have to do now is call this function within the wp_pagnavi function and read our variable from the WordPress database.

We can then simply insert this variable into the function head of the next_posts_link function and the variable is output as a result. Here is our edited wp_pagenavi function:

<?php function wp_pagenavi(){

$val = get_option( mt_favorite_color );
	?>
<div class="pagination clearfix">
	<div class="alignleft"><?php next_posts_link($val);?></div>
	<div class="alignright"><?php previous_posts_link(esc_html__('%s &raquo;', 'Divi')); ?></div>
</div>
<?php
}
?>

We now simply replace this with our previous wp_pagenavi function and we have already created our first WordPress plugin. Of course, there are still a few details to work out.

At the moment you can only change one of the two links and the names of the variables, the plugin and the descriptions still have the example values ​​from the WordPress codex. I leave that task to the interested reader. Finally, our final code again:

<?php
/**
* Plugin Name: Rename old/new posts
* Plugin URI: http://studentenwebdesign.de/
* Description: Plugin with Settings for renaming the old/new post link
* Version: 1.0
* Author: Pascal Cabart
* Author URI: studentenwebdesign
* License: free
*/
/**
* function to rename the "old/ new posts" Text
* uses the if-condition for an existing wp_pagenavi function (only tested with divi)
*/

function wp_pagenavi(){

$val = get_option( mt_favorite_color );
	?>
<div class="pagination clearfix">
	<div class="alignleft"><?php next_posts_link($val);?></div>
	<div class="alignright"><?php previous_posts_link(esc_html__('%s &raquo;', 'Divi')); ?></div>
</div>
<?php
}

/** Step 2 (from text above). */
add_action( 'admin_menu', 'my_plugin_menu' );
 
/** Step 1. */
function my_plugin_menu() {
add_options_page( 'My Plugin Options', 'My Plugin', 'manage_options', 'my-unique-identifier', 'my_plugin_options' );
}
 
/** Step 3. */
function my_plugin_options() {
    //must check that the user has the required capability
    if (!current_user_can('manage_options'))
    {
      wp_die( __('You do not have sufficient permissions to access this page.') );
    }
 
    // variables for the field and option names
    $opt_name="mt_favorite_color";
    $hidden_field_name="mt_submit_hidden";
    $data_field_name="mt_favorite_color";
 
    // Read in existing option value from database
    $opt_val = get_option( $opt_name );
 
    // See if the user has posted us some information
    // If they did, this hidden field will be set to 'Y'
    if( isset($_POST[ $hidden_field_name ]) && $_POST[ $hidden_field_name ] == 'Y' ) {
        // Read their posted value
        $opt_val = $_POST[ $data_field_name ];
 
        // Save the posted value in the database
        update_option( $opt_name, $opt_val );
 
        // Put a "settings saved" message on the screen
 
?>
<div class="updated"><p><strong><?php _e('settings saved.', 'menu-test' ); ?></strong></p></div>
<?php
 
    }
 
    // Now display the settings editing screen
 
    echo '<div class="wrap">';
 
    // header
 
    echo "<h2>" . __( 'Menu Test Plugin Settings', 'menu-test' ) . "</h2>";
 
    // settings form
    
    ?>
 
<form name="form1" method="post" action="">
<input type="hidden" name="<?php echo $hidden_field_name; ?>" value="Y">
 
<p><?php _e("Favorite Color:", 'menu-test' ); ?>
<input type="text" name="<?php echo $data_field_name; ?>" value="<?php echo $opt_val; ?>" size="20">
</p><hr />
 
<p class="submit">
<input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e('Save Changes') ?>" />
</p>
 
</form>
</div>
 
<?php
}
?>

If something went wrong somewhere, here you have the final version as a real plugin. Simply upload it to the WordPress backend and define the desired link in the settings, although you now have to be careful not to install a plugin with the same name twice, as this also leads to errors. The details are still to be worked out and everything has only been tested with the Divi Theme. I hope you enjoy your new plugin!

Links used

Atom (text editor from GitHub)
WordPress Codex
Child Theme
functions.php
Create administration menus
esc_html__
update_option
get_option

Do you have any questions or suggestions? Write me a comment and I will respond to any question. If you are looking for an inexpensive web designer, you can have your homepage created with my help.