Problem: once render($content) is called, show($content['element'] will affect the array, but subsequent calls to render($content) will render the cached copy of $content, which was generated prior to the show($content['element']) call.
Steps to reproduce:
// We hide the comments and links now so that we can render them later.
hide($content['comments']);
print render($content);
// show comments
show($content['comments']);
//attempt to print content again but $content will be printed without comments.
print render($content);
//comments are printed
print render($content['comments']);
If we never render $content, the hide/show functions work.
hide($content['comments']);
hide($content['links']);
show($content['comments']);
print render($content);
Also if you copy $content to foo, and then call print render($foo), the comments will be printed
// We hide the comments and links now so that we can render them later.
hide($content['comments']);
print render($content);
// show comments
show($content['comments']);
//copy $content to $foo
$foo = $content
//attempt to print content again but $content will be printed without comments.
print render($content);
//comments are printed along with
print render($food)
//comments are printed
print render($content['comments']);
Expected Behavior: once show(&$element) is called, print render($content) prints the entire content, including the array element we set to show.
Actual Behavior: show(&$element) updates the array, but print render ($content) prints a cached version of the array.
Comments
Comment #1
kanani commentedTurns out its the same behavior for hide(&$element) as well. Once render($content) is called, any subsequent calls to render(&$content) will return the cached render, regardless of any calls to show/hide.
This is perfectly valid for $content since you should theoretically not be printing it twice, but for other variables you may want to do that. At a minimum the API should note this.
Comment #2
damien tournoud commentedThere is no such thing as the "cached copy of $content", except for the render cache, but I strongly doubt that you are running into it.
This is the expected behavior:
Comment #3
damien tournoud commentedComment #4
kanani commentedI annotated the expected behaviour code from #2 and dropped it into node.tpl.php.
Actual behavior is different. The second call to render($content) returns the content. (See http://api.drupal.org/api/function/render/7 which says that call to render(&$element) always returns the top level element)
Also the very last call to print render($content['comments']); returns the comments, even though they were previously rendered.
Comment #5
jhodgdonI wasn't quite convinced by kanani's test, so I altered it a bit...
What I found:
If you have $content containing $content['comments']...
- If you call print render($content), you get the whole thing. After that, if you call hide($content['comments']) and then print render($content) again, you still get the whole thing -- the hide() has no effect.
- If you call hide($content['comments']) first, before the first render, then subsequent calls to show($content['comments']) do not affect the output of print render($content) at all.
Which is what kanani reported.
It is actually the expected behavior if you look at the doc for drupal_render() -- it is going to set the #printed status flag at the top level the first time through, so it will never look deeper after that first call.
However, that is not what is documented in render(), show(), and hide(). I think this is just a doc problem, and should be fixed on the other doc issue that kanani reported
#930000: show(), hide(), and render() documentation is misleading
For reference, here's the code I added to the top of my node.tpl.php to test this. Remove the first print render($content) line to test that if you hide initially, subsequent shows do nothing; leave it in to test that if it's shown initially, subsequent hides do nothing.
So I think I'll mark this as "fixed" as a support request, and leave the doc issue open. Feel free to disagree :)
Comment #6
kanani commentedI think
is right on. And we should thank RockSoup for first surfacing this issue at his session at the Vancouver PNW Summit 2010