Load Minimum of WordPress

A small contribution for all those using WordPress as a backend, framework or something similar. The applications, especially in the B2B sector, becoming more and more, as do the questions.

So far, I've always liked to recommended BackPress. But even a well-maintained standard is feasible, with all its advantages in the context of the philosophy of updates. WordPress reduces initializing to a minimum, if the constant SHORTINIT is set.
Continue reading …


Beautiful Web Type Combinations

Fonts have become great favorites of the customers, with relatively little effort you can achieve a lot - at least if you understand some of the typography and use solutions that are easy to implement. In this context, I had experiences with own fonts from designers and the costs are not in proportion to the use of free web fonts. In particular, Google provides here a big range of solutions and makes the integration easy.

The endless choices of fonts also presents a problem, it is not easy to find the right fonts in a good combination. In the past I collected some solutions in a single page and now have a very nice scope. The solutions are not from me, but usually by designers in the world wide web.
Continue reading …

broken doppelgaenger

Don’t use strlen()

Each time I see someone use strlen() I cringe. It will break.

Despite its name, strlen() doesn’t count characters. It counts bytes. In UTF-8 a character may be up to four bytes long.

So what happens if we use strlen() and its companion substr() to shorten the title of post?

<?php # -*- coding: utf-8 -*-
declare( encoding = 'UTF-8' );
header('Content-Type: text/plain;charset=utf-8');

$string = 'Doppelgänger';
print 'strlen():    ' . strlen( $string ) . "\n";
print 'mb_strlen(): ' . mb_strlen( $string, 'utf8' ) . "\n\n";

print 'substr():    ' . substr( $string, 0, 8 ) . "\n";
print 'mb_substr(): ' . mb_substr( $string, 0, 8, 'utf8' );
WordPress News, Hacks, Tips, Tutorials, Plugins and Themes - Page 5 of 58 - WP Engineer


I have to use an image here. If I had used the plain text output our newsfeed would break. And that’s what happens each time you use strlen() and substr() on strings encoded in UTF-8: You end up with partial characters and invalid UTF-8.

Alternatives for mb_strlen()

You can use different methods to get the real string length.

$length = preg_match_all( '(.)su', $string, $matches );

See also Hakre: PHP UTF-8 string Length.

Or just use …

$length = strlen( utf8_decode( $string ) );

There is also a nice php-utf8 library on GitHub from Frank Smit.


WP_List_Table – a step by step guide

Throughout WordPress the class WP_List_Table is used to display data, e.g. users, plugins, comments, or posts. The class contains almost all necessary methods for displaying, sorting, paginating, and searching data and and what is more obvious than to use it for your own plugins?

This article tries to give you a comprehensive walk-through all necessary steps to create a table tailored to your needs.

  1. Preliminary work
  2. Basics
  3. Sorting
  4. Actions
  5. Bulk actions
  6. Pagination
  7. Searching
  8. Screen options
  9. Styling the table
  10. Other customizations
  11. Weblinks

Preliminary work

For testing purposes we create a small plugin which adds a menu item:

Plugin Name: My List Table Example
<div class="wrap">
<div id="icon-users" class="icon32"></div>
<h2>My List Table Test/h2>


For a start we're creating a list table with only the basic functionality. First we have to make sure that the necessary class is available since the WP_List_Table isn't loaded automatically:

if( ! class_exists( 'WP_List_Table' ) ) {
    require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );

To create a table to your needs you have to derive a class from WP_List_Table:

class My_List_Table extends WP_List_Table {

$myListTable = new My__List_Table();

For demonstration purposes we create some sample data. Usually this data would be read from the database:

var $example_data = array(
  array('ID' => 1,'booktitle' => 'Quarter Share', 'author' => 'Nathan Lowell',
        'isbn' => '978-0982514542'),
  array('ID' => 2, 'booktitle' => '7th Son: Descent','author' => 'J. C. Hutchins',
        'isbn' => '0312384378'),
  array('ID' => 3, 'booktitle' => 'Shadowmagic', 'author' => 'John Lenahan',
        'isbn' => '978-1905548927'),
  array('ID' => 4, 'booktitle' => 'The Crown Conspiracy', 'author' => 'Michael J. Sullivan',
        'isbn' => '978-0979621130'),
  array('ID' => 5, 'booktitle'     => 'Max Quick: The Pocket and the Pendant', 'author'    => 'Mark Jeffrey',
        'isbn' => '978-0061988929'),
  array('ID' => 6, 'booktitle' => 'Jack Wakes Up: A Novel', 'author' => 'Seth Harwood',
        'isbn' => '978-0307454355')

Before we can display the data in the table we have to define some methods and variables:

function get_columns(){
  $columns = array(
    'booktitle' => 'Title',
    'author'    => 'Author',
    'isbn'      => 'ISBN'
  return $columns;

function prepare_items() {
  $columns = $this->get_columns();
  $hidden = array();
  $sortable = array();
  $this->_column_headers = array($columns, $hidden, $sortable);
  $this->items = $this->example_data;;

The method get_columns() is needed to label the columns on the top and bottom of the table. The keys in the array have to be the same as in the data array otherwise the respective columns aren't displayed.

prepare_items defines two arrays controlling the behaviour of the table:

  • $hidden defines the hidden columns (see Screen Options),
  • $sortable defines if the table can be sorted by this column.

Finally the method assigns the example data to the class' data representation variable items.

Before actually displaying each column WordPress looks for methods called column_{key_name}, e.g. function column_booktitle. There has to be such a method for every defined column. To avoid the need to create a method for each column there is column_default that will process any column for which no special method is defined:

function column_default( $item, $column_name ) {
  switch( $column_name ) { 
    case 'booktitle':
    case 'author':
    case 'isbn':
      return $item[ $column_name ];
      return print_r( $item, true ) ; //Show the whole array for troubleshooting purposes

In our example the method will return the title for every column and if the column is not found it displays the content of the $item array for debugging purposes.

These are the essential ingredients to define a custom list table class. All you have to do now is to add an admin page to the backend, create an instance of our class, prepare the items and call display() to actually display the table:

function my_add_menu_items(){
    add_menu_page( 'My Plugin List Table', 'My List Table Example', 'activate_plugins', 'my_list_test', 'my_render_list_page' );
add_action( 'admin_menu', 'my_add_menu_items' );

function my_render_list_page(){
  $myListTable = new My_Example_List_Table();
  echo '<div class="wrap"><h2>My List Table Test</h2>'; 
  echo '</div>'; 

This is the minimal version of a WP_List_Table possible:

Download minimal WP_List_Table example (gist)


At the moment the items appear in the order they are defined in the code since the WP_List_Table class does not contain any code for sorting. What it does contain is some code to mark certain columns as sortable. In section "Basics" there already was a line $sortable = array(); which now will be changed to:

$sortable = $this->get_sortable_columns();

Additionally we need the method:

function get_sortable_columns() {
  $sortable_columns = array(
    'booktitle'  => array('booktitle',false),
    'author' => array('author',false),
    'isbn'   => array('isbn',false)
  return $sortable_columns;

This way the above mentioned column headers are changed to links and display small triangles if the mouse hovers over them. The second parameter in the value array of $sortable_columns takes care of a possible pre-ordered column. If the value is true the column is assumed to be ordered ascending, if the value is false the column is assumed descending or unordered. This is needed for the small triangle beside the column name indicating the sort order to show in the correct direction:

If you click on the column header the page is reloaded and $_GET contains something like this:

  'page' => string 'my_list_test' (length=12)
  'orderby' => string 'booktitle' (length=5)
  'order' => string 'asc' (length=3)

With this information you can write a method for sorting our example data:

function usort_reorder( $a, $b ) {
  // If no sort, default to title
  $orderby = ( ! empty( $_GET['orderby'] ) ) ? $_GET['orderby'] : 'booktitle';
  // If no order, default to asc
  $order = ( ! empty($_GET['order'] ) ) ? $_GET['order'] : 'asc';
  // Determine sort order
  $result = strcmp( $a[$orderby], $b[$orderby] );
  // Send final sort direction to usort
  return ( $order === 'asc' ) ? $result : -$result;

To actually sort the data we have to extend prepare_items():

function prepare_items() {
  usort( $this->example_data, array( &$this, 'usort_reorder' ) );
  $this->items = $this->example_data;

If you're retrieving the data from the database (which is most likely) it's of course best to use SQL's ORDERBY directly.


If you not only want to display the items but also want to manipulate them you have to define some actions:

function column_booktitle($item) {
  $actions = array(
            'edit'      => sprintf('<a href="?page=%s&action=%s&book=%s">Edit</a>',$_REQUEST['page'],'edit',$item['ID']),
            'delete'    => sprintf('<a href="?page=%s&action=%s&book=%s">Delete</a>',$_REQUEST['page'],'delete',$item['ID']),

  return sprintf('%1$s %2$s', $item['booktitle'], $this->row_actions($actions) );

These actions will appear if the user hovers the mouse cursor over the table:

If you click on one of the action links the form will return for example the following data in $_GET:

  'page' => string 'my_list_test' (length=12)
  'action' => string 'delete' (length=6)
  'book' => string '2' (length=1)

Bulk actions

Bulk action are implemented by overwriting the method get_bulk_actions() and returning an associated array:

function get_bulk_actions() {
  $actions = array(
    'delete'    => 'Delete'
  return $actions;

This only puts the dropdown menu and the apply button above and below the table:

The checkboxes for the rows have to be defined separately. As mentioned above there is a method column_{column} for rendering a column. The cb-column is a special case:

function column_cb($item) {
        return sprintf(
            '<input type="checkbox" name="book[]" value="%s" />', $item['ID']

This method currently will not be processed because we have to tell the class about the new column by extending the method get_columns():

function get_columns() {
  $columns = array(
    'cb'        => '<input type="checkbox" />',

This will also put the "select all" checkbox in the title bar:

If you don't want to display the checkbox in the title you simply set the value to an empty string. Nevertheless you still have to define the key/value pair otherwise no checkboxes are shown at all:

If "Apply" is pressed the form will return various variables: action and action2 contain the selected action or -1 if the user chose no action, and if any checkbox was selected the marked rows, in our case books, for example:

'action' => string 'delete' (length=6)
'book' => 
    0 => string '2' (length=1)
    1 => string '6' (length=1)
'action2' => string '-1' (length=2)

action contains the selection from the upper select box, action2 the selection from the lower select box, and book the id of the selected rows, if any. You can use the method current_action() to query action/action2:

$action = $this->current_action();

It will return action if it's set, otherwise action2. If nothing is set the method returns FALSE.


First things first: WordPress does not paginate your data in any way. It only contains a method to display a navigation bar on the top and bottom right of the table:

You have to tell the method how many items you have in total, how many items shall be displayed on a page, and most important, the data to be displayed on the page:

function prepare_items() {
  $per_page = 5;
  $current_page = $this->get_pagenum();
  $total_items = count($this->example_data);

  // only ncessary because we have sample data
  $this->found_data = array_slice($this->example_data,(($current_page-1)*$per_page),$per_page);

  $this->set_pagination_args( array(
    'total_items' => $total_items,                  //WE have to calculate the total number of items
    'per_page'    => $per_page                     //WE have to determine how many items to show on a page
  ) );
  $this->items = $this->found_data;

As pointed out in the comment the array_slice is only necessary because we use sample data. If you're retrieving the data from a database you only need to load the necessary data by using SQL's LIMIT.


If you have a huge amount of data a search field will simplify accessing certain items:

$myListTable->search_box('search', 'search_id');

The button text search is defined by the first parameter, the id of the input by the second parameter. The method creates the following output:

<p class="search-box">
<label class="screen-reader-text" for="search_id-search-input">
<input id="search_id-search-input" type="text" name="s" value="" /> 
<input id="search-submit" class="button" type="submit" name="" value="search" />

The method will place the input field and the search button on the right side and style it correctly. The <form> element is not generated. You have to add it manually, in our case this would be:

<form method="post">
  <input type="hidden" name="page" value="my_list_test" />
  <?php $this->search_box('search', 'search_id'); ?>

(The hidden element is needed to load the right page.)
To react to the search command you need to check the content of $_POST['s'] and filter your data accordingly before displaying the table.

Screen options

All core backend pages containing a WP_List_Table provide a "Screen Options" slide-in where the user can adjust the columns to be shown and the number of rows to be displayed.
To add options to your plugin you need to change your current code. First you have to make sure that the screen options are displayed only on the current page:

$hook = add_menu_page('My Plugin List Table', 'My List Table Example', 'activate_plugins', 'my_list_test', 'my_render_list_page');
add_action( "load-$hook", 'add_options' );

function add_options() {
  $option = 'per_page';
  $args = array(
         'label' => 'Books',
         'default' => 10,
         'option' => 'books_per_page'
  add_screen_option( $option, $args );

This only displays the option field and apply button, saving and loading the data has to be defined separately. WordPress provides a filter called set-screen-option to take care of this:

add_filter('set-screen-option', 'test_table_set_option', 10, 3);
function test_table_set_option($status, $option, $value) {
  return $value;

The option is stored in the table usermeta in the database so each user has his own setting. To retrieve the option and adjust the table display accordingly the method prepare_items has to be altered (excerpt):

function prepare_items() {

  $per_page = $this->get_items_per_page('books_per_page', 5);
  $current_page = $this->get_pagenum();


Instead of simply assigning a number the user specified value is loaded. If the user hasn't changed the value there is no such option stored in the database and a default value is taken.

Adding the checkboxes for hiding/showing the columns is done by WordPress automatically. You just have to make sure that your derived class is instantiated before the screen option panel is rendered so that the parent class can retrieve the column names. To accomplish this the corresponding code is moved into the method add_options():

function add_options() {
    global $myListTable;
    $option = 'per_page';
    $args = array(
        'label' => 'Books',
        'default' => 10,
        'option' => 'books_per_page'
    add_screen_option( $option, $args );

    $myListTable = new My_Example_List_Table;

The user's selections are automatically saved via Ajax functions. Nevertheless you have take care by yourself that the columns are hidden if the page is loaded initially. The method get_column_info() returns all, the hidden and the sortable columns. In the method prepare_items() instead of

$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);

it's now

$this->_column_headers = $this->get_column_info();

and the columns are set according to the screen options.

Annotation: you should avoid some strings as keynames since they are treated by WordPress specially:

$special = array('_title', 'cb', 'comment', 'media', 'name', 'title', 'username', 'blogname');

Your table would still work, but you won't be able to show/hide the columns.

Styling the table

Currently the table is styled to the WordPress defaults. To change this you have to adapt the CSS classes which are automatically assigned to each column. The class name consists of the string "column-" and the key name of the $columns array, e.g. "column-isbn" or "column-author". As an example the width of the columns will be redefined (for simplicity the style data is written directly into the HTML header):

function _construct() {
  add_action( 'admin_head', array( &$this, 'admin_header' ) );

function admin_header() {
  $page = ( isset($_GET['page'] ) ) ? esc_attr( $_GET['page'] ) : false;
  if( 'my_list_test' != $page )

  echo '<style type="text/css">';
  echo '.wp-list-table .column-id { width: 5%; }';
  echo '.wp-list-table .column-booktitle { width: 40%; }';
  echo '.wp-list-table .column-author { width: 35%; }';
  echo '.wp-list-table .column-isbn { width: 20%; }';
  echo '</style>';

Other customizations

If there are no items in the list the standard message is "No items found." is displayed. If you want to change this message you can overwrite the method no_items():

function no_items() {
  _e( 'No books found, dude.' );

Download complete WP_List_Table example (gist) or see the Gist


We’ve Lost A Very Good Friend, WordPress Enthusiast And An Important Part Of WPEngineer!

Sadness has descended on WPEngineer last week. Michael Preuß, one of our WPEngineer Team, died suddenly after a short illness and after a memorable life.

Frank and I are still in shock and we can't realize that Michael left us without saying goodbye. He leaves a big gap in our life. He was not only our teammate at WPEngineer, he also was a very good friend, who have shared the same love for WordPress and the community as we do.

We didn't meet us very often in person, since we live quite far away from each other. But when we did, we always had a blast and fun talking about WordPress and other stuff that was going on right now around the world. But most of the time we were talking on the phone for hours, literally.

This time our reunion was one of Frank's and my saddest moment. We had to carry Michael to his grave. It was painful, incomprehensible and unbearable at once. Unlikely for us, not one word about WordPress, this time we had to mourn the loss of our beloved friend Michael.

Feb 2009 - Matt meets WPEngineer: Frank, Michael, Matt, Alex

Feb 2009 - Matt meets WPEngineer: Frank, Michael, Matt, Alex

Just 4 years ago we got to know each other and became very good friends. Michael, Frank and I had the urge to give the WordPress community something back, a platform for writing tips, tricks and solutions for the WordPress community - WPEngineer was born! Frank and I will continue to publish future posts, despite the loss we have.

We will also help his partner and friend Heiko, to continue Michael's life's work Xtreme Theme.

He left his wonderful and caring wife Carola and his two sons Robert and Alexander behind, and I'm sure, many other WordPress Junkies, like we are, who still can't believe he is gone forever!

You will always be in our Source Code!

In deepest sympathy

Alex & Frank

Stop SOPA!

What is this all about: Help Stop SOPA/PIPA
Turn off your website on January 18th for 12 hours.

Simple and fast solution for turn the website off; use the Plugin WP Maintenance Mode, original for the activation of the maintenance mode; but its easy for this requirement. As useful; the plugin send an 503 Service Unavailable header.

Set the following settings in the plugin

Code for the field text, the video markup:

<iframe src="http://player.vimeo.com/video/31100268?byline=0&portrait=0" width="400" height="225" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
<p><a href="http://vimeo.com/31100268">PROTECT IP / SOPA Breaks The Internet</a> from <a href="http://vimeo.com/fightforthefuture">Fight for the Future</a>.</p>

Here is the result for not signed in visitors: