WP-Fun.co.uk

Using Objects with WordPress Plugins, p. 3

In part 2 of the series I looked at the way objects can be used to separate the repetitive logic from the core code of the plugin itself by demonstrating an object based text box. In this part I’m going to take it one further and show how several objects can be derived from a common class to prevent repetition of code in the objects themselves.

I ended part 2 with two classes: A text box class that handled display of a textbox as well as getting and setting its value when the form is loaded or submitted, and the class used for the plugin itself that created an admin page and added three textboxes.

In this part I am going to create two more classes. The first is a generic form control class. Into this I am going to put the initial declaration of the necessary variables, and the value getting and setting code from the text box class.

This is the full text box class from part 2:

//note this example does not perform any validation.
class my_text_box
{
 
    var $prefix = 'my_text_box_';
    var $name = '';
    var $value = '';
    var $description = '';
 
    //php 4 constructor
    function my_text_box( $name , $description ) {
 
        $this->name = $name;
        $this->description = $description;
 
        if ( $v = get_option( $this->prefix . $this->name ) ) {
            $this->value = $v;
        }
 
        if ( isset( $_POST[$this->prefix . $this->name] ) ) {
			$this->value = $_POST[$this->prefix . $this->name];
            update_option( $this->prefix . $this->name , $this->value );
        }
    }
 
    function display() {
 
    echo '<p>';
    echo '<label for="'.$this->prefix . $this->name.'">'.$this->description.'</label>';
    echo '<input type="text" name="'.$this->prefix . $this->name.'" value="'.$this->value.'" />';
    echo '</p>';
 
    }
}

The new class, is a generic class that doesn’t display anything, but does handle the values. You can see the sections of the code that have been removed from the textbox class by comparing the two classes.

In the generic class the value getting and setting code is no longer part of the constructor, so it will need to be called explicitly. Also note I have amended the prefix from my_text_box to the more generic my_form_control.

class my_form_control{
 
    var $prefix = 'my_form_control_';
    var $name = '';
    var $value = '';
    var $description = '';
 
    function get_value( ) {
 
        if ( $v = get_option( $this->prefix . $this->name ) ) {
            $this->value = $v;
        }
 
        if ( isset( $_POST[$this->prefix . $this->name] ) ) {
			$this->value = $_POST[$this->prefix . $this->name];
            update_option( $this->prefix . $this->name , $this->value );
        }
    }
}

Now, this is the important part. Having moved some of the code into a generic class we need to rewrite the textbox class, and we do this by using the ‘extends’ keyword.

class my_text_box extends my_form_control
{
 
    //php 4 constructor
    function my_text_box( $name , $description ) {
 
        $this->name = $name;
        $this->description = $description;
        $this->get_value();
    }
 
    function display() {
 
    echo '<p>';
    echo '<label for="'.$this->prefix . $this->name.'">'.$this->description.'</label>';
    echo '<input type="text" name="'.$this->prefix . $this->name.'" value="'.$this->value.'" />';
    echo '</p>';
 
    }
}

The ‘extends’ keyword, used in the class title tells PHP that our class should inherit everything that is in the generic class, so although the my_text_box class is now much shorter than it was it actually has exactly the same functionality.

As well as moving the code into the generic class there is one more change; the constructor of the text box class now calls the get_value function. Note that we can still use the $this keyword to access it, even though it is contained within the generic class we have extended.

The benefit of this is that we can now create a second type of form control which will differ in only one way, it will output slightly different html, and we don’t need to recreate the code that gets and sets the value.

class my_text_area extends my_form_control
{
 
    //php 4 constructor
    function my_text_area ( $name , $description ) {
 
        $this->name = $name;
        $this->description = $description;
        $this->get_value();
    }
 
    function display() {
 
    echo '<p>';
    echo '<label for="'.$this->prefix . $this->name.'">'.$this->description.'</label>';
    echo '<textarea name="'.$this->prefix . $this->name.'">'.$this->value.'</textarea>';
    echo '</p>';
 
    }
}

This new class works in exactly the same way as the text box class, except that it outputs the html for a textarea, instead of a text box. It extends the base class, uses the same method of getting and setting the value. Already, extending the generic class has saved 10 lines of code that would have been identical to each other. If we were to create a third class, for example, a drop down box, then we would have saved twenty lines of code. Add that the fact that if you find a flaw you only need to amend it once, and the saving made by using objects instead of hardcoding the html into the admin page and you start to see how beneficial using objects can be.

Finally, there is one more change that is needed. We need to amend the actual admin page itself to use a text area as well as a text box. To do this we change only one line from the admin page in part 2:

$option2 = new my_text_box( 'Option_2' , 'Second Option');

We change this to:

$option2 = new my_text_area( 'Option_2' , 'Second Option');

So the final admin page class looks like this:

class my_plugin
{
 
    //PHP 4 style constructor
    function my_plugin(){
 
	add_action( 'admin_menu' , array(&$this , 'add_admin_menu') );
 
    }
 
	function add_admin_menu(){
 
	add_options_page('My Plugin Options', 'My Plugin Options', 9, basename(__FILE__), array(&$this, 'admin_page'));
 
	}
 
    function admin_page(){
 
    $option1 = new my_text_box( 'Option_1' , 'First Option');
    $option2 = new my_text_area( 'Option_2' , 'Second Option');
    $option3 = new my_text_box( 'Option_3' , 'Third Option');
 
    ?>
    <div class="wrap">
        <h2>My Admin Page</h2>
        <form method="post">
        <p>
        <?php $option1->display(); ?>
        </p>
        <p>
        <?php $option2->display(); ?>
        </p>
        <p>
        <?php $option3->display(); ?>
        </p>
        <p>
        <input type="submit" name="submit_my_plugin_options" value="Submit" />
        </p>
        </form>
    </div>
    <?php
    }
 
 
}
 
$my_plugin = new my_plugin();

We’ve made a significant change to the admin page by changing only one word of the actual page content itself.

You can download the finish plugin here: just remove the .txt from the end of it.

In this part I have demonstrated how you can extend generic classes that encapsulate regularly used functions to create multiple classes with similar functionality without repeating the same code, potentially saving a significant amount of identical code and making the code more maintainable at the same time. In the final part I will look at ways of storing collections of objects in order to remove even the admin page code itself from the core plugin files.