WordPress Widget vs Drupal 8 Block

Both WordPress and Drupal have long had the ability to place arbitrary content throughout your site. WordPress calls them Widgets, while Drupal has named them Blocks. Beyond the name they essentially provide the same functionality, but previous to Drupal 8, blocks have lacked the ability to be placed on a page more than once.

Not to go into a deep Drupal history lesson here or anything, but TL;DR, Drupal blocks in the past have been: 1 API implementation = 1 block. If you created a block in code, that block could be used exactly once in any given block placement interface. *

As a long time widget/block fan and WordPress/Drupal developer, I was naturally very excited when Drupal 8 adopted an instance approach to blocks that finally matches the flexibility of WordPress’s implementation.

Let’s take a look at how similar they are now

WordPress Widget Example

<?php
class ExampleWidget extends WP_Widget {
	/**
	 * ExampleWidget constructor.
	 */
	function __construct() {
		parent::__construct(
		// id_base
			'example_widget_id',
			// title
			__( 'My example widget' ),
			// widget options
			array(
				'classname'   => 'examplewidget',
				'description' => __( 'My example is great!' )
			)
		);
	}

	/**
	 * Echo the widget contents to the screen
	 *
	 * @param array $args
	 * @param array $instance
	 */
	function widget( $args, $instance ) {
		print "Hello {$instance['some_text']}";
	}

	/**
	 * Display the widget form to the screen
	 *
	 * @param array $instance
	 */
	function form( $instance ) {
		$default_values = array(
			'some_text' => 'Jonathan',
		);
		$instance = wp_parse_args( $instance, $default_values );
		?>
        <label for="<?php print $this->get_field_id( 'some_text' ) ?>"><?php _e('Some Text') ?></label>
        <input type="text"
               id="<?php print $this->get_field_id( 'some_text' ) ?>"
               name="<?php print $this->get_field_name( 'some_text' ) ?>"
               value="<?php print esc_html( $instance['some_text'] ) ?>" />
		<?php
	}

	/**
	 * Sanitize a new instance array and return it
	 *
	 * @param array $new_instance
	 * @param array $old_instance
	 */
	function update( $new_instance, $old_instance ) {
		$instance['some_text'] = sanitize_text_field( $new_instance['some_text'] );
		return $instance;
	}
}
example-wordpress-widget.php

Widget Form

Drupal 8 Block Example

<?php
namespace Drupal\example_block\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Form\FormStateInterface;
/**
 * Provide a simple Block to Drupal.
 *
 * @Block(
 *   id = "example_block",
 *   admin_label = @Translation("My example block")
 * )
 */
class ExampleBlock extends BlockBase implements BlockPluginInterface
{
  /**
   * Return the block contents
   *
   * {@inheritdoc}
   */
  public function build()
  {
    $config = $this->getConfiguration();
    return [
      '#markup' => "Hello {$config['some_text']}"
    ];
  }
  /**
   * Return a Form API array
   *
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state)
  {
    $form = parent::blockForm($form, $form_state);
    $config = $this->getConfiguration();
    $form['some_text'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Some Text'),
      '#default_value' => isset($config['some_text']) ? $config['some_text'] : 'Jonathan',
    ];
    return $form;
  }
  /**
   * Update the configuration values from the form state
   *
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state)
  {
    $this->configuration['some_text'] = $form_state->getValue('some_text');
  }
}
example-drupal-block.php

Block Form

That’s pretty darn similar!

Summary

Both classes now do the same following things, with the remaining differences primarily being class/method signatures or other internal APIs (Drupal).

Similarities

  • Both systems use inheritance to ease the development of a new subtype.
    WordPress widgets extend the WP_Widget class
    Drupal blocks extend BlockBase
  • Both provide a means of overriding the output of the parent class.
    WordPress calls this method widget()
    Drupal calls it build()
  • Both provide a means of overriding the configuration form of the parent class.
    WordPress calls this method form()
    Drupal calls it blockForm()
  • Both provide a means of saving configuration form values.
    WordPress calls it update()
    Drupal calls it blockSubmit()
  • Both save the configuration to the database on their own.

Differences

  • Drupal requires the use of many more internal APIs not specifically related to the Block API.
  • Drupal’s build() method must return a render array.
    WordPress expects the widget to echo its contents.
  • Drupal’s blockForm() method must return a Form API array.
    WordPress expects the widget to echo the form immediately.
  • On submission of the configuration form:
    Drupal needs you to set the new values within the block’s configuration array
    WordPress expects you to return an array with the new values

That’s not so different!

0 Thoughts

Discussion

Leave a Reply

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