Hướng dẫn tạo Drupal 7 Content Type Search Block chỉ với 5 Steps

I recently had a need for a search form in a sidebar, that would search a specific content type. Since the content type I needed to search for was already indexed by the search module, I wanted to stick with core Drupal searching. I didn’t really want to mess with altering an advanced search form, so I came up with the following solution, which only took 5 easy steps.

Step 1: Create the form

Let’s start by creating a simple form with a single text field and a submit button:

function mymodule_search_block_form($form, &$form_state) {
  $form['keys'] = array(
    '#type' => 'textfield',
    '#size' => 15,
    '#required' => TRUE,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Search',
  );
  return $form;
}

Step 2: Create the form handler

function mymodule_search_block_form_submit($form, &$form_state) {
  drupal_goto('custom/node/search/' . $form_state['values']['keys']);
}

This handler is a simple drupal_goto, which points to the menu callback path that we will define in step 3.

Step 3: Create the search results menu callback

function mymodule_menu() {
  $items['custom/node/search/%'] = array(
    'page callback' => 'mymodule_do_search',
    'page arguments' => array(3),
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

This is a standard Drupal menu callback. We are using mymodule_do_search as the page callback, and argument 3 which is our wildcard, will be our page argument.

Step 4: Create the Search Results Callback Function

function mymodule_do_search($keys) {
  // set the page title
  drupal_set_title('FAQ search results');
  // get the search results
  $results = module_invoke('node', 'search_execute', $keys . " type:faq");
  return theme('search_results', array('results' => $results));
}

We start off by setting the page title with a drupal_set_title. We display the search keys in the title by using arg(3). Next, we set the $results array using the module_invoke function. The module_invoke function is a very useful tool that allows us to call another module’s function. In this case we are calling the node module’s search_execute function, using $keys . " type:faq" as the argument. The . " type:faq" portion is what narrows the search to just the faq content type.

Now that we’ve got the $results array loaded up, we return the results using the search_results theme function.

Step 5: Create the Search Form Block

The last thing we need to do, is make the search form available in a block.

function mymodule_block_info() {
  $blocks['faq_search'] = array(
    'info' => t('FAQ Search Block'),
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}
 
function mymodule_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'faq_search':
      $block['title'] = 'Custom FAQ Search';
      $block['content'] = drupal_render(drupal_get_form('mymodule_search_block_form'));
      break;
  }
  return $block;
}

The block hook got split into 2 separate hooks in Drupal 7, so we now have hook_block_info and hook_block_view. As you can see, we do a drupal_get_form, in conjunction with a drupal_render to add the search form to the block’s contents. Now we just need to place the search block into the site using either the core block setup, or context.

Until next time, happy searching!