欢迎各位兄弟 发布技术文章
这里的技术是共享的
自己动手开发模块
1)建一目录 sites/all/modules/test001
2)在其下建文件
注意,模块名(以及钩子声明)必须是小写字母。
一, test001.module php文件
有一类似的ID标签。// $Id$
Drupal.org的版本控制系统能够通过修订信息和作者信息将CVS ID信息填满
按惯例都应该将该标签加在你的模块中
按照Drupal的 编码规范, 应该省略结束标签 ?>
在你的模块当中的所有函数,应该以{模块名}_{hook}的形式命名,
其中 hook 是指预先定义好的钩子函数的相应的后缀。
二, test001.info 这个文件应该命名为test001.info
该.info文件使用的是.ini格式,包含一个 ; $Id$ 可以使CVS插入相关文件ID信息。
通常格式
; $Id$
name = 模块名 (必须)
;必须的 :仅仅第一个单词的第一个字母大写(例如应该"Example module")
description = 简单描述模块要做什么.
一行简短描述,用于在模块管理页面告诉管理员该模块做什么。记住,太长的描述并不是太好,所以请尽量简明;而且长度是限制在255字符的。
注意,description中的特殊字符必须由相应的HTML来代替
例如,使用 description = This is my "crazy@email.com" email address 来代替 description = This is my "crazy@email.com" email address 。
如果描述中有单引号或撇号,你可以简单地将整个字符串放在双引号里面。例如, description = "Please don't use this unless you know what you are doing."
core (必须)
从Drupal 6.x起,那些没有明确指明兼容Drupal哪个核心版本
必须的
从Drupal 6.x起,那些没有明确指明兼容Drupal哪个核心版本的模块,将不再起作用。
dependencies (可选) ;模块依赖
例: dependencies[] = taxonomy dependencies[] = comment
package (可选)
如果一个模块的.info文件包括有一个'package'属性,
那么在admin/build/modules页面,将会把具有相同'package'的模块列举在一起。
如果没有'package'属性,那么该模块将列举在'Other'块里。
一些建议使用的 'package' 例子:
Audio, Bot, CCK, Chat E-Commerce, Event, Feed, Parser, Organic groups, Station, Video, Views,
Voting (如果使用的VotingAPI)
那么,现在你通过http://127.1/drupal/admin/build/module将可以看到我们所要创建的模块test001。
三, help钩子 帮助函数 {module}_help
我们同样能够利用help钩子来提供一些关于我们模块的帮助和其他信息。
由于我们前面所使用的.info文件,所以该钩子的实现并不是必须的。
help钩子函数在 module文件里
其中的 $path变量是指提供帮助的路径,通常用switch 语句来处理。
function test001_help($path, $arg) {
$output = ''; //declare your output variable
switch ($path) {
case "admin/help#test001":
$output = '<p>'. t("Displays links to nodes created latest") .'</p>';
break;
}
return $output;
}
当链接到主要帮助页面时(/admin/help 或者?q=admin/help).
admin/help#modulename 将会被Drupal核心调用。看到帮助文档
Hook_help()可以告诉drupal系统模块的信息以使模块在“模块”管理页面上列出来,
这样用户就可以选择是否启用或禁用此模块了。
模块一但被启用,模块文件里的全部代码都被包含到系统中,同时
模块的函数也可以调用drupal的所有可用函数和访问所有可用变量了。
四, perm钩子 权限函数 {module}_perm
这个函数是用来定义你的模块的权限名称的。
它并不授予权限,仅仅指明什么权限对这个模块可用。
基于这些权限的访问是定义在{module}_access函数中的。
function test001_perm() {
return array('access test001 content');
//如果要更好的地控制权限的模块,你需要扩展这个权限设置,如下
//return array('access test001 content', 'administer test001');
}
必须要开启test001模块,开发模块下(最好禁用缓存,才能更好的看到效果)
这时你将会在http://127.1/drupal/admin/user/permissions 看到刚才所创建的权限:
你的权限名称可以随意取的,但是每个名称必须独一无二
权限名称应该包含你的模块名字,因为这样能够有效地避免命名冲突。
建议的权限命名规则是"action_verb modulename".
样例
function newmodule_perm() {
return array(
'access newmodule', 'create newmodule', 'administer newmodule');
} // function newmodule_perm
五, 你可能已经听说过这样一些模块类型,“区块模块”,
主要是指那些创建区块内容的模块(例如菜单模块);
“节点模块”,主要是指那些用于生成整页内容的模块(例如博客和论坛模块)
六, block钩子 {module}_block 创建区块
function test001_block($op = 'list', $delta = 0, $edit = array()) {
// 你的模块代码
} // end function test001_block
$op (或者 operation): 区块函数有四个不同的操作('list', 'view', 'save' 和 'form')
$delta: 区块模块可以用来创建你所需要的那样多的不同的区块。
delta是一个用在内部的数字,用以识别你的不同的区块。
用户(user)模块就是一个有多个不同区块的模块例子:
用户登陆区块,最新会员区块和在线会员区块。
$edit: 仅仅和 "save" $op一起使用,稍微有些难处,我们暂不讨论。
我们只有一个区块。首先,非常重要的一点就是,
要定义在页面Administer -> Site Building -> Blocks 出现的内容。
为了让你的区块能够被列举在管理页面,你必须为'list' $op定义输出。
function test001_block($op = 'list', $delta = 0, $edit = array())
{
// list the blocks
if ($op == "list") {
$block[0]["info"] = t('Test001');
return $block;
}
} // end test001_block
添加了上面的代码到test001.module后,我们就能在区块列表页面admin/build/block看到该区块:
$block - $block 是存储区块变量的变量。
$block[0] - $block 是一个数组变量,数组中的每一项代表我们其中的一个区块。
其中的“0”是 $delta 的值,
因为我们这里只定义了一个区块,所以是“0”。
如果我们需要定义更多的区块,则需要定义$block[0], $block[1], $block[2], 等等。
$block[0]["info"] 代表区块的每个元素 (0, 1, 2)同样是一个 键=值 对数组。
这些键包括有“info”,“cache”,“weight”,“status”等等。
我们暂时只讨论“info”,这是在区块列表页面所显示的区块名称。
所以,在Drupal内部,我们的区块名称是 $block[0],
但是在管理页面,区块名称是Test001。在接下来这一步,我们将生成区块内容。
function test001_block($op = 'list', $delta = 0, $edit = array())
{
// list the blocks
if ($op == "list") {
$block[0]["info"] = t('Test001');
return $block;
}
else if ($op == 'view') {
$block_content = '';
$query = "SELECT nid, title, created FROM {node} ORDER BY created DESC limit 0,10" ;
$queryResult = db_query($query);
while ($links = db_fetch_object($queryResult)) {
$block_content .= l($links->title, 'node/'.$links->nid) . '<br />';
} if ($block_content == '') {
$block_content .= 'There is no content';
}
$block['subject'] = 'Test001 Subject';
$block['content'] = $block_content; return $block;
}
} // end test001_block
使用db_query,db_fetch_object封装了所有的数据库操作 如mysql,postgres
注意上面代码中的URL是包裹在函数l()里的,
l()函数能够生成<a href=”link”>这样的链接。
这里,我们同样返回了一个数组,包含元素”subject”和”content”。
这其实也是Drupal核心所期望的区块函数所返回的值。
如果你的区块函数返回值中没有将这两个元素都包含在里面,
那么这个区块将不能正确呈现出来。
七)进行sql查询
:表名称要包含在大括号里,例如{node}.这样做是必须的,
以便让你的模块能够支持数据库表名前缀。
你可以通过阅读Drupal站点上Drupal手册里的表前缀(以及多个站点共享数据表)
获得更多信息。
我们将使用SQL查询db_query()来获取记录(也就是数据库里的数据列表
八) (a)模块安装,放在sites/all/modules/目录下
必须test001文件夹,里面必须要含test001.module test001.info文件
(b)启用 到管理=>站点构建=>模块 下启用 打上勾保存一下
(c)配置 因它是区块模块,须要到区块管理页面将区块激活,为它指定一个显示的区域
一定要注意,要选择你的主题中有显示的区域
如果是节点模块可能需要,也可能并不需要更多的配置,这些都取决于模块
(d)应该还有设置权限的吧 还要看看 权限 有没有开启吧!!
3)
此时,要么用devel模块clear cache,
要么浏览一下管理页面中的“菜单”页面就会刷新菜单路径缓存了。现在应该可以了
4)
前面所有的路径定义中access都为TRUE,但通常我们都希望对页面内容的访问作一些权限控制。此时我们需要在模块里实现hook_perm()函数:
function example_perm() {
return array('access foo', 'access baz');
}
现在,你在“访问控制”页面就可以分配这两个权限给指定的角色了。同时,你还要在hook_menu里这样定义'access':
'access' => user_access('access foo'),
//这个不太懂 ,好像是不需要 ...在drupal 6 中
//好像是直接 'access arguments'=> array('access hellodrupal blocks'), //程序自动判断返回值
user_access()函数会访问$user全局变量和权限设定以确定访问页面的当前用户是否有'access foo'这个权限,有就返回TRUE,没有返回FALSE。用户ID为1的用户默认拥有任何权限,即user_access(‘任意值’)对他来说都会返 回TRUE;权限管理对他完全没用,乖乖。——所以,有特殊要求时,记得还要控制uid=1的用户。
好了,我相信你已经能够用模块定义自己的页面了——虽然看似有些繁琐,但恭喜你已经迈出模块之旅的第一步。
//不是 钩子函数
function test001_admin() {
$form['test001_maxdisp'] = array( '#type' => 'textfield',
'#title' => t('Maximum number of links'),
'#default_value' => variable_get('test001_maxdisp', 2),
'#size' => 2, '#maxlength' => 2,
'#description' => t("The maximum number of links to display in the block."),
'#required' => TRUE );//required是什么意思 意思是必须要有值
return system_settings_form($form);
}
function test001_menu() {
$items = array();
$items['admin/settings/test001'] = array( 'title' => 'Test001 module settings',
'description' => 'Description of your Test001 settings control',
'page callback' => 'drupal_get_form',
'page arguments' => array('test001_admin'),
'access arguments' => array('access administration pages'),
'type' => MENU_NORMAL_ITEM );
return $items;
}
//这里好像是系统菜单 system_settings_form
与普通的菜单有点不一样
4)//不是 钩子函数
function test001_all()
{
}
如果你希望从另外的模块调用该函数,
可以采用标准的命名方案:modulename_action,
可以通过函数module_invoke()来调用。
function test001_all()
{
// content variable that will be returned for display
$page_content = '';
$query = "SELECT nid, title, created FROM {node} ORDER BY created DESC";
$queryResult = db_query($query);
while ($links = db_fetch_object($queryResult))
{
$page_content .= l($links->title, 'node/'.$links->nid).'<br />';
}
// check to see if there was any content before
// setting up the block
if ($page_content == '')
{
// no content from a week ago, let the user know
$page_content = "No events occurred on this site.";
}
return $page_content;
}
function test001_menu()
{
$items = array();
$items['admin/settings/test001'] = array( 'title' => 'Test001 module settings',
'description' => 'Description of your Test001 settings control',
'page callback' => 'drupal_get_form',
'page arguments' => array('test001_admin'),
'access arguments' => array('access administration pages'),
'type' => MENU_NORMAL_ITEM, );
//this is added for this current tutorial.
$items['test001'] = array( 'title' => 'Test001',
'page callback' => 'test001_all',
'access arguments' => array('access test001 content'),
'type' => MENU_CALLBACK );
return $items;
}
function test001_block($op = 'list', $delta = 0, $edit = array())
{
// list the blocks
if ($op == "list") {
$block[0]["info"] = t('Test001');
return $block;
}
else if ($op == 'view') {
$block_content = '';
//$limitnum = variable_get('test001_maxdisp', 2);
//$query = "SELECT nid, title, created FROM {node} ORDER BY created DESC limit 0,".limitnum ;
//$queryResult = db_query($query);
$limitnum = variable_get('test001_maxdisp', 2);
$query = "SELECT nid, title, created FROM {node} ORDER BY created DESC ";
$queryResult = db_query_range($query, 0, $limitnum);
while ($links = db_fetch_object($queryResult)) {
$block_content .= l($links->title, 'node/'.$links->nid) . '<br />';
} if ($block_content == '') {
$block_content .= 'There is no content';
} else {
//下面这个是增加"更多"链接
$options = array( "attributes" => array("title" => t("More events") ) );
$link = l( t("more…"), "test001", $options );
//看看 l 方法 $options参数 自己领会 就是a标签的属性吧
$block_content .= "<div class=\"more-link\">" . $link . "</div>";
}
$block['subject'] = 'Test001 Subject';
$block['content'] = $block_content;
return $block;
}
}
自己动手开发模块2
1)在 sites/all/modules/中
建一文件夹 hellodrupal
2)在其内建 hellodrupal.info,hellodrupal.module
名称要一样
<?php
; $Id$
name = Hellodrupal
description = List the latest content links
core = 6.x
packgage = //未指定 ,放在other
dependencies =
这里的结束 ?>一般没有 防止可能 空格 对 session,cookie有影响
3)http://api.drupal.org/api/function/hook_block/5
第五个版本 看到关于此hook_block函数的说明
4)http://api.drupal.org/api/group/database/5
第五个版本,看到关于操作数据库的函数
db_query 对应mysql_query()
db_query_range (返回一定条数的结果集) 相当于 limit 作用
pager_query 分页
db_query
$query = select nid,title,created From {node}
where created >=%d and created <=%d
{node} 封装了前缀
db_query_range($query, 0 ,10);//$query 是 $sql, limit 0,10
$result = db_query_range('SELECT n.title, n.body, n.created
FROM {node} n WHERE n.uid = %d', $uid, 0, 10);
theme('item_list', $links);//体会一下
表示 输出一个 ul 其 class='item_list'
其中 li 里面的东西就是 $links
_函数 表示是私有的
自己动手开发模块3
1)druapl创建的表单是安全的
封装了表单的创建和存取
它表单首先存储于数据库
对表单进行缓存
第二个用户 就不用生存 直接从数据库取(我觉得是从缓存取吧)
每个表单有id 通过id取表单
2)drupal_get_form($from_id)
http://api.drupal.org/api/function/drupal_get_form/5
看到说明
根据某个表单构造函数,生成相应的表单,
某个表单构造函数 自己随便定义的函数,是不受任何钩子函数的回调
$from_id为表单的名字(唯一)
drupal_get_form("hello_form")
多个表单以向导的方式提交时,此函数可保存表单状态
function my_form()//my_form 就是 $form_id
{
// 文本框 name是文本框的名称
$form['name'] = array(
'#type' =>'textfield',//drupal 规定文本框用textfield来表示
'#title'=>t('Your name'),//标题 显示在文本框前面
'#description'=>t('Please input your name');//文本框下面的描述
}
//提交按钮 //
$form['submit'] = array('#type'=>'submit','#value'=>t('Save'));
return $form;
}
function hello_drupal_form(){
return drupal_get_form('my_form');
}
表单元素有哪些
http://api.drupal.org/api/file/developer/topics/forms_api_reference.html/5
fieldset 将表单元素分组
属性
'#collapsible' => TRUE, //是否可折叠
'#collapsed' => FALSE, //默认是(false)打开 还是(true)关闭
function my_form()//my_form 就是 $form_id
{
$form['basic'] = array(
'#type'=>'fieldset',
'#title'=>t('Basic information'),
'#collspsiable'=>true,
'#collapsed'=>false
);
// 文本框 name是文本框的名称
$form['basic']['name'] = array(
'#type' =>'textfield',//drupal 规定文本框用textfield来表示
'#title'=>t('Your name'),//标题 显示在文本框前面
'#default_value'=>'hello world',
'#description'=>t('Please input your name')//文本框下面的描述
);
$form['basic']['age'] = array(
'#type'=>'textfield',
'#title'=>'Your age'
);
//提交按钮 //
$form['submit'] = array('#type'=>'submit','#value'=>t('Save'));
return $form;
}
item 可读的元素 纯文字的描述
3) t('Your name') 开发中文网站的时候 可以直接写
4) 验证类似于钩子函数 表单函数名_validate
//两个参数 必写
//$form_id表单id
//$form_values表单的相当于post,
但是作用比post大,它本质上是从db中取的
//此函数其实是可选的,可以不验证
//drupal 5
function test_form_validate($form_id,$form_values)
{
form_set_error('',t(You must input your name'));
}
//drupal 6
/ * 表单验证
* @param (array) &$form
* 表单字段
* @param (array) &$form_state
* 表单值,用做判断表单的各种参数,包括用户提交的所有数据
*/
function myform_page_form_validate(&$form, &$form_state) {
/**
* 用户提交的所有数据在 $form_state['values'] 之中,相当于 $_POST
* 根据需求,验证昵称是否少于 2 个字符,中英文均算一个字符
* 可使用封装好的计算字符串长度函数:drupal_strlen
*/
if (drupal_strlen($form_state['values']['name']) < 2) {
/**
* 如果少于 2 个字符,调用 form_set_error() 写入错误信息,系统将显示错误信息,同时阻止表单提交
* form_set_error() 的格式,第一个参数:字段名称,第二个参数:用户将看到的错误信息
*/
form_set_error('name', '昵称不能少于 2 个字符');
} else if (drupal_strlen($form_state['values']['title']) > 255) {
form_set_error('title', '标题长度不能大于 255 个字符');
}
// 如验证通过,将进入表单提交环节
}
5)submit 类似于钩子函数的回调函数
表单函数名_submit
表单提交处理函数
//drupal 5
function test_form_submit($form_id,$form_values)
{
drupal_set_message(t('Your name is ').$form_values['name'].' '.
t('Your age is ').$form_values['age'];
}
//drupal 6
/**
* 表单提交
* @param (array) &$form
* @param (array) &$form_state
*/
function myform_page_form_submit(&$form, &$form_state) {
/**
* 写入数据库
*/
db_query("INSERT INTO {myform} (id, title, name, mail, timestamp, body)
VALUES (null, '%s', '%s', '%s', %d, '%s')", $form_state['values']['title'],
$form_state['values']['name'], $form_state['values']['mail'],
$_SERVER['REQUEST_TIME'], $form_state['values']['body']);
// 获取上一条 insert sql 返回的主键,以此判断是否执行成功
if (db_last_insert_id('myform', 'id')) {
/**
* 执行成功了,到数据库去看看,是不是有这条记录了
* 显示一条信息给用户
*/
drupal_set_message('感谢您,反馈已经提交,我们将尽快和您取得联系');
// 如果想将用户重定向到一个页面,可修改 $form['#redirect'] 值,如:
$form['#redirect'] = 'test/abcde';
/**
* 这里也可以使用 drupal_goto 来重定向,但这并不是个好方法
* 因为可能还有其它提交函数在 后面排队,被这儿一重定向,后面就没机会执行了
*/
} else {
// 数据写入失败了
drupal_set_message('抱歉,遇到问题,提交失败了', 'error');
}
}
<?php
//帮助
function hellodrupal_help($path) {
$output = ''; //declare your output variable
switch ($path) {
case "admin/help#hellodrupal":
$output = '<p>'. t("第一个Drupal模块") .'</p>';
break;
}
return $output;
}//function on this display help
function hellodrupal_block($op='list',$delta=0){
switch ($op)
{
case 'list' :
$block[0]['info'] = t('我的第一个drupal模块');
$block[1]['info'] = t('我的第二个drupal模块');
return $block;
case 'view' :
switch ($delta)
{
case 0 :
$block['subject'] = '我的第一个block';
$block['content'] = '欢迎访问我的站点';
break;
case 1 :
//$block['subject'] = '我的第二个block';
//$block['content'] = '欢迎再次访问我的站点';
$query = "select nid,title,created from {node}";
$queryResult = db_query_range($query, 0 ,10);
$links = array();
while ($node = db_fetch_object($queryResult))
{
$links[] = l($node->title,'node/'.$node->nid);
}
$block['content'] = theme('item_list', $links);
$block['subject'] = '我的第二个block';
break;
}
return $block;
break;
}
}
function hellodrupal_menu() {
$items = array();
$items['hello'] = array(
'title'=>t('hello drupal page'),
'page callback'=>'hello_druapl_page',
'page arguments' => array('hello','helloDrupal'),
//'page arguments' => array(1,2),
//它的优先级 大于 url传来的参数 也就是此时url如果放参数,参数不起作用我
//如果要默认值 就放在回调函数的形参上 (默认的时候要注意,第几个有默认值, page arguments=>array(......)) 中第几个元素就必须没有,假如有的话 虽不在url中赋值,但是是有值的 值为两个单或双引号括起来
//array(1,2)表示只取url前两个参数 array(1)表示只取url第一个参数
//如果 把 'page arguments' 注释掉
//那么 此时才取默值 ;;
//否则的话 如果 取'page arguments' => array(1,2),
//再如果 url 过来 没有传参的话 (其实是传两个 空值)
//此时的话 参数就不是放在回调函数上的形参 而是两个空值
'access arguments'=> array('access hellodrupal blocks')
);
$items['helloform'] = array(
'title'=>t('hello drupal page form'),
'page callback'=>'hello_drupal_form',
'page arguments' => array('page callback arguments'),
'access arguments'=> array('access hellodrupal blocks')
);
return $items;
}
/*function hello_druapl_page()
{
$output = 'hello drupal page';
return $output;
}*/
function hello_druapl_page($name = null, $nickname = null)
{
$output = '';
if(empty($name)){
$output = "hello andbody";
}
else {
$output = "hello ".$name;
}
if(!empty($nickname)){
$output .= ' your nick name is '.$nickname;
}
return $output;
}
//定义权限 仅仅指明什么权限对这个模块可用
function hellodrupal_perm(){
return array('access hellodrupal blocks');
}
function hello_drupal_form(){
return drupal_get_form('my_form');
}
/*function my_form()//my_form 就是 $form_id
{
// 文本框 name是文本框的名称
$form['name'] = array(
'#type' =>'textfield',//drupal 规定文本框用textfield来表示
'#title'=>t('Your name'),//标题 显示在文本框前面
'#description'=>t('Please input your name')//文本框下面的描述
);
//提交按钮 //
$form['submit'] = array('#type'=>'submit','#value'=>t('Save'));
return $form;
}*/
function my_form()//my_form 就是 $form_id
{
$form['basic'] = array(
'#type'=>'fieldset',
'#title'=>t('Basic information'),
'#collapsible'=>true,
'#collapsed'=>false
);
// 文本框 name是文本框的名称
$form['basic']['name'] = array(
'#type' =>'textfield',//drupal 规定文本框用textfield来表示
'#title'=>t('Your name'),//标题 显示在文本框前面
'#default_value'=>'hello world',
'#description'=>t('Please input your name')//文本框下面的描述
);
$form['basic']['age'] = array(
'#type'=>'textfield',
'#title'=>'Your age'
);
//提交按钮 //
$form['submit'] = array('#type'=>'submit','#value'=>t('Save'));
return $form;
}
//表单函数_validate 验证类似于钩子函数的回调函数
function my_form_validate(&$form, &$form_state)
{
/**
* 用户提交的所有数据在 $form_state['values'] 之中,相当于 $_POST
*/
// form_set_error('',$form_values['name']);
if($form_state['values']['name'] == '')
{
form_set_error('',t('You must input your name'));
}
}
//表单函数_submit 提交函数
function my_form_submit(&$form, &$form_state)
{
/**
* 用户提交的所有数据在 $form_state['values'] 之中,相当于 $_POST
*/
drupal_set_message(t('Your name is ').$form_state['values']['name'].' '.
t('Your age is ').$form_state['values']['age']);
}
自己动手开发模块4
一个模块 可以实现多处功能
一般情况下 只需要用 devel 清空缓存就可以了
(也可以模块 先关闭 再开启 比较麻烦)
1)menu 菜单机制 模块管理机制
它是导航系统
所有的菜单 模块都是实现了 hook_menu 钩子函数
2)
http://api.drupal.org/api/function/hook_menu/5
实现菜单系统
只有一个入口 index.php
url->是否维护->否->get menu array
->q 后面参数 取过来-> 看有调用无钩子函数 它会调用(回调函数)
->如果没有 调用回调函数->不同的主题模板 不同的节点类型 这个过程完成的
->如果有 调用回调函数-> 看回调函数的定义是否存在
->如果不存在 回调函数的定义 ->返回 menu_not found
->如果存在 回调函数的定义 ->用户是否有权限(hook_perm)
->如果没有权限-> 返回 menu_access_denied(拒绝)
->如果有权限 根据url参数 和回调函数需要的参数进行处理->调用回调函数->生成页面
function hook_menu($may_cache) {
}
//drupal 6 是没有参数
//drupal 6
//type 菜单类型 最常用两种 MENU_NORMAL_ITEM (显示菜单项)
// MENU_CALLBACK(不显示菜单项)
//drupal 6 好像是没有采用 什么分缓存和不缓存了 全部缓存
function hook_menu() {
$items = array();
$items['example'] = array(
'title' => 'Example Page', //必须
'page callback' => 'example_page',
'access arguments' => array('access content'), //必须 // 要让所有可以访问,
//'access arguments' =>true,
'type' => MENU_SUGGESTED_ITEM,
);
$items['example/feed'] = array(
'title' => 'Example RSS feed',
'page callback' => 'example_feed',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
//这是 drupal5 不适用了
function hello_page_menu($may_cache) {
$item = array();
if ($may_cache) //有缓存的时候 把下面注册在菜单项中 $items就是菜单项
{
//path url中路径 title 显示在菜单管理中,作为菜单项进行管理
//callback 指示 当访问 url时,执行哪个函数(它是回调函数,不是钩子,随便起什么名,不一定要 模块名_函数名()的格式),
//此函数里执行各种
//逻辑.输出html脚本,此函数也在本文件里实现
//access 访问权限
//如果不设它 那会drupal 会提示 access 被拒绝(所有人都看不到)
//所以这是drupal一个bug 必须要写 只要写成跟 drupal 里的随便哪个权限一样就可以
//还要让这个权限对所有角色默认允许
//也可以自己定义一个权限
//如 funtion hello_page_perm(){
// return array('access hellodrupal blocks');
// }
//先这里是
$items[] = array('path'=>'hello','title'=>t('hello'),
'callback'=>'hello_page_test',
//'access'=> user_access('access hello page'));
'access'=> 'access hellodrupal blocks');
//path hello/sayhello 两层 自动把它注册为 hello的子菜单项
//type 告诉drupal 菜单项的类型 默认就是普通菜单项 可以在菜单中进行管理删除
$items[] = array('path'=>'hello/sayhello','
title'=>t('Say hello'),
'callback'=>'hello_page2_test',
'type'=> MENU_CALLBACK);
}
return $items;
}
//drupal 5
$may_cache //第一次访问 可以被缓存 它为true
//会调用两次 要注册的菜单 要么放在真下 要么放在假下,否则会出错
一)第一次为true
二)第一次为false 样式表文件等
//drupal 6
function your_module_menu() {
$items['admin/settings/your_module'] = array(
'title' => 'Your Module Settings', // NOTE: t() not needed
'description' => 'Menu description', // ... for these elements
'page callback' => 'page_callback_funtion',
'page arguments' => array('page callback arguments'),//它的优先级 大于 url传来的参数我
//如果要默认值 就放在回调函数的形参上 (默认的时候要注意,第几个有默认值, page arguments=>array(......)) 中第几个元素就必须没有,假如有的话 虽不在url中赋值,但是是有值的 值为两个单或双引号括起来
//它是默认参数的意思 //它是静态的 被存入缓存的
//'page arguments' => array(1,2),
//它的优先级 大于 url传来的参数我
//如果要默认值 就放在回调函数的形参上 放在page_callback_funtion函数的形参上
//如果用array(1,2)表示只取url前两个参数 array(1)表示只取url第一个参数 ,
'access callback' => 'user_access', // Check that the current user
'access arguments' => array('Administer Your Module'), // ... has this permission.
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
//回调函数的参数 就是url/参数
多个参数 url/参数/参数
funtion hello_page_perm(){
return array('access hellodrupal blocks');
}
funtion hello_page_test(){
$output = 'hello drupal page';
return $output;
}
funtion hello_page_test($name = null){
$output = '';
if(empty($name)){
$output = "hello andbody";
}
else {
$output = "hello ".$name;
}
return $output;
}
funtion hello_page_test($name = null, $nickname = null){
$output = '';
if(empty($name)){
$output = "hello andbody";
}
else {
$output = "hello ".$name;
}
if(!empty($nickname)){
$output .= 'your nick name is ".$nickname;
}
return $output;
}
3)表单验证 表单名_validate
function test001_admin_validate($form, &$form_state)
{
$maxdisp = $form_state['values']['test001_maxdisp'];
if (!is_numeric($maxdisp))
{
form_set_error('test001_maxdisp', t('You must select a number for the maximum number of links.'));
//第一个参数是字段名 ,,好像也可以为空
}
else if ($maxdisp <= 0) {
form_set_error('test001_maxdisp', t('Maximum number of links must be positive.'));
}
}
自己动手开发模块5
1)http://hellodrupal.info/node/131 node_save
2)http://www.5iphp.com/drupal-hook_nodeapi drupal-hook_nodeapi
3)http://hellodrupal.info/node/31 drupal-hook_nodeapi
4)http://zhupou.cn/node/982 hook_user
5)http://blog.csdn.net/g089h515r806/article/details/2217658 hook_user 还要看
6)http://www.doooor.com/forum.php?mod=viewthread&tid=2382 hook_user
7)http://drupaltaiwan.org/node/1181 user_save 还要看
8)http://www.trackself.com/archives/1352.html user_save