Drupal 8 PSR-4 Form compatibility in Drupal 7

This post is sponsored by Capgemini.

Up until Drupal 8 there has been little to encourage well organised code. It now has PSR-4 autoloading so your classes are automatically included. Even though Drupal 8 is just round the corner, a lot of us will still be using Drupal 7 for quite a while, however that doesn’t mean we can’t benefit from this structure in Drupal 7.

This post covers two parts:

  1. Autoloading class files.
  2. Avoiding extra plumbing to hook into your class methods.

You’re probably familiar with drupal_get_form(‘my_example_form’) which then looks for a function my_example_form(). The issue is that your form definition will no longer be in such a function but within a method in a class. To cover both these parts we will be using two modules:

  1. XAutoLoad - Which will autoload our class.
  2. Cool - Which allows us to abstract the usual functions into class methods.

Drupal 8 was originally using PSR-0 which has been deprecated in favour of PSR-4. As a consequence the Cool module uses PSR-0 in its examples although it does support PSR-4. We will create an example module called psr4_form.

The information on autoloading and folder structure for PSR-4 in Drupal 8 states that we should place our form class in psr4_form/src/Form/FormExample.php however the cool module instead loads from a FormControllers folder: psr4_form/src/FormControllers/FormExample.php.

We can get round this by providing our own hook_forms() as laid out in the Cool module:

<?php
/**
* Implements hook_forms().
*/
function psr4_form_forms($form_id, $args) {
 
$classes = \Drupal\cool\Loader::mapImplementationsAvailable('Form', '\Drupal\cool\Controllers\FormController');
  unset(
$classes['Drupal\\cool\\BaseForm']);
  unset(
$classes['Drupal\\cool\\BaseSettingsForm']);
 
$forms = array();
  foreach (
$classes as $class_name) {
   
$forms[$class_name::getId()] = array(
     
'callback' => 'cool_default_form_callback',
     
'callback arguments' => array($class_name),
    );
  }

  return
$forms;
}
?>

If you are ok placing your class in the FormControllers folder then you can omit the above function to keep your .module file simple or you could put the hook in another module. Potentially the Cool module could be updated to reflect this.

This class requires a namespace of the form Drupal\<module_name>\Form. It also extends the BaseForm class provided by the Cool module so we don't need to explicitly create our form functions:

<?php
namespace Drupal\psr4_form\Form;

class
FormExample extends \Drupal\cool\BaseForm {
  ...
}
?>

Within our FormExample class we need a method getId() to expose the form_id to Drupal:

<?php
public static function getId() {
  return
'psr4_form';
}
?>

And of course we need the form builder:

<?php
public static function build() {
 
$form = parent::build();
 
$form['my_textfield'] = array(
    
'#type' => 'textfield',
    
'#title' => t('My textfield'),
   );

   return
$form;
}
?>

All that is left is to define your validate and submit methods.

At the time of writing, the Cool module isn’t up to date with Drupal 8 Form API conventions. I started this blog post with the intention of a direct copy and paste of the src folder. Unfortunately the methods don't quite follow the same conventions and they also need to be static:

Drupal 7 Drupal 8
getId getFormId
build buildForm
validate validateForm
submit submitForm

This example module can be found at https://github.com/oliverpolden/psr4_form.

Links

Modules

Information

Post new comment

By submitting this form, you accept the Mollom privacy policy.

User login

Author of...

  • @Casablanca Looks like a great time last night. Sorry I couldn't make it :( 12 years 28 weeks ago
  • Our new homepage is live http://t.co/iwNX1tWZ 12 years 28 weeks ago
  • Can you help with conditionally setting the 'from' in mails sent with notifications/messaging modules #drupal http://t.co/ItE75IlW 12 years 28 weeks ago
  • My post about highjacking #Drupal menu items with 'drupal_get_form' callbacks for creating popups or #ahah goodness http://t.co/Pe9wSz6k 12 years 29 weeks ago
  • Oh the conflict within. An entire section of a #drupal site was built bespoke, do I add a bespoke subsection, or rewrite the entire section? 12 years 32 weeks ago
  • @psd It depends. Serving static pages means https has a larger relative impact. If there's a lot of processing, https is relatively small. 12 years 33 weeks ago
  • Just had a play with the #drupal Field collection module. goo.gl/p6sEn A really nice Drupal 7 implementation of the multigroup module. 12 years 33 weeks ago
  • @philhawksworth @a_alfredo When will scampcat have the descriptions pop up when you hover over the markers? 12 years 33 weeks ago
Oliver Polden