Last updated August 8, 2012. Created by jn2 on March 24, 2011.
Edited by PFreeman, nicxvan, kim-day. Log in to edit this page.
Drupal hook described: hook_block_view()
Main functions described: user_access(), l(), theme()
The next step in this tutorial is to take the data we generated in our custom function and turn it into content for the block. We will do this using hook_block_view. This function returns two values, 'subject', which is the title of the block, and 'content', which is self-documenting. Once again, we will use a switch structure. This structure allows for additional blocks to be added in the future if needed. The $delta parameter tells the function which block is being requested.
Access check
Here's the first part of the code:
<?php
function current_posts_block_view($delta = '') {
switch($delta){
case 'current_posts':
$block['subject'] = t('Current posts');
if(user_access('access content')){
//Retrieve and process data here.
}
?>Best practice dictates that information displayed to the user be assessed against that user's permissions. Here we implement the most basic of checks, 'access content'. You can use any permission here that Drupal supplies, or even create your own. For a list of permission names, go to People > List (tab) (or http://example.com/admin/people). In the permission dropdown there, you will find a list of the machine readable names that you can use in your code. This list will include all permissions active on your site, including those created by contrib modules. The names in the Permissions tab (http://example.com/admin/people/permissions) are not the machine readable names.
Another way to find permissions set in core modules is through the API reference. Enter the module name followed by _permission, for example, node_permission. You'll get a list of all the permissions that node defines. Knowing which one to use might be a bit tricky. For example, the access content permission we use here is actually defined in the node module, not the block module.
Coding the data as links
Here's the next bit of code:
<?php
//Use our custom function to retrieve data.
$result = current_posts_contents();
//Array to contain items for the block to render.
$items = array();
//Iterate over the resultset and format as links.
foreach ($result as $node){
$items[] = array(
'data' => l($node->title, 'node/' . $node->nid),
);
}
?>First we use our custom function to save the data into the $result variable. The $items variable gives us a place to store the processed data. We then iterate over the resultset, processing each item and formatting it as a link.
Notice the actual link is created by the l() function. (That's a small case 'L'.) The first parameter sets the link text, in this case the node's title. The second parameter is the actual link path. The path to any node is always "node/#", where # is the ID number of the node. l() uses this path to generate appropriate links, adjusting the URL to the installation's URL configuration.
Theming the data
Drupal's presentation layer is a pluggable system known as the theme layer. Each theme can take control of most of Drupal's output, and has complete control over the CSS. Theming in Drupal is a vast subject with entire books devoted to the subject. Here we will merely touch the surface with a theme function. Later in the tutorial, we will delve into render arrays.
Here's the last section of code for current_posts_block_view:
<?php
if (empty($items)) { //No content in the last week.
$block['content'] = t('No posts available.');
} else {
//Pass data through theme function.
$block['content'] = theme('item_list', array(
'items' => $items));
}
}
return $block;
}
}
?>First, we allow for the possibility of no content that fits our criteria. Your module's block should appear whether or not new content from the last week exists on your site.
If the $items variable contains data, it goes to the theme() function. The first argument of this function is the theme hook. Drupal includes many default theme hooks you can use with this function; see Default theme implementations for the complete list. We have chosen to theme our data as an unordered list, the theme_item_list theme hook. The second argument passes the content to be themed.
You may wonder why the code takes this form if the function is theme_item_list. theme() looks for a theme function called theme_hookname, where 'hookname' is the first argument, in this case, item_list. In other words, the second part of the hook name becomes the first argument when the function is called, telling the theme function which of its default versions to use.
The whole function
<?php
/**
* Implements hook_block_view().
*
* Prepares the contents of the block.
*/
function current_posts_block_view($delta = '') {
switch($delta){
case 'current_posts':
$block['subject'] = t('Current posts');
if(user_access('access content')){
//Use our custom function to retrieve data.
$result = current_posts_contents();
//Array to contain items for the block to render.
$items = array();
//Iterate over the resultset and format as links.
foreach ($result as $node){
$items[] = array(
'data' => l($node->title, 'node/' . $node->nid),
);
}
if (empty($items)) { //No content in the last week.
$block['content'] = t('No posts available.');
}
else {
//Pass data through theme function.
$block['content'] = theme('item_list', array(
'items' => $items));
}
}
return $block;
}
}
?>(Remember not to include the opening or closing PHP tags when you add this section.)
Comments
Undefined variable block
Hi,
I tested this code and Drupal gave me this error:
Notice: Unidefned variable: block at current_posts_block_view() (line ...)
I changed the
return $blockline into the switch statment, the error disappear, but the block never appear. Is this correct?Δ
I suspect that you have a hook_block_info() that defines a value for
$deltathat you don’t mention in theswitchstatement.$blockmust be defined in eachcaseof theswitchstatement, and there must be acasefor each$delta– or you could use adefaultclause, but that wouldn’t make a lot of sense.___________________
It’s in the detaιls…
You should change $query =
You should change
$query = db_select('node', 'n')
->fields('n', array('nid'))
to
$query = db_select('node', 'n')
->fields('n', array('nid', 'title'))
The problem is that we must retrieve also the field 'title' from the database,
otherwise the result data lack such a property, making $node->title, an error.
Fix found
Hi agein,
I found the mistake in this code, before of line
switch($delta){put
$block = array();The module apear in the place chosen.
I don't have this problem,
I don't have this problem, the code in the example works perfectly well. (I am using PHP version 5.3.2-1ubuntu4.9)
Server error after adding the switch statement
Okay, so I've been following along with the tutorial just fine. Up until now.
When creating the current_posts_block_view() function, I get a server error (error 500) when I reload the modules page and toggle the module as being enabled.
If I comment out all statements in the function, one at a time to trace the issue, I have t remove everything except for:
<?phpfunction current_posts_block_view($delta = '') {
switch($delta) {
/*case 'current_posts':
$block['subject'] = t('Current posts');
......
}
*/
}
}
?>
I've tried changing the case value (you have it as 'current_posts', what is this name for?) and other things, but can't get beyond this issue. Any suggestions?
Yours,
twobit
Disregard this. I had an
Disregard this. I had an added
<?php}
?>
Problem is now though, I get no errors withe the module, but when I enable the module, turn the block on (and put it to header area), I get nothing displayed.
where is it displayed ?
I don't know if the code is working ? I don't know where it should be displayed ?
The code is so obscure for me...
theme() early or late?
There seems to be a disconnect between some of the documentation and presentations I've come across for Drupal 7, which are urging developers to adopt the model of deferring theming as late as possible, and other docs (like this page) which throw in a theme() call in the middle of things without any explanation of why they're not leaving the rendering of that portion of the page until the end. Is this an oversight? Or is there a subtle concept at work that I just haven't understood yet?
You're right. The D7 API
You're right. The D7 API documentation for hook_block_view (http://api.drupal.org/api/drupal/modules--block--block.api.php/function/...) does specify that a renderable array is preferred as the return value for "content", although an HTML string is acceptable, so the code above still works. I'm not yet proficient enough to update this tutorial to use render arrays, but you can see an example on the API page I linked.
Render arrays
This is a very long tutorial that covers a lot of ground. If you are in a hurry to get to render arrays, go to http://drupal.org/node/1118218.
_______________________________________________________
Beginner to intermediate Drupal 7 training using screen share
User didn't have access to a file but can see file link
Thank you for this great tutorial that help me lot.
But I remark that user didn't have access to a file but can see file link in the block. And when he clicks on link, he can't see file. That is good! But, can't we do better to not show that link since user hasn't access on file?
I think the test "if(user_access('access content'))" is applied to the block and not to each node return of block.
Forms in blocks
Suppose i have a block that provides a small form:
<?phpfunction mymod_block_view($delta = '') {
switch($delta) {
case 'mymod':
$block['subject'] = null;
if(user_access('access content')){
$block['content'] = drupal_get_form('mymod_form');
}
}
return $block;
}
?>
How would I pass this through the theme layer?
Strange Parameter Value
I use this example to create my custom module. Everything is working fine and I thank you for that.
Everything is working fine, the only issue i m facing is in the function below
<?php
function mytt_block_view($delta = '') {
$block = array();
<strong> drupal_set_message("mytt_block :".$delta );</strong>
?>
the output is
mytt_block :mytt_profile
mytt_block :current_posts
mytt_block :mytt
mytt_block :mytt_towntalking
The problem is I changed the name of Blocks and the blocks in bold do not exist anymore but they are still being called. I clear the cache, restart my Vista/Wamp many times but they are still showing. any clue?
$delta variable explanation
Hi, I'm enjoying reading this tutorial and it's proving very useful. On this page an explanation of the $delta variable would be handy as it hasn't (yet) been covered. Also an explanation as to why it is set to equal an empty string when it's passed to the function. Thanks.
I now understand that it's
I now understand that it's not being set to the empty string - this is just a default value if the variable isn't previously defined. My ignorance of php at fault, but would probably still be useful to explain.