1

UPDATE: I know that I could accomplish this inside of a tpl.php file. But I would prefer to keep as much logic in the template.php file as possible, reserving tpl.php adjustments for markup. I have been informed that Drupal is NOT an MVC paradigm but an AOP, and I am trying to adapt to that as quickly as possible. But I feel that since I have already accomplished this IN the Template.php file that there is bound to be a 'Best Practices' way of doing this that I would like to adopt.

Currently, I have a node_field called field_unique_card. This is a Boolean field. If field_unique_card == 1 then the title of the node needs to be something like this:

$title = '* ' . $title;

The way I am currently doing it is as follows:

UPDATE: I just remembered the better way of (expr1)?(expr2):(expr3); so I updated my preprocess function.

function theme_preprocess_node(&$variables)
{
    ...
    $variables['title'] =  $variables['field_unique_card'][0]['value'] ? '*' . $variables['title'] : '';
}

I am wondering if this is 'Drupal Best Practices' or if there is a smarter way? I ask because this only affects the nodes when they are displayed as a field. But on every node display there is an additional output of the Node title that happens at the top of the page. I can't figure out how to make it so that the title shows the * there as well.

Any help would be greatly appreciated.

3 Answers 3

1

It's a little confusing at first, but the main page title (usually the <h1> tag) is in page.tpl.php. If you look at the standard node.tpl.php file...

<?php if (!$page): ?>
  <h2<?php print $title_attributes; ?>><a href="<?php print $node_url; ?>"><?php print $title; ?></a></h2>
<?php endif; ?>

the title variable that you're overriding in the node preprocess function, won't affect the title of the node if it's being displayed as a full page. This is completely by design so that the main page title can be consistently set in a single place (the page template file).

That makes it a slightly strangled route, and what seems like a simple task becomes a bit messy. You could implement a hook_preprocess_page function, check for a node in the current page, and adjust accordingly:

function MYTHEME_preprocess_page(&$vars) {
  if ($node = menu_get_object()) {
    if (MYTHEME_node_is_unique_card($node)) {
      $vars['title'] = '*' . $vars['title'];
    }
  }
}

If you're using Drupal 6 you can also add

$vars['head_title'] = $vars['title'];

straight after setting the title, to alter the <head> title of the document (should you need to make it match). If you're using Drupal 7, that logic would move to hook_preprocess_html().

Now as this is Drupal, there are other ways to do this too, with a custom module.

For Drupal 6, you can implement hook_nodeapi() to intercept the node view and alter the title:

function MYMODULE_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  if ($node->type == 'my_type' && some_other_condition($node)) {
    // If this ISN'T a teaser view.
    if (!$a3) {
      drupal_set_title('*' . $node->title);
    }
  }
}

Or the same thing for Drupal 7, using hook_node_view()

function MYMODULE_node_view($node, $view_mode, $langcode) {
  if ($node->type == 'my_type' && $view_mode == 'full' && some_other_condition($node)) {
    drupal_set_title('*' . $node->title);
  }
}

There's usually more than one way to do something in Drupal so it can get pretty confusing; my best advice is to pick a process/workflow that works for you and stick with it. Your attempts to separate logic from presentation are spot on. The less logic in a template file, the better for so many reasons.

Regarding design patterns - You'll never get Drupal to respect a true MVC architecture in my opinion, but you can certainly apply some of the disciplines to Drupal development.

Some people have their own ideas on that though, and claim MVC in Drupal is possible. From a purists' point of view I can't agree with that thought, but there are some interesting articles out there (including that one) that might help explain how to shoehorn that thinking into a Drupal site.

1
  • Thank you. It's the preprocess_page function that will do it. I just didn't want to generate so many preprocess functions. But I don't see how else to do this... it seems that that is the Drupal way. Commented May 21, 2013 at 15:57
2

The easiest (and less expensive) way I see to do this is as follows (did not try this, but should work):

  1. Copy node.tpl.php from the core node module (/modules/node) to your theme's folder (/sites/all/themes/).
  2. Modify the code to display the desired title. By default the code to display the title is:

    <h2<?php print $title_attributes; ?>>
      <a href="<?php print $node_url; ?>"><?php print $title; ?></a>
    </h2>
    

    can be changed to:

    <h2<?php print $title_attributes; ?>>
      <?php if($unique_card == 1) { ?>
        <a href="<?php print $node_url; ?>"><?php print "*" . $title; ?></a>
      <?php } else { ?>
        <a href="<?php print $node_url; ?>"><?php print $title; ?></a>
      <?php } ?>
    </h2>
    

    Note: I used the variable $unique_card because the comments from node.tpl.php mentions:

    Field variables: for each field instance attached to the node a corresponding variable is defined; for example, $node->body becomes $body. When needing to access a field's raw values, developers/themers are strongly encouraged to use these variables. Otherwise they will have to explicitly specify the desired field language; for example, $node->body['en'], thus overriding any language negotiation rule that was previously applied.

2
  • That IS an answer that would work. But it doesn't directly answer my question. I'm trying to keep as much logic in my template.php and do just formatting in my tpl.php files. So can you give me any clues on how to do this inside of template.php versus inside of a tpl.php? Commented May 17, 2013 at 19:50
  • @randomblink - I mentioned at the very beginning of the answer that this way is less expensive. What I meant by that is you don't need extra database queries or any other function to achieve the desired result. The field variables are already defined, just have to use them. I also acknowledge the purpose of keeping the formatting and logic different. If you wish to do so, clive has mentioned the right way of doing it :)
    – AjitS
    Commented May 20, 2013 at 9:42
0

To address one of your sub-questions, namely

I am wondering if this is 'Drupal Best Practices' or if there is a smarter way?

Drupal's common practice is to keep it in node.tpl.php

Drupal's practice is to split logic into files corresponding to parts of this logic, like node's logic to node.tpl.php, main html logic to html.tpl.php and so on. This way it's easier to find malfunctioning part and revert it from backup without reverting changes in totally unrelated parts.

Of course you can feel free to ignore it, especially if you aren't planning to share.

4
  • 1
    I know this is a bit picky and probably just semantics, but it's presentation that should be in template files, the logic should be in preprocess functions :)
    – Clive
    Commented May 18, 2013 at 11:40
  • The big question is - what is "title". Some might argue it belongs to a model, not templates at all... And prepending a star is presentation for me. Heck, how "logic" is it when you can do it in CSS?
    – Mołot
    Commented May 18, 2013 at 13:23
  • Yeah that's exactly the point in trying to make in the last part of my answer. You can't consider Drupal from an MVC perspective, it just doesn't work. In the Drupal paradigm, the title should be altered in the preprocess function, not the template file. It may or may not be a presentation concern, depending on whether or not the prep ended text is business logic (eg SEO). Bottom line, Drupal 7 doesn't facilitate clean code structure very well. Drupal 8 is a different beast though, can't wait for that
    – Clive
    Commented May 18, 2013 at 13:38
  • @Molot adding a star COULD be done in CSS, but I wanted the asterisk to match the styling of the font. This way if I change out CSS files for my site the asterisk would fit itself correctly. Commented May 21, 2013 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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