In this blog, I am going to cover
1.What is a hook?
2.Important hooks in drupal 7. (I am not listing all the hooks ,but some commonly used hooks in drupal)
3.How can we create our own hooks?
Hooks is a PHP function that is named foo_bar where foo is the name of the module and bar is the name of the hook. We can use this function in a drupal module file.
Hooks can interact with the core code of the drupal. It can be used to override the core functionalities. Hooks occur at various points in the thread of the execution. The behaviour of the hooks differs one from another.
eg : hook_menu, hook_theme, hook_block_info etc.
Imagine you have a drupal code base. You want to set one variable in the drupal database when a node is created.
In terms of the PHP , we can check where they have implemented the functionality for the node creation and can directly add a logic there.
But in terms of Drupal, Drupal is a CMS it has its own coding standards. Team has implemented hook functionalities to interfere with drupal core instead of directly changing the drupal core.
Always use hooks. Never touch the drupal core.
So i will suggest you to use hook_node_save.
If you are a Drupal developer, you might be familiar with hooks.I am going to list and elaborate some hooks that we can suggest for any web development.
This hook is used to generate a menu link in drupal (same as a link).
Returns an associative array which contains key as paths and values as the property (key-value) for each path.
eg: I have a drupal module "myfirstmodule"
function myfirstmodule_menu() {
$items['hello'] = array(
'page callback' => 'myfirstmodule_display_hello',
);
return $items;
}
//This is not a hook.
function myfirstmodule_display_hello() {
print 'hello';
}
I want to create a menu which should take arguments in the page callback.
function myfirstmodule_menu() {
$items['root/videos/funny'] = array(
'page callback' => 'myfirstmodule_display_message',
'page arguments' => array(1, 2, TRUE)
);
return $items;
}
//This is not a hook.
function myfirstmodule_display_message($first_level, $second_level, $show_message) {
if ($show_message) {
print 'you are in '.$first_level . '/'. $second_level;
}
}
Arguments can be given as an array. The arguments can be given from the url and we should specify the index of the argument in the url which starts from 0. Also we can pass variables and default values.
Note:
This concept is different from the navigation menus in the drupal as this hook_menu is based on page callback. All the menus created using hook_menu will be saved in menu_router table.
This hook is related with hook_menu. If you understand the above hook, this will be very easier to grasp.
This hook is used to alter the menu path properties of an existing menu. Before the call back this hook will be executed
hook_menu -> take the call back from the menu_router -> hook_menu_alter -> (my logic)
One of the most important menu in drupal core is the node. I can alter the page call back for this node using this hook.
/**
* Implements hook_menu_alter.
* Implements my page call back for the drupal nodes.
*/
function mytestmodule_menu_alter(&$items) {
$items['node']['page callback'] = 'mytestmodule_render_node';
}
/**
* Callback to disallow access for the anonymous user.
*/
function mytestmodule_render_node(){
//my logic goes here.
}
Note:
Always use hook_menu_alter to change a callback defined in the core.You can alter any property of the menu path by this menu.
A block is a piece of content which we can display in a region.
This hook is used to register the drupal blocks.It defines all blocks provided by the module.
Return value
An associative array containg the key as block machine name and values as the properies (key-value) for the block.
The properties or configurations of the block are
1.info - This will display the human readable name of the block in the block configurations page.
2.cache - Block caching has a great significance in the perfomance.
The values allowed are
DRUPAL_CACHE_PER_USER: The block can change depending on the user viewing the page. This setting can be resource-consuming for sites with large number of users, and should only be used when DRUPAL_CACHE_PER_ROLE is not sufficient.
DRUPAL_CACHE_PER_PAGE: The block can change depending on the page being viewed.
DRUPAL_CACHE_GLOBAL: The block is the same for every user on every page where it is visible.
DRUPAL_CACHE_CUSTOM: The module implements its own caching system.
DRUPAL_NO_CACHE: The block should not get cached.
If the same static code is used in all pages for a block ,go for DRUPAL_CACHE_GLOBAL and it will be fast. But never use it if you are having the conditions for the block view.
etc...
To see the full configs , go to https://api.drupal.org/api/drupal/modules%21block%21block.api.php/function/hook_block_info/7
All info will be updated in the {block} table.
This hook is used to display the block to the user that is defined by the hook_block_info. The logic for each block goes inside this hook.
hook_block_view($delta = '')
$delta is an argument holding the current block machine name. This can be used to provide logic for each block.
Imagine i have an html content to render as a block.
Code :
<h1>My First Drupal Block</h1>
<p>This is a trial version of my block</p>
Using the hook_block_info , i will register my block
function mytestmodule_block_info() {
$blocks['mytestblock'] = array(
'info' => t('My First Drupal Block'),
'cache' => DRUPAL_CACHE_GLOBAL,
);
}
Using the hook_block_view, I will store the block contents to render it on some region.
function hook_block_view($delta = '') {
if ($delta == 'mytestblock') {
$block['content'] = array(
'#type' => 'markup'
'#prefix' => '',
'#suffix' => '',
'#markup' => '<h1>My First Drupal Block</h1>' . '\n'
. '<p>This is a trial version of my block</p>',
);
return $block;
}
I have a requirement to show it on every pages. So i can use DRUPAL_CACHE_GLOBAL and it will increase perfomance.
This hook should be written in the .install file of the drupal module. As it will execute only while installing the module.
Suppose you want to set one variable in db while installing the module, you can use the hook_install.
eg :
function mytestmodule_install() {
variable_set('mytestmodule_enabled_time', REQUEST_TIME);
}
This hook will be triggered when the module got uninstalled.
Suppose you want to delete the variable from the database while uninstalling a module ,you can use hook_uninstall
eg:
function mytestmodule_uninstall() {
variable_del('mytestmodule_enabled_time';
}
This hook is used to create a new table in the database.
A Drupal schema definition is an array structure representing one or more tables and their related keys and indexes. A schema is defined by hook_schema() which must live in your module's .install file.
/**
* Implements hook_schema().
*/
function mytestmodule_schema() {
$schema['mytestmodule_table'] = array(
'description' => 'The base table for mytestmodule',
'fields' => array(
'id' => array(
'description' => 'Primary key with type; a unique id for the item.',
'type' => 'int',
'not null' => TRUE,
'unsigned' => TRUE,
'default' => 0,
),
'name' => array(
'description' => 'test name for the table',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
),
'primary key' => array('id'),
)
);
return $schema
}
The hook will be executed before rendering html.tpl.php file in drupal. The renderable array can be altered in this hook before the render.
Eg:
Requirement :
Suppose there is a requirement to alter the seo title of the page and we can achieve this from the hook_preprocess_html.
function mytestmodule_preprocess_html(&$variables) {
$variables['head_title'] = 'my test site';
}
Any renderable contents can be changed before rendering the page contents using this hook. We can also add new renderable arrays with the help of this hook.
EG:
The requirement is to render one more html content to the header of the page before rendering.
function mytestmodule_preprocess_page(&$variables) {
$variables['page']['header']['myhtml'] = array('#type' => 'markup', '#markup' => '<p>hello</p>');
}
Content in myhtml array will render while rendering the header region contents.
Any renderable contents can be changed before rendering the node contents using this hook. We can also add new renderable arrays with the help of this hook.
EG:
Imagine a node of type 'my_node_type' with five fields to be rendered. I want to unset a field (my_field) from displaying to the user and
this can be done in preprocess_node.
function mymodule_preprocess_node(&$variables) {
if ($variables['node']->type == 'my_node_type') {
unset($variables['content']['my_field']);
}
}
This hook will execute before rendering a block in a region.
Eg: I want to redirect my block to render in my own tpl file (block--my-default.tpl.php) and i will do the following in my block preprocessor.
$variables['theme_hook_suggestions'][] = 'block__my_default';
This hook is run at the beginning of the page request. When this hook is called ,the theme and module are already loaded in the memory.
Eg: I want to set some variables before drupal renders my block or page.
function mymodule_init() {
$node = menu_get_object();
switch($node->type) {
case 'a' : $my_param = 'this_a';
break;
case 'b' : $my_param = 'param_b';
break;
//********
default: $my_param = 'default';
break;
//line ends here
}
variable_set('loaded_page_info', $my_param);
}
This hook is run at the beginning of the page request. This will be called before the module and theme are loaded into the memory.
Now the most interesting part in drupal. Imagine a case in drupal where we are dealing with our own hooks. Hooks should be created only when there is a scope for reusablity. Instead of coming to your module everytime for the same change ,you can implement your own hooks.
Eg:
I have created a module for rendering a field collection in my own way. But tommorow other person using this module wants to change the content of a field collection item before rendering. Here comes the requirement and easiness of creating our own hooks.
You need to create an api file for implementing the hooks.The API file should be your_module.api.php . Implement the hook function in this file
eg: function hook_custom_field_collection_render_alter(&$content) {
//logic goes here.
}
This function will be called when ever my custom module is rendering a field collection. But how my module know this hook? For that point , i will describe details in next step.You can leave it as empty if you don't want to do anything here.
In my custom module for rendering a field collection, i am using drupal_render($content) in line number 37.
$content is a renderable array
eg:
// Render my content.
drupal_render($content);
But before rendering field collection, i want to alter the content. I have already defined my hook in api file.
function custom_field_collection_render($items) {
//*********
Line number 34 //Since we are targeting $content , we need to pass it as an argument.
Line number 35 module_invoke_all('custom_field_collection_render_alter' , $content);
Line number 36 // Render my content.
Line number 37 drupal_render($content);
//************
}
Now it will be available in all the modules. So we should write our own hooks to alter the definitions present in the api file.
Implement my hook
function mymodule_custom_field_collection_render_alter(&$content) {
//logic goes here.
}
Hope you understood the hooks techniques in drupal.
Thanks,
Vishnu
1.What is a hook?
2.Important hooks in drupal 7. (I am not listing all the hooks ,but some commonly used hooks in drupal)
3.How can we create our own hooks?
1.What is a hook?
1.1Simple Definition
Hooks is a PHP function that is named foo_bar where foo is the name of the module and bar is the name of the hook. We can use this function in a drupal module file.
1.2In Depth
Hooks can interact with the core code of the drupal. It can be used to override the core functionalities. Hooks occur at various points in the thread of the execution. The behaviour of the hooks differs one from another.
eg : hook_menu, hook_theme, hook_block_info etc.
1.3Why we require hooks?
Imagine you have a drupal code base. You want to set one variable in the drupal database when a node is created.
In terms of the PHP , we can check where they have implemented the functionality for the node creation and can directly add a logic there.
But in terms of Drupal, Drupal is a CMS it has its own coding standards. Team has implemented hook functionalities to interfere with drupal core instead of directly changing the drupal core.
Always use hooks. Never touch the drupal core.
So i will suggest you to use hook_node_save.
2. Important Hooks in drupal 7
If you are a Drupal developer, you might be familiar with hooks.I am going to list and elaborate some hooks that we can suggest for any web development.
2.1. hook_menu
Simple defintion
This hook is used to generate a menu link in drupal (same as a link).
Returns an associative array which contains key as paths and values as the property (key-value) for each path.
eg: I have a drupal module "myfirstmodule"
function myfirstmodule_menu() {
$items['hello'] = array(
'page callback' => 'myfirstmodule_display_hello',
);
return $items;
}
//This is not a hook.
function myfirstmodule_display_hello() {
print 'hello';
}
I want to create a menu which should take arguments in the page callback.
function myfirstmodule_menu() {
$items['root/videos/funny'] = array(
'page callback' => 'myfirstmodule_display_message',
'page arguments' => array(1, 2, TRUE)
);
return $items;
}
//This is not a hook.
function myfirstmodule_display_message($first_level, $second_level, $show_message) {
if ($show_message) {
print 'you are in '.$first_level . '/'. $second_level;
}
}
Code Explanation
Arguments can be given as an array. The arguments can be given from the url and we should specify the index of the argument in the url which starts from 0. Also we can pass variables and default values.
Note:
This concept is different from the navigation menus in the drupal as this hook_menu is based on page callback. All the menus created using hook_menu will be saved in menu_router table.
2.2 hook_menu_alter
This hook is related with hook_menu. If you understand the above hook, this will be very easier to grasp.
This hook is used to alter the menu path properties of an existing menu. Before the call back this hook will be executed
hook_menu -> take the call back from the menu_router -> hook_menu_alter -> (my logic)
One of the most important menu in drupal core is the node. I can alter the page call back for this node using this hook.
/**
* Implements hook_menu_alter.
* Implements my page call back for the drupal nodes.
*/
function mytestmodule_menu_alter(&$items) {
$items['node']['page callback'] = 'mytestmodule_render_node';
}
/**
* Callback to disallow access for the anonymous user.
*/
function mytestmodule_render_node(){
//my logic goes here.
}
Note:
Always use hook_menu_alter to change a callback defined in the core.You can alter any property of the menu path by this menu.
2.3 hook_block_info
A block is a piece of content which we can display in a region.
This hook is used to register the drupal blocks.It defines all blocks provided by the module.
Return value
An associative array containg the key as block machine name and values as the properies (key-value) for the block.
The properties or configurations of the block are
1.info - This will display the human readable name of the block in the block configurations page.
2.cache - Block caching has a great significance in the perfomance.
The values allowed are
DRUPAL_CACHE_PER_USER: The block can change depending on the user viewing the page. This setting can be resource-consuming for sites with large number of users, and should only be used when DRUPAL_CACHE_PER_ROLE is not sufficient.
DRUPAL_CACHE_PER_PAGE: The block can change depending on the page being viewed.
DRUPAL_CACHE_GLOBAL: The block is the same for every user on every page where it is visible.
DRUPAL_CACHE_CUSTOM: The module implements its own caching system.
DRUPAL_NO_CACHE: The block should not get cached.
If the same static code is used in all pages for a block ,go for DRUPAL_CACHE_GLOBAL and it will be fast. But never use it if you are having the conditions for the block view.
etc...
To see the full configs , go to https://api.drupal.org/api/drupal/modules%21block%21block.api.php/function/hook_block_info/7
All info will be updated in the {block} table.
2.4 hook_block_view
This hook is used to display the block to the user that is defined by the hook_block_info. The logic for each block goes inside this hook.
hook_block_view($delta = '')
$delta is an argument holding the current block machine name. This can be used to provide logic for each block.
Imagine i have an html content to render as a block.
Code :
<h1>My First Drupal Block</h1>
<p>This is a trial version of my block</p>
Using the hook_block_info , i will register my block
function mytestmodule_block_info() {
$blocks['mytestblock'] = array(
'info' => t('My First Drupal Block'),
'cache' => DRUPAL_CACHE_GLOBAL,
);
}
Using the hook_block_view, I will store the block contents to render it on some region.
function hook_block_view($delta = '') {
if ($delta == 'mytestblock') {
$block['content'] = array(
'#type' => 'markup'
'#prefix' => '',
'#suffix' => '',
'#markup' => '<h1>My First Drupal Block</h1>' . '\n'
. '<p>This is a trial version of my block</p>',
);
return $block;
}
}
I have a requirement to show it on every pages. So i can use DRUPAL_CACHE_GLOBAL and it will increase perfomance.
5. hook_install
This hook should be written in the .install file of the drupal module. As it will execute only while installing the module.
Suppose you want to set one variable in db while installing the module, you can use the hook_install.
eg :
function mytestmodule_install() {
variable_set('mytestmodule_enabled_time', REQUEST_TIME);
}
6.hook_uninstall
This hook will be triggered when the module got uninstalled.
Suppose you want to delete the variable from the database while uninstalling a module ,you can use hook_uninstall
eg:
function mytestmodule_uninstall() {
variable_del('mytestmodule_enabled_time';
}
6.hook_schema
This hook is used to create a new table in the database.
A Drupal schema definition is an array structure representing one or more tables and their related keys and indexes. A schema is defined by hook_schema() which must live in your module's .install file.
/**
* Implements hook_schema().
*/
function mytestmodule_schema() {
$schema['mytestmodule_table'] = array(
'description' => 'The base table for mytestmodule',
'fields' => array(
'id' => array(
'description' => 'Primary key with type; a unique id for the item.',
'type' => 'int',
'not null' => TRUE,
'unsigned' => TRUE,
'default' => 0,
),
'name' => array(
'description' => 'test name for the table',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
),
'primary key' => array('id'),
)
);
return $schema
}
7. hook_preprocess_html
The hook will be executed before rendering html.tpl.php file in drupal. The renderable array can be altered in this hook before the render.
Eg:
Requirement :
Suppose there is a requirement to alter the seo title of the page and we can achieve this from the hook_preprocess_html.
function mytestmodule_preprocess_html(&$variables) {
$variables['head_title'] = 'my test site';
}
8. hook_preprocess_page
Any renderable contents can be changed before rendering the page contents using this hook. We can also add new renderable arrays with the help of this hook.
EG:
The requirement is to render one more html content to the header of the page before rendering.
function mytestmodule_preprocess_page(&$variables) {
$variables['page']['header']['myhtml'] = array('#type' => 'markup', '#markup' => '<p>hello</p>');
}
Content in myhtml array will render while rendering the header region contents.
9. hook_preprocess_node
Any renderable contents can be changed before rendering the node contents using this hook. We can also add new renderable arrays with the help of this hook.
EG:
Imagine a node of type 'my_node_type' with five fields to be rendered. I want to unset a field (my_field) from displaying to the user and
this can be done in preprocess_node.
function mymodule_preprocess_node(&$variables) {
if ($variables['node']->type == 'my_node_type') {
unset($variables['content']['my_field']);
}
}
10. hook_preprocess_block
This hook will execute before rendering a block in a region.
Eg: I want to redirect my block to render in my own tpl file (block--my-default.tpl.php) and i will do the following in my block preprocessor.
$variables['theme_hook_suggestions'][] = 'block__my_default';
11. hook_init
This hook is run at the beginning of the page request. When this hook is called ,the theme and module are already loaded in the memory.
Eg: I want to set some variables before drupal renders my block or page.
function mymodule_init() {
$node = menu_get_object();
switch($node->type) {
case 'a' : $my_param = 'this_a';
break;
case 'b' : $my_param = 'param_b';
break;
//********
default: $my_param = 'default';
break;
//line ends here
}
variable_set('loaded_page_info', $my_param);
}
12.hook_boot
This hook is run at the beginning of the page request. This will be called before the module and theme are loaded into the memory.
3.How can we create our own hooks in drupal?
Now the most interesting part in drupal. Imagine a case in drupal where we are dealing with our own hooks. Hooks should be created only when there is a scope for reusablity. Instead of coming to your module everytime for the same change ,you can implement your own hooks.
Eg:
I have created a module for rendering a field collection in my own way. But tommorow other person using this module wants to change the content of a field collection item before rendering. Here comes the requirement and easiness of creating our own hooks.
step1.
You need to create an api file for implementing the hooks.The API file should be your_module.api.php . Implement the hook function in this file
eg: function hook_custom_field_collection_render_alter(&$content) {
//logic goes here.
}
This function will be called when ever my custom module is rendering a field collection. But how my module know this hook? For that point , i will describe details in next step.You can leave it as empty if you don't want to do anything here.
step2.
In my custom module for rendering a field collection, i am using drupal_render($content) in line number 37.
$content is a renderable array
eg:
// Render my content.
drupal_render($content);
But before rendering field collection, i want to alter the content. I have already defined my hook in api file.
function custom_field_collection_render($items) {
//*********
Line number 34 //Since we are targeting $content , we need to pass it as an argument.
Line number 35 module_invoke_all('custom_field_collection_render_alter' , $content);
Line number 36 // Render my content.
Line number 37 drupal_render($content);
//************
}
Now it will be available in all the modules. So we should write our own hooks to alter the definitions present in the api file.
step 3.
Implement my hook
function mymodule_custom_field_collection_render_alter(&$content) {
//logic goes here.
}
Hope you understood the hooks techniques in drupal.
Thanks,
Vishnu