1

I have a structure in database, and I want it printed. So in hook menu I have entry with

'page callback' => 'mymodule_mystructure_display',

And in inc file I have

function mymodule_mystructure_display($id_structure) {
  $mystructure= something(); // Data preparation
  return $mystructure;
}

And I have all helpers set up so in mystructure.tpl.php I can simply use:

kpr($mystructure);

and it all works, so let me omit details for now, they are covered in Examples for Developers anyway.

The real struggle is with files.

In $mystructure['files'] I have a nested array like this:

array(2) {
  [0]=>
  array(2) {
    ["name"]=>
    string(26) "Display name of first file"
    ["fid"]=>
    int(34)
  }
  [1]=>
  array(2) {
    ["name"]=>
    string(27) "Display name of second file"
    ["fid"]=>
    int(62)
  }
}

where ["fid"] corresponds to {file_managed}.fid field in Drupal's database.

What's the cleanest way to output links to files, with ["name"] used as link text?

What I'm doing now is pretty dirty:

  1. In function mymodule_mystructure_display I foreach or array_walk over files.

  2. For each element, I take file id, and use this helper function on it:

    _uri_by_id($id) {
      $file = file_load($id);
      return $file->uri;
    }
    
  3. Result is fed to file_create_url function, and it's result is saved under ["url"] index, to give me this array in $mystructure['files']:

    array(2) {
      [0]=>
      array(2) {
        ["name"]=>
        string(26) "Display name of first file"
        ["fid"]=>
        int(34)
        ["url"]=>
        string(50) "http://example.com/sites/default/files/example.pdf"
      }
      [1]=>
      array(2) {
        ["name"]=>
        string(27) "Display name of second file"
        ["fid"]=>
        int(62)
        ["url"]=>
        string(50) "http://example.com/sites/default/files/example.txt"
      }
    }
    
  4. In mystructure.tpl.php I use l() to print actual link:

    echo l($item["name"], $item["url"]);
    

This all works. But it feels bad. I was always a backend guy, my frontend knowledge is somehow lacking. But I'm sure there should be a shorter way from managed file ID to a link. So what would it be?

Note: value under ["name"] is derived from $mystructure, it is not something taken directly from file object. This pretty much stopped me from using theme_file_link(). But even if it wouldn't be the problem, I still need to load file object manually to use theme_file_link().

2

I'd personally prefer something like this:

// Extract file IDs so we only run one file_load().
$fids = array_map($mystructure['files'], function($x) { return $x['fid']; });
$files = file_load_multiple($fids);

$build = array();
foreach ($mystructure['files'] as $file) {
  // Update the description
  $files[$file['fid']]->description = $file['name'];

  // Add to the build
  $build[] = array(
    '#theme' => 'file_link',
    '#file' => $files[$file['fid']],
  );
}

return $build;

A bit cleaner/more performant, and using as much core API as possible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.