I'm writing a module and in this I connect to a database and collect some titles of a bunch of lab protocols which I then list. I also get the protocol id connected to each title and I would like for a user to be able to click one of the titles and then be taken to a page where you will see something like this(* = this content will be displayed differently depending on which title you clicked):

"The clicked title*

Abstract

The current abstract*

Materials

The current materials*

Instructions

The current instructions* "

My problem is I'm not sure of how to do this. I taught of using the function l() and have it always link to the same node which when loaded is modified to show the protocol content that belongs with the clicked title. But I don't know how to do this using l(), or even if I really should do this. And I don't know how to create the preprepared node that should be filled with specific content.

I taught of maybe using any of these function for this:

hook_node_info
hook_node_load

I'm mostly asking if this seems like a good idea at all and if so how I should proceed? Or does anyone have any better idea of how to do this?

Here is my module so far(the relevant parts):


//Fetches title and id from external db
 function view_protocols_contents(){ 

   db_set_active('protocols');
   //Use Database API to retrieve current posts.

   $query = db_select('protocol', 'n')->extend('PagerDefault')->limit(8);
  $query->join('protocol_abstract', 'a', 'n.protocol_id=a.protocol');
$result = $query
  ->fields('n', array('protocol_id', 'title'))
  ->fields('a', array('abstract_usage'))
  ->execute();

  db_set_active('default');
 
    return $result;
}


function view_protocols_menu() {
  $items = array();

  $items['admin/config/content/view_protocols'] = array(
    'title' => 'View protocols',
    'description' => 'Configuration for View protocols module',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('view_protocols_form'),
    'access arguments' => array('access administration pages'),
    'type' => MENU_NORMAL_ITEM,
  );

$items['view_protocols'] = array(
    'title' => 'View protocols',
    'page callback' => '_view_protocols_pagy',
    'access arguments' => array('access view_protocols content'),
    'type' => MENU_NORMAL_ITEM, //Will appear in Navigation menu. (Why automatically in Navigation menu?)
  );

  return $items;
}

/**
 * Custom page callback function, declared in view_protocols_menu().
 */
function _view_protocols_pagy() {
  $result = view_protocols_contents();
  //Array to contain items for the page to render.
  $items = array();
  
//Iterate over the resultset and format as links.
  foreach ($result as $node) {
     $items[] = array(
		      'data' => t($node->title)."<br>".t($node->abstract_usage),
    ); 
  }

   if (empty($items)) { 
    $page_array['view_protocols_arguments'] = array(
      //Title serves as page subtitle
      '#title' => t('All protocols in MolMeth:'),
      '#markup' => t('No protocols available.'),
    );
    return $page_array;  
  }
  else { 
    $page_array['view_protocols_arguments'] = array( 
      'first_para' => array(
        '#title' => t('All protocols in MolMeth'),
        '#items' => $items,			    
        '#theme' => 'item_list__view_protocols',
      ),
      'second_para' => array(
	'#theme' => 'pager',  
      ),
    );
    return $page_array;
    } 
}

Comments

jaypan’s picture

In a situation like this, you register a path with a wildcard. For example:

function my_module_menu()
{
  $menu['my_path/%'] = array // % is the wildcard
  (
    'title' => 'some title',
    'page callback' => 'my_module_callback',
    'page arguments' => array(1), // passing the index of the wildcard, which passes the wildcard
    'access callback' => TRUE, // this always allows access for everyone. Done in this case for the sake of convenience
  );
}

function my_module_callback($key) // $key will be the value passed in the wildcard
{
   // the below is an example of what could theoretically be done
  $some_name = db_query('SELECT name FROM {some_table} WHERE some_id = :id', array(':id' => $key))->fetchField();
  // do something with $some_name below this
}

Then you can build your links with the path you registered:

$ids[0] = 'item1';
$ids[1] = 'item2';
$ids[2] = 'item3';

$items = array();
$items[] = l(t('Item 1'), 'my_path/' . $ids[0]);
$items[] = l(t('Item 1'), 'my_path/' . $ids[1]);
$items[] = l(t('Item 1'), 'my_path/' . $ids[2]);

$list = theme('item_list', array('items' => $items));

Contact me to contract me for D7 -> D10/11 migrations.

numfar85’s picture

The linking works nicely, now I just need to get the links to actually go somewhere. I think I could make a function i the module which returns a render array that contains what I want to show, but I am more unsure of how to get that content into a page that has the path that was defined with the wildcard. How do I do that?

jaypan’s picture

It's already done with what I showed you. By registering a path and a callback function, the data returned from that callback function is shown as a page when accessing that path.

Contact me to contract me for D7 -> D10/11 migrations.

numfar85’s picture

When I click on the link it says:

"Access denied
You are not authorized to access this page."

Does the $menu have to be called that? I called it $items in my hook_menu function.

Like this:

function view_protocols_menu() {
  $items = array();

  $items['admin/config/content/view_protocols'] = array(
    'title' => 'View protocols',
    'description' => 'Configuration for View protocols module',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('view_protocols_form'),
    'access arguments' => array('access administration pages'),
    'type' => MENU_NORMAL_ITEM,
  );

$items['view_protocols'] = array(
    'title' => 'View protocols',
    'page callback' => '_view_protocols_pagy',
    'access arguments' => array('access view_protocols content'),
    'type' => MENU_NORMAL_ITEM, //Will appear in Navigation menu. (Why automatically in Navigation menu?)                                       
  );

$items['my_path/%'] = array // % is the wildcard                                                                                                
  (
   'title' => 'Protocol',
   'page callback' => '_view_protocols_tjoho',
   'page arguments' => array(1), // passing the index of the wildcard, which passes the wildcard                                                
   'access callback' => TRUE, // this always allows access for everyone. Done in this case for the sake of convenience                          
   );

  return $items;
}


jaypan’s picture

hook_menu() is cached - you need to clear your cache after making any changes/additions/deletions to it.

Contact me to contract me for D7 -> D10/11 migrations.

numfar85’s picture

How do I access the 'page arguments' array which passed the wildcard value to the callback function when I want to use it in the callback function?

jaypan’s picture

Look in my original code, it's $key in my_callback(). Whatever you set as the page arguments gets passed as a variable to your callback function.

Contact me to contract me for D7 -> D10/11 migrations.