Skip directly to content

Forms & Database in Drupal 8

rteijeiro's picture
on Thu, 10/03/2013 - 00:24

In the previous post we learnt how to create a menu link to access our forms so now we will learn how to create those forms. For our Bingo module, we will need two forms, one to add participants to the contest and other to delete participants from the contest.

Let's start with the form to add participants. We need to implement \Drupal\Core\Form\FormInterface and override it's methods. You can take a look at all available methods in core/lib/Drupal/Core/Form/FormInterface.php file. The following code implements our AddForm class:

lib/Drupal/bingo/AddForm.php

<?php                                                                                                                                       

namespace Drupal\bingo;

use Drupal\Core\Form\FormInterface;

class AddForm implements FormInterface {

Now whe can implement our own methods starting with getFormID to identify our form with an unique ID:

  function getFormID() {
    return 'bingo_add_form';
  }

And create our form fields in the same way we did it in Drupal 7:

  /*
   * {@inheritdoc}
   */
  function buildForm(array $form, array &$form_state) {
    $form['name'] = array(
      '#type' => 'textfield',
      '#title' => t('Participant'),
    );

    $form['actions'] = array('#type' => 'actions');

    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Add'),
    );

    return $form;
  }

To create the form to delete participants we extend Drupal\Core\Form\ConfirmFormBase class implementing our own methods. You can take a look at core/lib/Drupal/Core/Form/ConfigFormBase.php file to see all available methods. We start with our class extension:

lib/Drupal/bingo/DeleteForm.php

<?php                                                                                                                                       

namespace Drupal\bingo;

use Drupal\Core\Form\ConfirmFormBase;

class DeleteForm extends ConfirmFormBase {

And then implement our method to customize confirm text in form button, for example:

  /*
   * {@inheritdoc}
   */
  function getConfirmText() {
    return t('Delete');
  }

The second part of this post is related to Database access. We need to connect our form requests to the database in order to get and send out data. For that purpose we need a specific controller for our database architecture. We will create it in BingoStorage.php file, and it's contents can be something like:

lib/Drupal/bingo/BingoStorage.php

<?php                                                                                                                                       

namespace Drupal\bingo;

class BingoStorage {

  // Returns all participant names stored in database.
  static function getAll() {
    return db_query('SELECT name FROM {bingo}')->fetchCol();
  }

  /*
   * Stores participant name in database.
   *
   * @param $name
   *   participant name.
   */
  static function add($name) {
    db_insert('bingo')->fields(array('name' => $name))->execute();
  }

  /**
   * Deletes participant name in database.
   *
   * @param $name
   *   participant name.
   */
  static function delete($name) {
    db_delete('bingo')->condition('name', $name)->execute();
  }
}

As you can see we have implemented two methods, one to create participants in the database and other to delete them. Yes, I know it needs some error handling to avoid warnings but, who cares? Maybe in a future post :P

Now we can add participants to our database using the add form:

lib/Drupal/bingo/AddForm.php

  /*
   * {@inheritdoc}
   */
  function submitForm(array &$form, array &$form_state) {
    $name = $form_state['values']['name'];

    BingoStorage::add($name);

    drupal_set_message(t('Added %name as new participant.', array('%name' => $name)));

    $form_state['redirect'] = 'bingo';
  }

As you can see we call BingoStorage::add($name); that is automatically loaded following the PSR-0 autoloader specification.

In the same way we can delete participants using the delete form:

lib/Drupal/bingo/DeleteForm.php

  /*                                                                                                                                        
   * {@inheritdoc}
   */
  function submitForm(array &$form, array &$form_state) {
    BingoStorage::delete($this->name);

    drupal_set_message(t('Participant %name deleted.', array('%name' => $this->name)));

    $form_state['redirect'] = 'bingo';
  }

Just take a look at Bingo module repository to see full code examples and how this module works like a charm ;)

In the next post I will try to explain the new template system introduced in Drupal 8. Yes, it's Twig!!

Comments

penyaskito's picture

Thanks for posting about Drupal8!

But one question: why BingoStorage has static methods?

I think it's a bad idea for unitesting it with phpunit. Maybe twig should wait and next post should be about Dependency Injection? 0:-) 

rteijeiro's picture

Sure, I should try to spend more time understanding that and explain it in a future post. Thanks for the suggestion, cabesa!

keopx's picture

Thanks "tocayo", good job and you post about drupal 8 develment!

Post new comment