Jump to navigation

You are currently browsing all posts tagged with 'drupal'

php Suhosin扩展导致drupal无法保存menu的问题

  • Posted on July 2, 2010 at 9:53 am

最近发现一个诡异的现象:
在drupal 6的管理后台,修改menu里面的navigation(导航),
也就是那个可以drag的table,
修改一下,无论是拖动改变顺序,还是check/uncheck checkbox,
提交之后,都无法保存。

先google了一下,有人也遇到相同问题,无解。

然后怀疑是和某模块冲突,因为drupal刚刚安装好的时候,
这个功能肯定是正常的。

于是把所有的第三方模块禁用了,但是没有禁用我自己写的模块,
情况并没有好转。

再怀疑是表单出了问题,用firebug跟了一下,
点击提交按钮之后,确实有POST动作发生,那么表单也没有什么问题了。

然后去modules/menu目录,下载了它的二个源文件,开始分析。

使用print+die的方式来debug,
最终发现这个表单的submit处理函数根本就没有被调用到,
可是表单确实被POST过去了呀。

然后开始尝试自己写一个测试用的submit处理函数和validate函数,
也没有被调用到。

然后再尝试修改form的名称。。。还是无效。

三个小时过去了。。无解。

然后开始在drupal的官网乱翻,居然翻到了一条相关的信息,
地址记不住了,
大意是说:
有人写了一个form,里面有超过200个元素,发现提交之后无法获取到表单全部元素的值。
然后有人回答说可能是装了Suhosin扩展之后,会有这个限制。
这个人就去修改了php.ini里面Suhosin相关的选项,就OK了。

然后我把phpinfo调出来一看,果然安装了Suhosin,
而且:
suhosin.post.max_vars 200(默认值)
suhosin.request.max_vars 200 (默认值)

啊,原因就在此了。

由于我的模块在navigation里面添加了大约15个menu,再搭配上系统原有的几十个menu,
每个menu对应3-4个表单元素,最后竟然超过了200个,
导致submit之后,formid居然没传过去。
所以drupal也就不知道用哪个submit处理函数了。
如此。

drupal中清除缓存的hook函数

  • Posted on May 11, 2010 at 2:03 pm

drupal 6:
drupal中有大量的hook函数,那么哪个才是清除缓存的时候使用的hook函数呢?

点击“管理➤站点配置 ➤性能”页面的“清除缓存数据”按钮时,
通过实现hook_flush_caches(), 你的模块就可以清除自己的缓存了。

/**
 * Implementation of hook_flush_caches().
 */
 
function masalife_flush_caches() 
{
 
    //do something
    return array();
 
}

drupal_goto 函数详解

  • Posted on April 24, 2010 at 2:51 pm

drupal 6:

drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302);

主要作用是从当前页跳转到另外一个页面。

Drupal will ensure that messages set by drupal_set_message() and other session data are written to the database before the user is redirected.
使用这个函数的时候不必担心 drupal_set_message()会失效,drupal会保证在跳转之前把message写到数据库里。

btw:
drupal会对path进行编码(encode),保证URL的正常。

Parameters
参数:
$path A Drupal path or a full URL.
$path: drupal路径,或者是一个完整的url
$query A query string component, if any.
$query: url中的参数部分。比如 a=1&b=1&c=1
$fragment A destination fragment identifier (named anchor).
$fragement #xxxx 锚点
$http_response_code Valid values for an actual “goto” as per RFC 2616 section 10.3 are:
$http_response_code HTTP CODE
301 Moved Permanently (the recommended value for most redirects)
302 Found (default in Drupal and PHP, sometimes used for spamming search engines)
303 See Other
304 Not Modified
305 Use Proxy
307 Temporary Redirect (alternative to “503 Site Down for Maintenance”)
Note: Other values are defined by RFC 2616, but are rarely used and poorly supported.

举例:
假设我们要跳转到
/my_page?sex=1&country=BE
正确:

drupal_goto("my_page", "sex=1&country=BE");

错误:

drupal_goto("my_page?sex=1&country=BE");

这样会跳转到 my_page%3Fsex%3D1%2526country%3DBE

drupal6 hook_schema中的自增字段

  • Posted on April 19, 2010 at 1:53 pm

假设模块为 abc
在文件abc.install中我们可以实现abc_install和abc_uninstall函数,
用来在模块安装/反安装过程中做一些事情,比如自动生成/删除数据表之类的。

function abc_install() {
    // Use schema API to create database table.
    drupal_install_schema('abc');
}
function abc_schema()
{
    $schema['abc_db_table'] = array(
              'field'=>array(
			'id'=>array(
				'type'=>'serial',
				'not null'=>TRUE,
				'description'=>t('xxx.'),
				),
			'title'=>array(
				'type'=>'char',
				'length'=>'255',
				'not null'=>TRUE,
				'default'=>'',
				'description'=>t('title'),
				),
			'flag'=>array(
				'type'=>'int',
				'size'=>'small',
				'not null'=>TRUE,
				'default'=>0,
				'description'=>t('flag'),
				),
              ),
		'primary key'=>array(
			'id',
		),
    );
}

这样就可以创建一张数据表: abc_db_table
它有一个主键id , ‘type’=>’serial’, 相当于 unsigned int auto_increment.

ps: text类型的字段(column),不能设置默认值(default value).

btw: 在hook_schema函数中, char类型的字段(column),有一个’length’属性,表示 char(xx) 。
int 类型的字段,有一个’size’属性,表示smallint, bigint, tinyint之类的。
text类型的字段,也有一个’size’属性,bigtext之类的意思。

drupal开发经验之菜单项

  • Posted on April 12, 2010 at 1:58 pm

drupal的默认菜单是 Navigation。 所有模块中实现的hook_menu,都有可能添加菜单项到它里面。
于是我们就写了很多模块,在Navigation中添加了许多菜单项。随着菜单项的增多,问题就慢慢出现了:
首先是菜单太多,又没有什么逻辑,找起来都不方便。
其实是菜单项想做汉化/韩化,甚至是双语同时使用,又不想去改module的代码。

于是后来再开发模块,就只添加MENU_CALLBACK类型的item,它不会对Navigation进行任何的修改。
然后再使用 /admin/build/menu-customize/navigation 来对Navigation进行修改。

drupal6 form中的reset按钮

  • Posted on April 10, 2010 at 9:26 am

drupal6 form中的reset按钮

在drupal中,form中的按钮只有一类,无论是submit,普通button, 还是Image button, 其实都是同一类的。

$form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
    '#executes_submit_callback '=>TRUE,
    '#validate'=>array("mymodule_validate_fun",),
    '#submit'=>array('mymodule_submit_fun'),
);

这就是一个典型的submit按钮,点击之后,它会去调用 mymodule_validate_fun函数来进行表单的验证,然后再调用mymodule_submit_fun函数进行表单提交之后的处理。

再来看一个普通button的例子。

$form['reset'] = array(
    '#value' => t('Reset'),
    '#executes_submit_callback '=>FALSE,
);

#executes_submit_callback告诉Drupal是否需要处理表单,为TRUE时处理表单,为FALSE时则简单的重新呈现表单

好了,理论上讲,一个普通button,就是一个reset按钮了。

如果这种处理不尽如人意,那么可以再改一下

$form['reset'] = array(
    '#value' => t('Reset'),
    '#executes_submit_callback '=>FALSE,
    '#attributes'=>array("onClick"=>"this.form.reset();"),
);

这样点击此按钮之后,就会去调用form.reset();来重置表单。

还可以这样:
假设当前的路径是 mymodule/myform

$form['reset'] = array(
    '#type'=>"submit",
    '#value' => t('Reset'),
    '#executes_submit_callback '=>TRUE,
    '#submit'=>array('mymodule_reset_fun'),
);
 
function mymodule_reset_fun()
{
	$path = "mymodule/myform";
	drupal_goto($path);
}

注:以上方法只是我的YY,没有实践过。

drupal 主题常用技巧总结

  • Posted on April 9, 2010 at 5:01 pm

drupal 主题常用技巧总结

判断用户是否登陆:

global $user;    
if( $user->uid )
{ 
/* 用户已经登陆 */ 
}
else
{
 /* 用户没有登陆 */ 
}
 
//说明:drupal的第一个用户uid为1

判断角色:

global $user;
print_r($user->roles);

按照URL来使用不同的模板:

在page.tpl.php最前面添加

if ( arg(0) == "myowntype")
{
	include 'page_xxx.tpl.php'; 
	return;
}

这样在访问 http://www.masalife.com/myowntype
的时候,就会去调用 page_xxx.tpl.php这个模板。

判断是否为首页

if( $is_front ){ /* 首页 */ }

drupal中的链接函数

  • Posted on April 7, 2010 at 4:29 pm
drupal中的链接函数
由于先接触到了theme(‘item_list’  和 theme(‘table’ ,
于是就主观地认为也应该有一个生成链接的theme
搜索过一段时间,找不到。
后来偶然间才发现,有一个函数l(),就是用来生成链接的。
function l($text, $path, $attributes = array(), $query = NULL, $fragment = NULL, $absolute = FALSE, $html = FALSE) {
$text 链接的文字
$path 链接地址
$attributes 链接的属性,比如class,title,target之类的
$query 不知
$fragment 同不知
$absolute 不知
$html 不知
举个例子吧:
l("manage user","admin/user", array('class'=>;'gray',title=>'this is title'));
生成出来的链接HTML为:
<a href="/?q=admin/user" title="this is title">manage user</a>
启用clean url之后,
生成出来的链接HTML为:
<a href="/admin/user" title="this is title">manage user</a>
很好。

drupal6 与 fckeditor

  • Posted on April 7, 2010 at 3:18 pm
drupal默认是没有富文本编辑器的,只有普通的textarea
于是国外某牛人写了一个fckeditor的模块,
只要按照说明文档进行激活,并做简单的设置,
即可自动把form中的textarea替换成fckeditor。
不过在使用中也发现了一个问题。
如果你用的默认form,没有对submit按钮进行修改的话,fckeditor没有什么问题,
非常好用。
如果你像我一样,修改了submit按钮:
$form['aktuell_submit'] = array(
'#type' => 'submit',
'#value' => t('save'),
 '#attributes'=>array("onclick"=>"aktuell_submit(this.form);return false;"),
 '#submit'=>array('aktuell_settings_submit'),
);
那么郁闷了,form提交之后,fckeditor中的内容没有被提交过去,
通过 $form_state['values'] 或者 $_POST[] 都没发现它的值。
解决办法:
在按钮onClick的时候,把fckeditor中的内容复制到textarea里面,这样一定会被提交过去了。
$html = '<script>
function passFckeditor(fo, name)
{
 var oEditor = FCKeditorAPI.GetInstance(name);
 //fo.elements[name].value = oEditor.EditorDocument.body.innerHTML;
 fo.elements[name].value = oEditor.GetXHTML(true);
}
</script>
';
$form['aktuell_submit'] = array(
'#type' => 'submit',
'#value' => t('save'),
 '#attributes'=>array("onclick"=>"passFckeditor(this.form, 'edit-aktuell-text');aktuell_submit(this.form);return false;"),
 '#submit'=>array('edit_aktuell_settings_submit'),
 '#prefix'=>$html,
);
PS:
edit-aktuell-text 就是那个textarea的id.

drupal 中的列表分页显示函数

  • Posted on April 6, 2010 at 9:16 pm

先看一下普通的php程序中的经典分页是怎样写的:

$n = new pictures();
$category = intval($_GET['category']);
//统计本分类下共有多少张图片
$count = $n->find_all_records_count($category);
if ($count != 0)
{
$page = (isset($_GET['page']))?intval($_GET['page']):1;
if ($page <1) $page = 0;
$total_page = ceil($count / pictures::PAGE_SIZE);
if ($page>$total_page) $page =$total_page;
$pic_list = array();
//得到本页的记录集
$n->find_all_records($pic_list, $page,$category);
//生成分页信息的html. 首页|上一页 下一页|尾页
$pageinfo = functions::pageinfo($page, $total_page, "/picList.php?category=".$category."&amp;page=", "");
}

再来看一下drupal中的吧

$sql = " SELECT * FROM {pictures} WHERE category='".$category."' ORDER BY `order` DESC, flag DESC, id DESC ";
$result = pager_query(db_rewrite_sql($sql), 10, 0, NULL);
$mypager = theme('pager', NULL, 10, 0);

就这样,没了。太简单了。全部都帮你处理好了。

ps:听人说,在使用pager_query的时候,sql 语句中的FROM一定要大写。。

Top