I need to display a page in drupal that is created by a template and based on a specific record from my table.
I created the module "item" (as an example).
I made the item_menu hook:
$items['items/%item'] = array(
'title' => 'Items',
'page callback' => 'drupal_get_form',
'page arguments' => array('show_item', 1),
'access callback' => true,
'access arguments' => array(),
);
I created a load function for the item:
function item_load($itemid)
{
$sql = 'SELECT * FROM {items} it WHERE it.id = :itemid';
$result = db_query(
$sql,
array(':itemid' => $itemid),
array( 'target' => 'mydatabase' ));
$item = $result->fetchObject();
return $item;
}
Now I want to use a template to display the specifics for the item, so I made a item module
a item.tpl.php. and a item_theme hook to register the template:
function item_theme($existing, $type, $theme, $path)
{
return array(
'show_item' => array(
'template' => 'item',
'variables' => array(),
),
);
}
The final thing I need to do is pass the item object to the item.tpl.php so I can display the item properties.
But I don't know how to do this. How can I make the item known within the template??
I hope the question is clear enough. Thanks in advance.
[edit]
I found that arg(1) contains the value of the wildcard from the menu page arguments, should I use arg(1) to look up the item in the database?
You need to declare the names and default values for the vars you want to use in the variables part of your array in hook_theme:
function item_theme($existing, $type, $theme, $path) {
return array(
'show_item' => array(
'template' => 'item',
'variables' => array('var1' => NULL, 'var2' => NULL, 'etc...'),
),
);
}
Then call the theme function like this:
$item_output = theme('show_item', array('var1' => $a_var, 'var2' => $another_var));
** UPDATE **
To address the load() function being called 4 times you can use static vars to avoid the query being run every time:
function item_load($itemid) {
$items = &drupal_static(__FUNCTION__, array());
if (!isset($items[$itemid])) {
$sql = 'SELECT * FROM {items} it WHERE it.id = :itemid';
$items[$itemid] = db_query(
$sql,
array(':itemid' => $itemid),
array('target' => 'mydatabase')
)->fetchObject();
}
return $items[$itemid];
}
Related
<?php
function customtable_permission() {
return array(
'show people' => array(
'title' => t('List of people'),
'description' => t('The table'),
),
);
}
function customtable_menu() {
$items = array();
$items['people'] = array(
'type' => MENU_NORMAL_ITEM,
'title' => t('Title'),
'description' => 'This page should show a table from a remote DB',
'page callback' => 'customtable_db_data',
'access arguments' => array('show people'),
);
return $items;
}
function customtable_db_data() {
db_set_active('remote_database');
$results = db_query("SELECT * FROM {people}");
$header = array(t('Id'), t('Name'), t('Department'), t('Division'), t('Insurance'));
$rows = array();
foreach($results AS $result) {
$rows[] = array(
$result->id,
$result->name,
$result->department,
$result->division,
$result->insurance,
);
}
db_set_active('default');
return theme('table', array('header'=> $header, 'rows' => $rows));
}
?>
This all works fine and I can go to site.com/people and see the all the entries from the database printed nicely in a table
But I want text boxes where I can filter each column. Users can search by name or a specific insurance or department. I think it is possible programmatically, but I'd like to know if there is a more "drupal" approach. Content types have the ability to filter its fields. Am I to create a content type based on my query? I don't exactly know. Any assist is appreciated.
I think the best way to do this is migrate the query result to a drupal content type, to do this you need to use the migrate api.
-Install and enabled migrate and migrate_ui drupal modules.
-Create any content type you want with your fields.Using the drupal interface.
-Create a custom module, using migrate api. For example:
/sites/all/modules/custom/migrate_customtable/migrate_customtable.migrate.inc
function migrate_customtable_migrate_api() {
$api = array(
'api' => 2,
'groups' => array(
'custom_table' => array(
'title' => t('Custom Table'),
),
),
'migrations' => array(
'Projects' => array(
'class_name' => 'CustomTableMigration',
'group_name' => 'custom_table',
'event_log' => ''
),
),
);
return $api;
}
Then, create a class called: CustomTableMigration.inc that will contains the migration:
<?php
/**
* Created by PhpStorm.
* User: ldcontreras
* Date: 25/07/18
* Time: 10:13
*/
class CustomTableMigration extends Migration {
public function __construct($arguments) {
parent::__construct($arguments);
$query = Database::getConnection('default', 'migrate_custom_table')//this must be define in your settins.php file
->select('people')
->fields('productos_new', array(
'id',
'name',
'department',
'division',
'insurance',
)
);
$this->source = new MigrateSourceSQL($query, array(), NULL, array(map_joinable => FALSE));
$this->destination = new MigrateDestinationNode('content_type_machine_name'); //the content type created
$this->map = new MigrateSQLMap($this->machineName,
array(
'id' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => t('Source ID'),
)
),
MigrateDestinationNode::getKeySchema()
);
$this->addFieldMapping('title', 'name');
$this->addFieldMapping('field_department_content_type', 'department');
$this->addFieldMapping('field_division_content_type', 'division');
$this->addFieldMapping('field_insurance_content_type', 'insurance');
$this->addUnmigratedDestinations(array(
'body:format',
'comment',
'is_new',
'log',
'promote',
'revision',
'revision_uid',
'tnid',
'totalcount',
'daycount',
'timestamp',
'path',
'translate',
'sticky',
'uid',
));
}
}
Finally,enable your custom module and run the migration using drush.
I have created a custom block and would like to associate it with a tpl in the associated module.
Currently I can associate only a tpl file in the theme folder.
I would like it to be a tpl of the module and then use the hook_menu and pass some data to it, which is impossible (to my knowledge) with a tpl in the theme folder.
Is that even possible?
If this is not possible I would like to use the tpl in my theme as a container and use the hook_menu to pass its contents but I don't know how to return the tpl/theme I will create in the module.
Can someone help me?
I hope the below example helps you
function MYMODULEBLOCK_block_info() {
$blocks['MYMODULE_BLOCK_NAME'] = array(
'info' => t('MYMODULE BLOCK TITLE'),
'cache' => DRUPAL_NO_CACHE, //there are a number of caching options for this
);
return $blocks;
}
function MYMODULEBLOCK_block_view($delta = ''){
switch($delta){
case 'MYMODULE_BLOCK_NAME':
if(user_access('access content')){ //good idea to check user perms here
$block['subject'] = t('MYBLOCK_TITLE');
$block['content'] = MYMODULE_BLOCK_FUNCTION_ITEMS();
return $block;
}
break;
}
}
function MYMODULE_BLOCK_FUNCTION_ITEMS(){
$items = array();
$items['VAR_ONE'] = array('#markup' => 'VAR_ONE_OUTPUT'); //this is the simplest kind of render array
$items['VAR_TWO'] = array(
'#prefix' => '<div>',
'#markup' => 'VAR_TWO_OUTPUT',
'#suffix' => '</div>',
);
// this is where the $items get sent to your default MYMODULE_BLOCK.tpl.php that gets
// registered below
return theme('MYMODULE_BLOCK_FUNCTION_ITEMS', array('items' => $items));
}
//here you are registering your default tpl for the above block
function MYMODULE_theme() {
$module_path = drupal_get_path('module', 'MYMODULE');
$base = array(
'path' => "$module_path/theme",
);
return array(
'MYMODULE_BLOCK_FUNCTION_ITEMS' => $base + array(
'template' => 'MYMODULE_BLOCK', //leave off .tpl.php
'variables' => array('items' => NULL,),
),
);
}
All the stuff in CAPITALS (except DRUPAL_NO_CACHE) can be named whatever you want
And then in a subfolder in your module called theme/ there should be a file called MYMODULE_BLOCK.tpl.php which could have this in it:
<?php
$items = $variables['items'];
print render($items['VAR_ONE']);
print render($items['VAR_TWO']);
And if you wanted to, you could actually overwrite the "default" module implementation you just made for MYMODULE_BLOCK.tpl.php in your theme as you wish in block--MYMODULE--DELTA.tpl.php
The way I do this is as follows...
function YOURMODULE_menu(){
$items['somepage'/%] = array(
'title' => 'Some page title',
'page callback' => 'YOURMODULE_page',
'page arguments' => array(1),
'type' => MENU_CALLBACK,
'access arguments' => array('access content'),
);
return $items;
}
function YOURMODULE_page($data){
$output = 'value from YOURMODULE module! = '.$data;
return theme('theme_file',array('results' => $output));
}
function YOURMODULE_theme() {
$path = drupal_get_path('module', 'YOURMODULE');
return array(
'theme_file' => array(
'variables' => array('results' => null),
'template' => 'theme_file',
'path' => $path,
),
);
}
Place your tpl file theme_file.tpl.php in your module directory and inside it use the below code.
<?php print $results; ?>
or
function YOURMODULE_theme() {
return array(
'theme_file' => array(
'variables' => array('results' => null),
'template' => 'theme_file',
),
);
}
Place your tpl file theme_file.tpl.php in your theme directory and inside it place the below code
<?php print $results; ?>
Go to your http://yourdomain.com/somepage/somedata to see the result.
I have made a custom module and it works fine till I start working on my custom theme.
Once I move over to my custom theme I get this error
Warning: Missing argument 2 for customvishal_form(), called in
/home/vishal/Dropbox/sites/new/includes/theme.inc on line 1029 and
defined in customvishal_form() (line 441 of
/home/vishal/Dropbox/sites/new/sites/all/modules/customvishal/customvishal.module).
You can see the error at : http://www.iamvishal.com/dev/about-us
I don't think anything is wrong with my code :
/**
* A simple form.
*/
function customvishal_form($form, &$form_submit) {
$form['customvishalactivate'] = array(
'#title' => t('Activate Preference'),
'#type' => 'radios',
'#options' => array('1' => t('Yes'), '0' => t('No')),
'#required' => TRUE,
);
return $form;
}
Its called from
function customvishal_pref($arg1)
{
// Here we willl make the form and save the data so when cron
// runs we will check the users preference
$build = array(
'header_text' => array(
'#type' => 'markup',
'#markup' => '<p>' . t('This page is where you add your preferences. Based on your
entered choices we will send you alerts ') . '</p>',
),
'example_form' => drupal_get_form('customvishal_form'),
);
return $build;
}
What might be causing this problem ?
Cheers,
Vishal
I had the same issue
I called hook_form like this:
/**
* Implements of hook_menu().
*/
function skupina_menu() {
$items = array();
$items['admin/config/people/skupina'] = array(
'title' => 'Skupiny odborníkov',
'description' => 'Prehľady návštev odborníkov',
'page callback' => 'drupal_get_form',
'page arguments' => array('skupina_statistics'),
'access arguments' => array('view statistics'),
'file' => 'admin.inc',
'file path' => drupal_get_path('module', 'skupina'),
'weight' => 1,
);
return $items;
}
and then
/**
* Prehlad navstev odbornikov - page
*/
function skupina_statistics($form, &$form_state) {
$form = array();
$form['skupina_obdobie'] = array(
'#type' => 'select',
'#title' => t('Zmeniť zobrazenie'),
'#options' => skupina_get_zobrazenia(),
'#description' => t('Zmení filtrovanie dát podľa zvolenej možnosti.'),
'#required' => FALSE,
);
return $form;
}
my problem was, that the function didn't have the "_form" in its name so its produce those warnings.
So the function must be called "skupina_statistics_form in my case
when the form function is called the only parameter that is sent to it is the form variable. Since your second function parameter doesn't have a default value it obviously produces a warning.
If you never use it in the function code you might consider removing it or providing a default value.
e.g.:
function customvishal_form($form, &$form_submit = NULL)
or you might consider passing an additional parameter. You can do this like so:
drupal_get_form('customvishal_form', $some_your_parameter);
I think I know the answer. I had the exact same problem.
Is your module named exactly as your custom theme? Mine was and I changed my theme name and the error went away
Let's say I have this implementation of hook_menu():
function example_menu(){
$items = array();
$items['admin/recent-completions'] = array(
'title' => 'Recent Completions (Last 100)',
'page callback' => 'example_recent',
'access callback' => user_access('Administer content'),
'type' => MENU_NORMAL_ITEM,
'weight' => -50
);
return $items;
}
How can I make a template for the page callback instead of returning a string?
You would need to implement a hook_theme function and specify a template file.
Then in your page callback, you would have to call your theme function. Something like...
function example_theme($existing, $type, $theme, $path) {
return array(
'recent_completion' => array(
'render element' => 'elements',
'template' => 'recent-completions',
),
...
}
function example_recent() {
// Do some logic and processing here
$render_array = array( /* array with parameters for the template */ );
return theme('recent_completion', $render_array);
}
I had the same question, but wasn't sure how to implement a hook_theme function. This is how it's done (in Drupal 6 at least).
I am trying to build my own module in Drupal 7.
So I have created a simple module called 'moon'
function moon_menu() {
$items = array();
$items['moon'] = array(
'title' => '',
'description' => t('Detalle de un Programa'),
'page callback' => 'moon_page',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK
);
return $items;
}
function moon_page(){
$id = 3;
$content = 'aa';
}
in moon_page() function, I like to load a custom template 'moon.tpl.php' from my theme file.
is this possible?
/*
* Implementation of hook_theme().
*/
function moon_theme($existing, $type, $theme, $path){
return array(
'moon' => array(
'variables' => array('content' => NULL),
'file' => 'moon', // place you file in 'theme' folder of you module folder
'path' => drupal_get_path('module', 'moon') .'/theme'
)
);
}
function moon_page(){
// some code to generate $content variable
return theme('moon', $content); // use $content variable in moon.tpl.php template
}
For your own stuff (not overriding a template from another module)?
Sure, you only need to:
Register your template with hook_theme()
Call theme('moon', $args)
$args is an array that contains the arguments to the template as specified by your hook_theme() implementation.
For Drupal 7, it did not worked for me. I replaced line in hook_theme
'file' => 'moon', by 'template' => 'moon'
and now it is working for me.
In drupal 7 I was getting the following error when using :
return theme('moon', $content);
Was resulting in "Fatal error: Unsupported operand types in drupal_install\includes\theme.inc on line 1071"
This was fixed using :
theme('moon', array('content' => $content));
You may use moon_menu, with hook_theme
<?php
/**
* Implementation of hook_menu().
*/
function os_menu() {
$items['vars'] = array(
'title' => 'desc information',
'page callback' => '_moon_page',
'access callback' => TRUE,
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function _moon_page() {
$fields = [];
$fields['vars'] = 'var';
return theme('os', compact('fields'));
}
/**
* Implementation of hook_theme().
*/
function os_theme() {
$module_path = drupal_get_path('module', 'os');
return array(
'os' => array(
'template' => 'os',
'arguments' => 'fields',
'path' => $module_path . '/templates',
),
);
}