Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am working on a simple search form widget, with a built in autocomplete capability (You can download the current version here). The plugin is working, but I am currently rewriting all the code using OOP. One of the problems I came across was the fact the a Wordpress Widget is already a part of the WP_Widget class. I can divide the code into 2 classes. The first one loads all the scripts and css, and initializes the widget. Here is the outline of the code:

class wdSearchForm {

        public function __construct() {
            // Action hook to load widget
            // Register and enqueue styles
            // Register and enqueue scripts
        }

        // register widget in WordPress so that it is available under the widgets section
        public function wd_searchform() {
            register_widget( 'wd_searchform' );
        }
}

And here is the outline to the widget class:

class wd_searchform extends WP_Widget {

    // Constructor
    function wd_searchform() {

    }

    // The widget itself
    function widget( $args, $instance ) {
        // The widget code
    }

    //Update the widget 
    function update( $new_instance, $old_instance ) {
        // Update code
    }

    function form( $instance ) {
        //Set up widget settings.
    }
}

I would like to combine the two, in order to use wp_localize_script and load the script with the widget options. How should I do that? Any suggestions are welcome, even if you'll tell me i'm totally in the wrong direction...

share|improve this question
2  
You should use the widget boilerplate here. –  Mr2P Jan 13 '13 at 18:55

2 Answers 2

up vote 5 down vote accepted

You can simply put your init code within the constructor of the class. For example:

class myWidget extends WP_Widget{

    function myWidget(){
       // Init code here
    }

    function widget( $args, $instance ) {
       // The widget code
       wp_enqueue_script(...);
       wp_enqueue_style(...);

   }

   // Over methods...

}

register_widget('myWidget');

My preference is to actually put the enqueue calls within the shortcode handling function to avoid the overhead and potential conflicts associated with loading JavaScript and stylesheets that aren't being used on a given page.

share|improve this answer
    
Thank you @Stephen. Can you elaborate on putting enqueue calls within the shortcode handling function? –  Yoav Kadosh Jan 13 '13 at 19:05
3  
Place your wp_enqueue_ calls within the method that actually handles the shortcode/widget processing. This way you don't enqueue the JS and styles unless the shortcode/widget is actually used on a given page. See edits above. –  Stephen Jan 13 '13 at 19:12

Your code is PHP4 style. PHP4 styled code should not be used anymore. And just putting some functions inside a class construct is not OOP. If you want to write reusable code, separate your code.

For example:

class Widget_Setup
{
    public $widget_class  = '';
    public $admin_styles  = array();
    public $admin_scripts = array();
    public $front_styles  = array();
    public $front_scripts = array();

    public $script_defaults = array(
        'handle'    => '',
        'src'       => '',
        'deps'      => array(),
        'version'   => false,
        'in_footer' => false
    );

    public $style_defaults = array(
        'handle'   => '',
        'src'      => '',
        'deps'     => array(),
        'version'  => false,
        'media'    => 'all'
    );

    public function __construct( $widget_class = '', $admin_styles = array(), $admin_scripts = array(), $front_styles = array(), $front_scripts = array() ) {

        $this->widget_class  = $widget_class;
        $this->admin_styles  = $admin_styles;
        $this->admin_scripts = $admin_scripts;
        $this->front_styles  = $front_styles;
        $this->front_scripts = $front_scripts;

        add_action( 'admin_print_styles',    array( $this, 'add_styles' ) );
        add_action( 'admin_enqueue_scripts', array( $this, 'add_scripts' ) );
        add_action( 'wp_enqueue_scripts',    array( $this, 'add_styles' ) );
        add_action( 'wp_enqueue_scripts',    array( $this, 'add_scripts' ) );

        if( ! empty( $this->widget_class ) )
            add_action( 'widgets_init', array( $this, 'register_widget' ) );

    }

    public function register_widget() {

        register_widget( $this->widget_class );

        return true;

    }

    public function add_styles() {

        $styles = ( is_admin() ) ?
            $this->admin_styles : $this->front_styles;

        if( empty( $styles ) )
            return false;

        foreach( $styles as $style ) {

            $style = wp_parse_args( $style, $this->style_defaults );

            wp_enqueue_style(
                $style['handle'],
                $style['src'],
                $style['deps'],
                $style['version'],
                $style['media']
            );

        }

        return true;
    }

    public function add_scripts() {

        $scripts = ( is_admin() ) ?
            $this->admin_scripts : $this->front_scripts;

        if( empty( $scripts ) )
            return false;

        foreach( $scripts as $script ) {

            $script = wp_parse_args( $script, $this->script_defaults );

            wp_enqueue_script(
                $script['handle'],
                $script['src'],
                $script['deps'],
                $script['version'],
                $script['media']
            );

        }

        return true;
    }

}

This class can be reused for every widget. The idea behind OOP is reusing your code by writing data constructs with additional function. Not using class constructs because somebody say it is good style.

The class could be used like this:

class MyAwesomeWidget extends WP_Widget
{

    const TEXTDOMAIN = 'widget_textdomain';

    public function __construct() {

        parent::__construct(

            'widget-name-id',
            __( 'Widget Name', self::TEXTDOMAIN ),
            array(
                'classname'   =>    __CLASS__,
                'description' =>    __( 'Short description.', self::TEXTDOMAIN )
            )
        );

        $admin_style = array(
            array( 'handle' => 'somehandle', 'src' => 'path/to/source' ),
            array( 'handle' => 'someotherhandle', 'src' => 'path/to/source' ),
        );

        $admin_scripts = array(
            array( 'handle' => 'scrpthandle', 'src' => 'path/to/source', 'deps' => array( 'jquery') ),
        );

        $front_styles = array(
            array( 'handle' => 'frontstyle', 'src' => 'path/to/src' ),
        );

        new Widget_Setup( __CLASS__, $admin_style, $admin_scripts, $front_styles );
    }

    public function widget( $instance, $args ) {}

    public function update( $new_instance, $old_instance ) {}

    public function form( $instance ) {}

}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.