How to create a custom WordPress plugin from scratch


During the past week I was thinking about a new tutorial on how to create a custom WordPress plugin from scratch. The task is not that hard to be done, especially when you have a good idea how WordPress works and what is its files structure.

The following will be a detailed tutorial for custom WordPress plugin creation. I will provide step by step instructions on how to start developing a simple plugin. For better understanding I will add a little piece of code that will query the database and generate backups.

Let’s start from the point that you have default WordPress installation. What you have to is login to its admin panel and navigate to plugins page. If no new plugin are installed so  far you would see the following on your screen:

WordPress plugins page

WordPress plugins page

These are the plugins that come by default. At this point you are on plugins page and this is the place where our plugin will appear soon. Here is what to do next:

Using FTP client you should access the root folder of your WordPress instance and then open wp-content folder. Inside it you will see plugins folder, open it and create new one named dbmechanic. The name can be of course changed. If you refresh plugin page you will see no change. This is because we create the folder of our plugin, but there is no code to trigger WordPress hooks.

As a next step, we have to create a new file that will contain the code of our future plugin. The file name could be dbmechanic.php.

Again WordPress plugin page does not show any signs about a new plugin because we have a folder and main file, but there is no code. So now we have to open dbmechanic.php and add the following header to it:

<?php
/*
Plugin Name: Simple database mechanic
Plugin URI: http://wppotion.com/
Description: A simple database mechanic plugin
Version: 1.0
Author: Leonid G.
Author URI: http://wppotion.com/
License: GPL
*/
?>

 

Now go back to plugins page and refresh it. If everything is fine, you will see our custom plugin in the list.

Custom WordPress plugin

Custom WordPress plugin

As you can see the information from the headers corresponds correctly with WordPress hooks and the name, version, URI and author are displayed as expected on the page.

We have now the basic file and we can proceed and add some options to it. As adding the code piece by piece may break it and generate fatal errors I will paste the entire code and then explain the lines:

<?php
/*
Plugin Name: Simple database mechanic
Plugin URI: http:// wppotion.com/
Description: A simple database mechanic plugin
Version: 1.0
Author: Leonid G.
Author URI: http://wppotion.com/
License: GPL
*/
add_action('admin_menu', 'dbmechanic_admin_actions');
/*
Here we use admin_menu hook and a functions that contains instructions to add a submenu to the general Settings page
*/
function dbmechanic_admin_actions()
{
add_options_page('DBmechanic', 'DB-mechanic', 'manage_options','__FILE__', 'mechanic_admin');
}
/*
As you can see add_options_page takes 5 arguments which define the title of the page, the name of the submenu, 'manage_options' defines who can control the submenu, the next one is the menu slug, mechanic_admin is the function that will display the plugin page.
*/
function mechanic_admin ()
{
/*
Now we will develop the function itself. As you can see there is no closing tag, because we will put some PHP and HTML inside it and the closing tag will be placed in the end.
*/
?>
<!--
Here we close PHP Tag, because what comes next is pure HTML code which should not be messed up with PHP
-->
<div class="wrap">
<h4> Database details: </h4>
<?php
echo "Database ";
echo "&nbsp; &nbsp; &nbsp;".DB_NAME;
echo "<br />";
echo "Mysql user ";
echo "&nbsp;".DB_USER;
echo "<br />";
echo "Password";
echo "&nbsp; &nbsp; &nbsp;".DB_PASSWORD;
echo "<br />";
echo "Hostname";
echo "&nbsp; &nbsp; &nbsp;".DB_HOST;
?>
<!--
Using a little PHP snippet we extract WordPress Mysql details. We do this just to show how the code interacts with wpdb object.
-->
<hr />
<form action="" method="POST" >
<input type="submit" name="database_check" value="Database Check" class="button-primary" />
</form>
<!--
This is form button that works using POST. We also use class that is defined by WordPress as button-primary
-->
<?php
global $wpdb;
if(isset($_POST['database_check']))
{
$AllRecordsCheck = $wpdb->query(
"
SELECT *
FROM $wpdb->options;
"
);
echo "<hr />";
echo 'All records in options table - '.$wpdb->num_rows ;
echo "<hr />";
/*
This code queries wpdb object and extracts and counts the number of rows in options table
*/
$TrRecordsCheck = $wpdb->query(
"
SELECT *
FROM $wpdb->options
WHERE option_name LIKE '\_transient\_feed\_%'
OR option_name LIKE '\_transient\_timeout\_feed\_%'
OR option_name LIKE '\_site\_transient\_timeout\_browser\_%'
OR option_name LIKE '\_transient\_dash\_%'
OR option_name LIKE '\_site\_transient\_browser\_%'
"
);
echo 'Transient rows ( not needed ) - '.$wpdb->num_rows;
/*
Here we extract the rows that contains transient or its variations in the names
*/
echo "<hr />";
$reduction = ($TrRecordsCheck / $AllRecordsCheck )*100;
$rounded = round($reduction, 2);
echo "Possible reduction - approximately <b>$rounded %</b>";
}
/*
Here we calculate the possible reduction and print the percentage.
*/
echo "<hr />";
?>
<form action="" method="POST" >
<input type="submit" name="database_backup" value="Database Backup" class="button-primary" />
</form>
<?php
$dir = plugin_dir_path( __FILE__ );
$url = plugin_dir_url( __FILE__ );
if(isset($_POST['database_backup']))
{
$backupFile = "$dir/backup_db/".DB_NAME."-".date("Y-m-d-H-i-s").".sql.gz";
$exp = "mysqldump --opt -u ".DB_USER." -p'".DB_PASSWORD."' -h ".DB_HOST."  ".DB_NAME." | gzip -9 -c > $backupFile";
system($exp);
echo " </br >Backup generated</br >";
echo "</br >Phisical location of the file <b>$backupFile</b></br >";
}
?>
<!--
This portion here generates a backup button and give instructions on how and where the backup to be generated and kept.
-->
<hr />
<form action="" method="POST" >
<input type="submit" name="database_optimize" value="Database Optimize" class="button-primary" />
</form>
<?php
if(isset($_POST['database_optimize']))
{
$TrRecordsDrop = $wpdb->query(
"
DELETE
FROM $wpdb->options
WHERE option_name LIKE '_transient_feed_%'
OR option_name LIKE '\_transient\_timeout\_feed\_%'
OR option_name LIKE '\_site\_transient\_timeout\_browser\_%'
OR option_name LIKE '\_transient\_dash\_%'
OR option_name LIKE '\_site\_transient\_browser\_%'
"
);
echo "<br />Optimization - done<br />";
}
?>
<!--
Here we perform the optimization itself
-->
<hr />
<form action="" method="POST" >
<input type="submit" name="database_manage" value="Manage Backups" class="button-primary" />
</form>
<?php
if(isset($_POST['database_manage']))
{
?>
<table class="widefat">
<thead>
<tr>
<th>List of the available backups</th>
</tr>
</thead>
<tfoot>
<tr>
<th>
<?php
echo "
<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js\"></script>
<script type=\"text/javascript\">
function deleteBackup(backupfile){
$.get( \"".$url."delete.php?delete=\"+backupfile, function( data ) {
//    $( \".result\" ).html( data );
var removedDiv = document.getElementById(backupfile);
removedDiv.parentNode.removeChild(removedDiv);
});
}
</script>
";
$path = "$dir/backup_db";
$dh = opendir($path);
$i=1;
while (($file = readdir($dh)) !== false) {
if($file != "." && $file != "..") {
echo "<div id='$file'>$i. <a href='".$url."backup_db/$file' title='Click to Download'>$file</a> | <a href='#' onclick=\"javascript: deleteBackup('$file')\">Delete Backup</a><br /></div>\n";
$i++;
}
}
closedir($dh);
?>
</th>
</tr>
</tfoot>
<tbody>
</tbody>
<!--
Here we give the option to control the available backups.
-->
<?php
}
?>
<?php
}
?>

Now if everything is fine, you have created your first custom WordPress plugin. Just refresh the plugin page and you will see the following on your screen:

Simple WordPress plugin

Simple WordPress plugin


Do you want to share your opinion?

Your email address will not be published. Required fields are marked *


*

We are not industry specific. We are WordPress specific. We work with everyone to help them find solutions with their troubles.
If you show us the problem you are experiencing, we will show you how to fix it. It is that simple.


Here you can check the latest resolved WordPress issues

Reported WordPress issues

  1. wordpress shipping cost reduction total cart price
  2. wc_get_product_ids_on_sale() …getting product on sale in WooCommerce
  3. Preserving custom pages via redirect
  4. Wordpress - get_template_part() section not showing
  5. Can't click behind my Iframe. Is it possible?
  6. To show toggle and simple menu
  7. Post in WordPress
  8. Get Json Data when a variable matches with ACF custom field in WooCommerce
  9. BuddyPress shared user-base on Multisite separate sites
  10. How to show product variation in cloumn instead of row in Wordpress?

WordPress problems we are working on

  1. All pages redirect to home page
  2. Is possible to read a value from a dynamic HTML table and pass it to an input form?
  3. Google Shopping With Multiple Titles
  4. Wordpress - white screen of death when trying to update a page and/or a file in Editor
  5. cart is not working with more than 3 variations Woocommeerce.?
  6. Apache set Access-Control-Allow-Origin from http to https
  7. Wordpress works fine on admin dashboard but not loading for public
  8. Tranform in ::before breaking child elements in Wordpress navigation menu - CHROME
  9. How to flash error message in wordpress?
  10. Warning: Illegal string offset while searching of product

Resolved issues

  1. How to edit this function to improve performance in Wordpress?
  2. Wordpress get post id
  3. Open Lightbox on onload page
  4. Blogs posts on an alternative page?
  5. Style don't change in form
  6. Using Consolibyte's PHP Devkit to Add a Customer to Quickbooks POS Desktop v.12 w/ Web Connector
  7. How to reset all fields when adding to WooCommerce Cart
  8. Wordpress Rest API and AngularJS ui-sref and custom HTML
  9. Importing contact form in front-page.php
  10. Wordpress - adding a custom font via font-face
wppotion - powered by persistence and passion