On the Joys of Raising Free-Range node.tpl.php Links

Ah, chickens -- delicious chickens. Its a timeless truth, however, that not all chickens were born equal. And clearly, the best tasting chickens are those who've been allowed to feed, graze, and socialize on the open range.

Alas, this is not a white paper on the art of raising free-range chickens. Rather, its a tutorial on raising free-range node.tpl.php links such as "add new comment", "read more", or any other link which the multitudes of modules spew forth into that disgustingly generic $links variable. By the end of this tutorial you will no longer be limted by the $links variable. Instead, you will have the necessary code and knowledge to turn any link into a variable that you can place at any point in your node.tpl.php file.

Enter the Sausage Factory

Below is a self contained template.php file that "makes the magic happen". Its commented heavily, as I don't assume this code is necessarily self evident. That said, I am assuming you know SOMETHING about the template.php file. If you don't, then you probably should google it real quick to get a halfway decent background.


function _phptemplate_variables($hook, $vars) {
switch ($hook) {
case "node":
/*As everyone under 40 knows, $vars['node']->links is an array which can be split up using the foreach(). Like... duh */
foreach ($vars['node']->links as $link) {
/*Do the nasty thang with preg_match... truth be told, I have no idea how this thing works. Rest assured however this method is dirty, unsanitary, and very cruel to the poor CPU usage of webservers. However, there is apparently no alternative at the moment (this will change in 4.8, according to my sources). How nasty is this method? Well.. I can't actually use the codefilsters for it because the below function causes it to think the php script is ending. So in a real PHP script this is supposed to just continue as though there was no ending...*/?>
preg_match("/]*).*?>(.*?)<\/a>/i",$link, $matches);<?php
/*Now we take our sliced $links carcus, and take out the bones. Or, rather, we've split up the url of the link, and text of the links into a further set of arrays. The text is split up by onespace. the URLs are split up by "/" Thus, the $textparts is an array that has split up the "read more" into "read", and "more". $urlparts will likely be a sliced array that has "node", and "[some number in it]"*/
$textparts = explode(" ", $matches[2]);
$urlparts = explode("/", $matches[1]);
/*I am an idiot, and cannot for the life of me remember wtf $matches[1] is. So I've named them cyborg-monkey-hybrid-friendly names. You'll always want to use $linkurl as your link's URL. Sometimes, you might not want the default title in which case you will be free to add your own title. THEN, sometimes you'll only be interested in attaching a CSS classname so that you can style your links differently. Your smart... I trust you'll figure it out. Remember: you are very special. */
$linkurl = $matches[1];
$default_title = $matches[2];
/*This switch statement is where the "magic" begins! */
switch (true) {
/*As you'll no doubt note, I've gone ahead and renamed "user's blog" to "User's Blizizog". I trust you can understand whow hyperlinks work. Therefore, I hope you will start to realize how dreadfully simple this method is. All that is required is the ability to look at either the URL, or the name of the hyperlink, and see a workd that is unique enough to allow you to extract the delicious link. In thise case, we know that the $user's blog link is going to without a doubt contain the word "blog". More or less, "case in_array("blog", $urlparts)" says "yo, PHP! If one of the array values of $urlparts is "blog", than that's our stoopid blog link. */
case in_array("blog", $urlparts):
$linktitle = $vars['node']->name."'s Blizizog";
$bloglink =
$feedlink =
/*Obviously, we'll need to pass our link to the node.tpl.php file. Below, we've done just that. Since you've probably noticed that we $vars['bloglink'] */
$vars['bloglink'] = $bloglink ." | ".$feedlink;
/*This method could be improved, but unfortunately, the nature of the l() function stumped me, ad I could only get this working by hardcoding the HREF links. However, if someone else can figure it out, perhaps we could make this more efficent, and easy to work with. Below is something of an example of how I image it working out eventually. A lot like the forms API arrays... I assume */
case in_array("forward", $urlparts):
$stylecodename = "emaillink";
$linktitle = "email page";
$vars['emaillink'] =
case in_array("comment", $textparts):
case in_array("comments", $textparts):
$stylecodename = "commentlink";
$vars['commentlink'] =
case in_array("read", $textparts):
$stylecodename = "readmorelink";
$vars['readmorelink'] = ''.$default_title.'';
case in_array("printer", $textparts):
$vars['printlink'] =
'Print Page';
$vars['otherlinks'] .= ''.$default_title.'';
return $vars;

Wasn't that fun?! I'm tired, so I am going to just go ahead and provide the node.tpl.php file that is working on this blog to help you get started. I don't have a lot of time these days, so I apologize for the quick explanation. However, at the very least, I hope this will help a few of you on the path towards raising free-range node links. There is joy in it. Truly.


<?php if ($page == 0) { ?>
type; ?>">

<?php print_r(date("F j, Y", strtotime($date))); ?> | <?php print $node_title; ?>

<?php print $content;?>

<?php print $readmorelink;?>
<?php print $commentlink;?>

<?php } else { ?>

<?php print $bloglink;?>

  • <?php print $commentlink;?>
  • <?php print $printlink;?>
  • <?php print $emaillink;?>

type; ?>">

Posted by <?php print $name; ?>
<?php print $date; ?>

<?php print $content; ?>

<?php } ?>