Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

Form API Drupal 7 creating forms on Drupal

17/04/2025, by Ivan

In previous lessons, we got acquainted with the hooks hook_block_info(), hook_block_view(), hook_menu(), hook_permission(), and now we can programmatically create as many pages and blocks as we need. In this lesson, we’ll explore the Drupal 7 Form API for creating forms. We'll build a form for administering module functionality and try to use as many of the hooks we've already learned to solidify our skills.

To start, we will display 3 blocks. I believe this won’t be difficult for you.

function sitemade_block_info(){
    $blocks = array();
    $blocks[1]['info'] = 'User list';
    $blocks[2]['info'] = 'Node list';
    $blocks[3]['info'] = 'Term list';
    return $blocks;
}

function sitemade_block_view($delta = '') {
    $block = array();
    switch ($delta) {
        case 1:
            $block['subject'] = 'Users';
            $block['content'] = '';
            $query = db_select('users', 'u')
                ->fields('u', array('uid', 'name'))
                ->orderBy('u.uid', 'DESC')
                ->range(0, 5)
                ->execute();
            $users = $query->fetchAll(PDO::FETCH_ASSOC);
            foreach ($users as $user) {
                $block['content'] .= '

'; } break; case 2: $block['subject'] = 'Nodes'; $block['content'] = ''; $query = db_select('node', 'n') ->fields('n', array('nid', 'title')) ->orderBy('n.nid', 'DESC') ->range(0, 10) ->execute(); $nodes = $query->fetchAll(PDO::FETCH_ASSOC); foreach ($nodes as $node) { $block['content'] .= '

'; } break; case 3: $block['subject'] = 'Terms'; $block['content'] = ''; $query = db_select('taxonomy_term_data', 't') ->fields('t', array('tid', 'name')) ->orderBy('t.tid', 'DESC') ->range(0, 10) ->execute(); $terms = $query->fetchAll(PDO::FETCH_ASSOC); foreach ($terms as $term) { $block['content'] .= '

'; } break; } return $block; }

We clear the cache so that our new blocks appear in the admin interface. We display these blocks in the left sidebar:

Drupal blocks

Now let’s create an admin page, where we will later place a form for administering these three blocks:

function sitemade_permission() {
    return array(
        'admin content blocks' => array(
            'title' => t('Admin content blocks'),
            'description' => t('Nodes, Users, Terms'),
        ),
    );
}

function sitemade_menu() {
    $items = array();
    $items['admin/config/content/content_blocks'] = array(
        'title' => 'User, node, term blocks',
        'description' => 'Block administration',
        'page callback' => '_sitemade_content_blocks',
        'access arguments' => array('admin content blocks'),
    );
    return $items;
}

function _sitemade_content_blocks() {
    $content = 'Lorem ipsum!';
    return $content;
}

After creating the page, you should see a placeholder at admin/config/content/content_blocks:

Drupal admin page

Next, let’s set permissions for the administrator to view this page (this is why we added hook_permission()):

Drupal permission

Now we’ll change the code of our hooks. First, let’s create the admin form. What will we administer in these three blocks? I suggest allowing configuration of the block title and the number of displayed entities (nodes, users, terms).

First, we change the ‘page callback’ property in hook_menu.

function sitemade_menu() {
    $items = array();
    $items['admin/config/content/content_blocks'] = array(
        'title' => 'User, node, term blocks',
        'description' => 'Block administration',
        'page callback' => 'drupal_get_form',
        'page arguments' => array('_sitemade_content_blocks'),
        'access arguments' => array('admin content blocks'),
    );
    return $items;
}

So, now we rewrite the _sitemade_content_blocks() function to return a form array.

function _sitemade_content_blocks() {
    $form = array();

    $form['nodes-title'] = array(
        '#type' => 'textfield',
        '#title' => t('Node block title'),
        '#default_value' => variable_get('node_block', ''),
        '#size' => 60,
        '#maxlength' => 64,
        '#description' => t('Title for node block'),
    );

    $form['node-selected'] = array(
        '#type' => 'select',
        '#title' => t('Nodes in block'),
        '#options' => drupal_map_assoc(range(1, 10)),
        '#default_value' => variable_get('node_block_range', 5),
        '#description' => t('Number of nodes to show'),
    );

    $form['users-title'] = array(
        '#type' => 'textfield',
        '#title' => t('User block title'),
        '#default_value' => variable_get('user_block', ''),
        '#size' => 60,
        '#maxlength' => 64,
        '#description' => t('Title for user block'),
    );

    $form['user-selected'] = array(
        '#type' => 'select',
        '#title' => t('Users in block'),
        '#options' => drupal_map_assoc(range(1, 10)),
        '#default_value' => variable_get('user_block_range', 5),
        '#description' => t('Number of users to show'),
    );

    $form['terms-title'] = array(
        '#type' => 'textfield',
        '#title' => t('Term block title'),
        '#default_value' => variable_get('term_block', ''),
        '#size' => 60,
        '#maxlength' => 64,
        '#description' => t('Title for term block'),
    );

    $form['term-selected'] = array(
        '#type' => 'select',
        '#title' => t('Terms in block'),
        '#options' => drupal_map_assoc(range(1, 10)),
        '#default_value' => variable_get('term_block_range', 5),
        '#description' => t('Number of terms to show'),
    );

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

    return $form;
}

We’ve displayed the form, now we need to process it. For processing we’ll use the hooks hook_formID_validate() and hook_formID_submit(), for validation and submission respectively.

function sitemade_content_blocks_submit($form, &$form_state) {
    variable_set('node_block', $form_state['values']['nodes-title']);
    variable_set('user_block', $form_state['values']['users-title']);
    variable_set('term_block', $form_state['values']['terms-title']);
    variable_set('node_block_range', $form_state['values']['node-selected']);
    variable_set('user_block_range', $form_state['values']['user-selected']);
    variable_set('term_block_range', $form_state['values']['term-selected']);
}

The form is now ready. After submission, data is saved using variable_set(), and later used to populate default field values using variable_get().

Drupal form submit

Lastly, update hook_block_view() so the block titles and number of listed items are read using variable_get().

function sitemade_block_view($delta = '') {
    $block = array();
    switch ($delta) {
        case 1:
            $block['subject'] = variable_get('user_block', 'Users');
            $block['content'] = '';
            $query = db_select('users', 'u')
                ->fields('u', array('uid', 'name'))
                ->orderBy('u.uid', 'DESC')
                ->range(0, variable_get('user_block_range', 5))
                ->execute();
            foreach ($query as $user) {
                $block['content'] .= '

'; } break; case 2: $block['subject'] = variable_get('node_block', 'Nodes'); $block['content'] = ''; $query = db_select('node', 'n') ->fields('n', array('nid', 'title')) ->orderBy('n.nid', 'DESC') ->range(0, variable_get('node_block_range', 5)) ->execute(); foreach ($query as $node) { $block['content'] .= '

'; } break; case 3: $block['subject'] = variable_get('term_block', 'Terms'); $block['content'] = ''; $query = db_select('taxonomy_term_data', 't') ->fields('t', array('tid', 'name')) ->orderBy('t.tid', 'DESC') ->range(0, variable_get('term_block_range', 10)) ->execute(); foreach ($query as $term) { $block['content'] .= '

'; } break; } return $block; }

Now you can view the result on the front page. And don’t forget: “Before leaving — clear the cache!”

Drupal block