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
[pastacode lang=”php” manual=”%3C%3Fphp%0Aclass%20ExampleWidget%20extends%20WP_Widget%20%7B%0A%09%2F**%0A%09%20*%20ExampleWidget%20constructor.%0A%09%20*%2F%0A%09function%20__construct()%20%7B%0A%09%09parent%3A%3A__construct(%0A%09%09%2F%2F%20id_base%0A%09%09%09’example_widget_id’%2C%0A%09%09%09%2F%2F%20title%0A%09%09%09__(%20’My%20example%20widget’%20)%2C%0A%09%09%09%2F%2F%20widget%20options%0A%09%09%09array(%0A%09%09%09%09’classname’%20%20%20%3D%3E%20’examplewidget’%2C%0A%09%09%09%09’description’%20%3D%3E%20__(%20’My%20example%20is%20great!’%20)%0A%09%09%09)%0A%09%09)%3B%0A%09%7D%0A%0A%09%2F**%0A%09%20*%20Echo%20the%20widget%20contents%20to%20the%20screen%0A%09%20*%0A%09%20*%20%40param%20array%20%24args%0A%09%20*%20%40param%20array%20%24instance%0A%09%20*%2F%0A%09function%20widget(%20%24args%2C%20%24instance%20)%20%7B%0A%09%09print%20%22Hello%20%7B%24instance%5B’some_text’%5D%7D%22%3B%0A%09%7D%0A%0A%09%2F**%0A%09%20*%20Display%20the%20widget%20form%20to%20the%20screen%0A%09%20*%0A%09%20*%20%40param%20array%20%24instance%0A%09%20*%2F%0A%09function%20form(%20%24instance%20)%20%7B%0A%09%09%24default_values%20%3D%20array(%0A%09%09%09’some_text’%20%3D%3E%20’Jonathan’%2C%0A%09%09)%3B%0A%09%09%24instance%20%3D%20wp_parse_args(%20%24instance%2C%20%24default_values%20)%3B%0A%09%09%3F%3E%0A%20%20%20%20%20%20%20%20%3Clabel%20for%3D%22%3C%3Fphp%20print%20%24this-%3Eget_field_id(%20’some_text’%20)%20%3F%3E%22%3E%3C%3Fphp%20_e(‘Some%20Text’)%20%3F%3E%3C%2Flabel%3E%0A%20%20%20%20%20%20%20%20%3Cinput%20type%3D%22text%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%22%3C%3Fphp%20print%20%24this-%3Eget_field_id(%20’some_text’%20)%20%3F%3E%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22%3C%3Fphp%20print%20%24this-%3Eget_field_name(%20’some_text’%20)%20%3F%3E%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%3D%22%3C%3Fphp%20print%20esc_html(%20%24instance%5B’some_text’%5D%20)%20%3F%3E%22%20%2F%3E%0A%09%09%3C%3Fphp%0A%09%7D%0A%0A%09%2F**%0A%09%20*%20Sanitize%20a%20new%20instance%20array%20and%20return%20it%0A%09%20*%0A%09%20*%20%40param%20array%20%24new_instance%0A%09%20*%20%40param%20array%20%24old_instance%0A%09%20*%2F%0A%09function%20update(%20%24new_instance%2C%20%24old_instance%20)%20%7B%0A%09%09%24instance%5B’some_text’%5D%20%3D%20sanitize_text_field(%20%24new_instance%5B’some_text’%5D%20)%3B%0A%09%09return%20%24instance%3B%0A%09%7D%0A%7D” message=”example-wordpress-widget.php” highlight=”” provider=”manual”/]
Widget Form
Drupal 8 Block Example
[pastacode lang=”php” manual=”%3C%3Fphp%0Anamespace%20Drupal%5Cexample_block%5CPlugin%5CBlock%3B%0Ause%20Drupal%5CCore%5CBlock%5CBlockBase%3B%0Ause%20Drupal%5CCore%5CBlock%5CBlockPluginInterface%3B%0Ause%20Drupal%5CCore%5CForm%5CFormStateInterface%3B%0A%2F**%0A%20*%20Provide%20a%20simple%20Block%20to%20Drupal.%0A%20*%0A%20*%20%40Block(%0A%20*%20%20%20id%20%3D%20%22example_block%22%2C%0A%20*%20%20%20admin_label%20%3D%20%40Translation(%22My%20example%20block%22)%0A%20*%20)%0A%20*%2F%0Aclass%20ExampleBlock%20extends%20BlockBase%20implements%20BlockPluginInterface%0A%7B%0A%20%20%2F**%0A%20%20%20*%20Return%20the%20block%20contents%0A%20%20%20*%0A%20%20%20*%20%7B%40inheritdoc%7D%0A%20%20%20*%2F%0A%20%20public%20function%20build()%0A%20%20%7B%0A%20%20%20%20%24config%20%3D%20%24this-%3EgetConfiguration()%3B%0A%20%20%20%20return%20%5B%0A%20%20%20%20%20%20’%23markup’%20%3D%3E%20%22Hello%20%7B%24config%5B’some_text’%5D%7D%22%0A%20%20%20%20%5D%3B%0A%20%20%7D%0A%20%20%2F**%0A%20%20%20*%20Return%20a%20Form%20API%20array%0A%20%20%20*%0A%20%20%20*%20%7B%40inheritdoc%7D%0A%20%20%20*%2F%0A%20%20public%20function%20blockForm(%24form%2C%20FormStateInterface%20%24form_state)%0A%20%20%7B%0A%20%20%20%20%24form%20%3D%20parent%3A%3AblockForm(%24form%2C%20%24form_state)%3B%0A%20%20%20%20%24config%20%3D%20%24this-%3EgetConfiguration()%3B%0A%20%20%20%20%24form%5B’some_text’%5D%20%3D%20%5B%0A%20%20%20%20%20%20’%23type’%20%3D%3E%20’textfield’%2C%0A%20%20%20%20%20%20’%23title’%20%3D%3E%20%24this-%3Et(‘Some%20Text’)%2C%0A%20%20%20%20%20%20’%23default_value’%20%3D%3E%20isset(%24config%5B’some_text’%5D)%20%3F%20%24config%5B’some_text’%5D%20%3A%20’Jonathan’%2C%0A%20%20%20%20%5D%3B%0A%20%20%20%20return%20%24form%3B%0A%20%20%7D%0A%20%20%2F**%0A%20%20%20*%20Update%20the%20configuration%20values%20from%20the%20form%20state%0A%20%20%20*%0A%20%20%20*%20%7B%40inheritdoc%7D%0A%20%20%20*%2F%0A%20%20public%20function%20blockSubmit(%24form%2C%20FormStateInterface%20%24form_state)%0A%20%20%7B%0A%20%20%20%20%24this-%3Econfiguration%5B’some_text’%5D%20%3D%20%24form_state-%3EgetValue(‘some_text’)%3B%0A%20%20%7D%0A%7D” message=”example-drupal-block.php” highlight=”” provider=”manual”/]
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 theWP_Widget
class
Drupal blocks extendBlockBase
- Both provide a means of overriding the output of the parent class.
WordPress calls this methodwidget()
Drupal calls itbuild()
- Both provide a means of overriding the configuration form of the parent class.
WordPress calls this methodform()
Drupal calls itblockForm()
- Both provide a means of saving configuration form values.
WordPress calls itupdate()
Drupal calls itblockSubmit()
- 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’sconfiguration
array
WordPress expects you to return an array with the new values
That’s not so different!
Discussion