Creating a Basic Wordpress Plugin
Published Friday 3rd of February 2012
I recently created my very first Wordpress plugin (I've been coding themes for a few years though) and I thought I'd write down a little getting started for other plugin noobs out there.
I'll cover how to configure your plugin, connect to the database using the WPDB, install and uninstall DB tables, create a page in the admin and submit forms.
I'll focus more on the WP specific stuff and less on PHP. If you don't know PHP you might find it hard to follow.
If you ever need more information about a WP function refer to the Wordpress codex. I won't go into as much detail as they do.
Let's code
All Wordpress plugins reside in the wp-content/plugins/ directory. Plugins can be as simple as a single PHP file or a directory full of PHP, CSS, JS, images and whatever else you can think of (just like a SleekPHP Module :).
To create a new plugin all we need to do is create a directory for our plugin in the plugins directory, and then create a PHP file with the same name as the directory we created:
- wp-content/plugins/
- wp-content/plugins/my-plugin/
- wp-content/plugins/my-plugin/my-plugin.php
- wp-content/plugins/my-plugin/
The first PHP comment in this file will hold our configuration:
<?php
/*
Plugin Name: My Plugin
Description: My first WP plugin
Author: You
Author URI: http://your-website.com
Version: 1.0
License: GPL
*/
That's enough for your plugin to show up in the admin, but at this point it won't do anything. Let's do something about that.
We'll start by setting up some handy CONSTANTS for use later in our code:
global $wpdb;
define('MYP_TITLE', 'My Plugin');
define('MYP_SLUG', 'my-plugin');
define('MYP_TABLE', $wpdb->prefix . 'myp_table');
define('MYP_DOCROOT', dirname(__FILE__));
define('MYP_WEBROOT', str_replace(getcwd(), home_url(), dirname(__FILE__)));
Now we're going to hook into Wordpress and tell it we want to perform certain actions at certain points. The first thing we want to do is tell it to run a function of ours when the plugin is activated, and another when it is deactivated. These functions are used for creating and dropping the database table:
register_activation_hook(__FILE__, 'myp_install');
register_deactivation_hook(__FILE__, 'myp_uninstall');
We'll also tell Wordpress to add a menu item in the admin for our plugin:
add_action('admin_menu', 'myp_menu');
Now we could go on and create these functions (mypinstall(), mypuninstall(), myp_menu()), do all the database logic and write all the HTML in this same file but that would look horrible so we're going to divide it up a bit.
Create two directories in your plugin directory: "lib" and "views". In lib create three files: install.php, model.php and controller.php.
Before we fill those files with juicy PHP code we'll put the last three lines in my-plugin.php which by now should look like this:
<?php
/*
Plugin Name: My Plugin
Description: My first WP plugin
Author: You
Author URI: http://your-website.com
Version: 1.0
License: GPL
*/
global $wpdb;
define('MYP_TITLE', 'My Plugin');
define('MYP_SLUG', 'my-plugin');
define('MYP_TABLE', $wpdb->prefix . 'myp_table');
define('MYP_DOCROOT', dirname(__FILE__));
define('MYP_WEBROOT', str_replace(getcwd(), home_url(), dirname(__FILE__)));
register_activation_hook(__FILE__, 'myp_install');
register_deactivation_hook(__FILE__, 'myp_uninstall');
add_action('admin_menu', 'myp_menu');
include 'lib/model.php';
include 'lib/install.php';
include 'lib/controller.php';
With the three includes added at the bottom.
Let's start with install.php.
install.php
We'll put our two functions myp_install() and myp_uninstall() in this file and all they'll do is CREATE or DROP our plugin database table.
<?php
function myp_install () {
global $wpdb;
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta('
CREATE TABLE `' . MYP_TABLE . '` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`content` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`active` tinyint(4) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
');
dbDelta('INSERT INTO `' . SSB_TABLE . '` VALUES ("", "Test", "This is a test", "1")');
}
function myp_uninstall () {
global $wpdb;
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta('DROP TABLE `' . MYP_TABLE . '`');
}
Hopefully the SQL is self explanatory. The ludacris use of global variables and the "upgrade.php" include is Wordpress at its best. This is the way it's done in WP you just have to live with it.
That's enough for our install/uninstall hooks. Now let's create the function responsible for rendering the page we added to the admin.
controller.php
Whatever the myp_menu() function prints will be output on our plugin page in the admin. Instead of writing our HTML inside echo:s in our function we'll use a view for that. This function will only be responsible for getting or updating data and pass that data along to the view:
<?php
function myp_menu () {
add_menu_page(MYP_TITLE, 'My Plugin', 'administrator', MYP_SLUG, 'myp_main');
}
function myp_main () {
# Insert data
if (isset($_POST['myp_insert_data'])) {
MYP_Table::insert($_POST);
}
# Delete data
if (isset($_POST['myp_delete_data'])) {
MYP_Table::delete($_POST['myp_id']);
}
# Get data
$myp_data = MYP_Table::get();
# Include view
include MYP_DOCROOT . '/views/main.php';
}
As you can see if we POST certain data to this file it will insert or delete data in our table. But instead of putting all the SQL queries and DB logic in this file we're using our MYP_Table "model". This way we can insert, update and delete data in our table from anywhere, without repeating ourselves.
model.php
The model will handle all DB logic using WP's WPDB class:
<?php
class MYP_Table {
public static function get () {
global $wpdb;
$rows = $wpdb->get_results('SELECT * FROM ' . MYP_TABLE, ARRAY_A);
return $rows;
}
public static function insert ($row) {
global $wpdb;
return $wpdb->insert(MYP_TABLE, array(
'title' => stripslashes_deep($row['title']),
'content' => stripslashes_deep($row['content'])
));
}
public static function update ($id, $row) {
global $wpdb;
$update = array();
if (isset($row['title'])) {
$update['title'] = stripslashes_deep($row['title']);
}
if (isset($row['content'])) {
$update['content'] = stripslashes_deep($row['content']);
}
if (isset($row['active'])) {
$update['active'] = $row['active'] ? '1' : '0';
}
if (count($update)) {
return $wpdb->update(MYP_TABLE, $update, array('id' => $id), array('%s', '%s'), array('%d'));
}
return false;
}
public static function delete ($id) {
global $wpdb;
return $wpdb->query('DELETE FROM ' . MYP_TABLE . ' WHERE id = ' . $wpdb->escape($id));
}
}
Hopefully this code too should be quite clear. You have to use stripslashesdeep() on data from $POST (or GET, COOKIE etc) since WP 3 because they addslashes to all such variables early in the WP init code (WP shines again!). Obviously you'll need to change all this to match the table you want to use but you can use this as a template.
The only thing that's left is to create the view which will list all our data (with delete buttons) and allow users to add new data.
views/main.php
This is nothing more than standard HTML and some basic PHP loops:
<!-- the .wrap-class is required by WP to style the h2 like others in the admin (again, WP ftw!) -->
<section id="my-plugin" class="wrap">
<!-- this ludacris display is how WP renders an icon -->
<div id="icon-themes" class="icon32"><br></div>
<h2>My Plugin</h2>
<p>An intro text about my plugin</p>
<h3>Add data</h3>
<form method="post" action="">
<p>
<label>
Title<br>
<input type="text" name="title">
</label>
</p>
<p>
<label>
Content<br>
<textarea name="content" rows="10" cols="80"></textarea>
</label>
</p>
<p>
<input type="hidden" name="myp_insert_data" value="1">
<input type="submit" value="Add data">
</p>
</form>
<h3>Your data</h3>
<?php if (count($myp_data)) : ?>
<ul>
<?php foreach ($myp_data as $data) : ?>
<li>
<h4><?php echo $data['title'] ?></h4>
<?php echo $data['content'] ?>
<form method="post" action="" onsubmit="return confirm('Are you sure?')">
<p>
<input type="hidden" name="myp_delete_data" value="1">
<input type="hidden" name="myp_id" value="<?php echo $data['id'] ?>">
<input type="submit" value="Delete">
</p>
</form>
</li>
<?php endforeach ?>
</ul>
<?php else : ?>
<p>You don't have any data yet.</p>
<?php endif ?>
</section>
There you have it. Happy WPing.
- Tags
- Comments
- No comments
Bookmark this Article