欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

主题函数 主题钩子函数

shiping1 的头像

<?php if (!empty($secondary_links)): ?>
          <div id="secondary" class="clear-block">
            <?php print theme('links', $secondary_links, array('class' => 'links secondary-links')); ?>
          </div>
     <?php endif; ?>

这里好像是 只能在page.tpl.php文件中才会起作用


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

_函数 表示是私有的


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第一个参数
    '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']);
}



$items[] = l('', 'user/register',
 array('attributes' => array('title' => t('Create a new user account.'))));

$form['links'] = array('#value' => theme('item_list', $items)); return $form;



Drupal问答

自站点成立以来,不少朋友通过email或者其它方式,向我询问drupal方面的问题,许多问题,这个用户遇到了,下个用户也可能 会用到。所以我决定,将所有的问题,以及我的答复,统一归类到一起,这样如果回答不准确,不对的时候,我将来也好修改。另一方面就是,如果有人遇到同样的问题,我就不用回答第2遍了。

当然,drupal设计的东西还是很多的,并不是每个问题我都能回答得了,也不是每个问题我都能给出详细的答案,比如一个问题需要写上几十行的代码,我会尽力回答好每个问题的,对于费时的,我也会给出相应的方法,对于自己不会的,自己也会不断研究,争取有一天,能够回答你的问题。

问题范围,只要和drupal相关就可以了。我的联系方式可以参看页面右下角。暂时只通过email的方式,不会通过论坛的。

Acquia drupal和drupal比较

昨天看到Acquia drupal 1.0发布了,这个是基于drupal6的一个版本。Acquia drupal现在不支持drupal5,将来也不会支持。它是从6开始了。每当drupal发布一个版本以后,它都会快速的跟进。它是建立在drupal基础之上的,而不是drupal的一个分支。

昨天,我从Acquia网站上,下载了他们发布的最新版本。解压缩到本地。发现的第一个不同点,就是Acquia drupal的体积要大很多,基本上是drupal的2倍吧。看来确实加了不少的东西。

从上面的文件夹往下看,includes目录下面没看出来变化,misc好像也没有,modules下面有变化了,多加了一个acquia目录,里面放置了20个他们精心挑选的模块。Profiles也有改动,默认的default被替换为了acquia。Scripts目录下面没有看出来变化。Sites目录下多了一个files子目录,而在sites\all下面,则添加了modules和themes两个子目录。在themes目录下面,添加了一个新的主题acquia_marina,看样子挺漂亮的。另外还增加了一个uploads目录,专门用来上传文件。跟目录下面的其它文件都没有变化,包括LICENSE文件,里面采用的都是GPL协议,所以担心acquia搞分裂的人,现在可以放心一下了。

安装Acquia drupal,把下载的文件解压到xampp\htdocs\acquia目录下,修改sites\default目录下的settings文件,我的是$db_url
= 'mysql://root:@localhost/acquia';。还有创建数据库acquia。在浏览器地址栏中,输入http://localhost/acquia/install.php,将会把你带到一个页面http://localhost/acquia/install.php?locale=&profile=acquia,在这里你需要输入用户名,email,等等,于drupal6.4唯一不同的地方是,让你输入acquia
subscription identifier,和key。这个不理它就是了。当然上面的图标也被替换成acquia的了。点击保存,安装就成功了,我的报了一点错误信息,但是不碍事,warning:
mail() [function.mail]:。。。Unable to send e-mail。这个也不用管。

进入以后,在上面老提示你输入identifier和key了,不过不是红色。Acquia有免费的可用,如果需要的话可以去申请一个。最上面的管理菜单很酷。

里面有不少新的特性,还是自己动手亲自看看吧。

相关链接: http://acquia.com/http://zhupou.cn

Google cse模块常见错误分析

很多个人站点安装了google的自定义搜索引擎,对于Drupal站长来说,有一个非常方便的模块可用那就是google_cse, Google Custom
Search Engine.

这个模块还是比较好用的,但是对于初次使用的用户,开始会碰到一个问题,点击搜索后,系统报错, Your client has issued a malformed
or illegal request.

原因就是,没有在模块的后台正确的配置cx,导航到admin/settings/google_cse,你会看到第一项, “Google Custom Search
Engine ID”:,很多人不知道这个地方填什么,以至于填错了,这里出错,就不能正常工作了.你就会看到上面的错误.

在这里输入的就是cx的值,cx的值在哪里呢?访问http://www.google.com/coop/manage/cse/,点击控制面板,在点击代码,你会看到这样的一段代码:

<form action="http://www.google.com/cse" id="cse-search-box">

<div>

<input type="hidden" name="cx" value="006644068316277358089:7skgjry3hxc" />

<input type="hidden" name="ie" value="UTF-8" />

<input type="text" name="q" size="31" />

<input type="submit" name="sa" value="搜索" />

</div>

</form>

<script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&lang=zh-Hans"></script>

在这里有用的就是<input type="hidden" name="cx" value="006644068316277358089:7skgjry3hxc"
/>

这里就给出了cx的值,把这个值拷贝到“Google Custom Search Engine ID”中,这样就可以了.

url传值和表单传值

drupal的传值很有意思,不过我做的时候都是在编写模块时用的,不知道别人怎么做的,然后就是

我写的东西比较少,有什么问题或者错误希望大家给指出来啊,呵呵。这个传值相当于普通php的url

地址是http://xxx.com/aaa?aa=hello&bb=world&cc=fine.这个的传递方法大概是这样的:

$items['aaa/%'] = array(

'title' => 'aaa',

'page callback' => 'show_sub',

'page arguments' => array(1),

'access callback' => TRUE,

'access arguments' => '',

'type' => MENU_NORMAL_ITEM,

);

function show_sub($cat1 = ''){

        echo $cat1;

        }

这样就把aaa/后面的这个值传到函数show_sub里了。举个例子,您访问的是http://drupal/aaa/hello,在这个页面上

就会输出hello这个值。如果page arguments这样的话 page arguments => array(1,2,3),那么对应的函数这么传值

function show_sub($aa = '',$bb = '', $cc = ''){ echo $aa.$bb.$cc;}那么当您访问http://drupal/aaa/hello/

world/fine这个地址时就会输出helloworldfine。这个是url传值。它的具体用法还要大家多多实验,我也不能说的

很清楚。

另一个想说的是form传值。它和url传值有点类似,一个是老东写过的一个文章里的例子,详细:http://www.cmsns.com/node/6

print drupal_get_form('test_form', $node);

//表单函数上就可以接收到了。

function test_form(&$form_state, $node){//注意这里是$node,也就是说可以直接传进来个数组的值。

        $form['title'] = array(

'#type'=> 'textfield',

'#title' => '主题',

'#default_value' => 11111,//默认值

'#maxlength' => 128,//长度

);

        return $form;

}

这个可以随便放到一个主题里的page.tpl.php就能看到效果,另一种方法还是hook_menu,原理和url传值是一样的。就是

$items['aaa/%'] = array(

'title' => 'aaa',

'page callback' => 'drupal_get_form',

'page arguments' => array('test_form',1,2,3),

'access callback' => TRUE, //访问权限,设为TRUE的话任何人都能访问

'access arguments' => '',

'type' => MENU_NORMAL_ITEM,

);

function test_form(&$form_state,$aa = '',$bb = '',$cc = ''){//传递表单参数

$form['title'] = array(

'#type'=> 'textfield',

'#title' => '主题',

'#default_value' => $cc,//默认值

'#maxlength' => 128,//长度

);

return $form;

}

这个访问http://drupal/aaa/hello/world/fine的时候form的title就是fine这个值

如何将Date表单元素的月日年的顺序改造为年月日

老葛的Drupal培训班 http://zhupou.cn

我们在表单元素中,很多时候都会使用date这样的元素,但是,你会发现,这个元素由3个select组成,他们的顺序为月,日,年,这是不符合中国的习惯的。

我在帮人指导建站的时候,就遇到了这样的问题,但是找不到答案。我判断,可以通过theme层搞定这个问题,这样就去找了对应的theme函数。这个问题在网上好像是找不到答案的,我google了多次,但是都找不到,也有人遇到了同样的问题,但是都是绕道而行。

我决定尝试着解决这样的问题,因为我相信,一定存在一个方法,将月日年的顺序调整为年月日。先看系统生成的默认元素里面的markup。然后就去找对应的主题函数,这样就找到了theme_date。

代码如下:

function theme_date($element) {

return theme('form_element', $element, '<div class="container-inline">'. $element['#children']
.'</div>');

}

container-inline就是这里生成。但是3个子元素的顺序不是这里决定的。我的第一个想法是,覆写这个函数,print_r($element['#children']),这样就可以到定这个顺序问题了。

不过我很想知道,核心代码中,哪部分决定了3个子元素的顺序,这样,就找到了expand_date($element)。代码如下:

function expand_date($element) {

// Default to current date

if (empty($element['#value'])) {

$element['#value'] = array('day' => format_date(time(), 'custom', 'j'),

'month' => format_date(time(), 'custom', 'n'),

'year' => format_date(time(), 'custom', 'Y'));

}

$element['#tree'] = TRUE;

// Determine the order of day, month, year in the site's chosen date format.

$format = variable_get('date_format_short', 'm/d/Y - H:i');

$sort = array();

$sort['day'] = max(strpos($format, 'd'), strpos($format, 'j'));

$sort['month'] = max(strpos($format, 'm'), strpos($format, 'M'));

$sort['year'] = strpos($format, 'Y');

asort($sort);

$order = array_keys($sort);

// Output multi-selector for date.

foreach ($order as $type) {

switch ($type) {

case 'day':

$options = drupal_map_assoc(range(1, 31));

break;

case 'month':

$options = drupal_map_assoc(range(1, 12), 'map_month');

break;

case 'year':

$options = drupal_map_assoc(range(1900, 2050));

break;

}

$parents = $element['#parents'];

$parents[] = $type;

$element[$type] = array(

'#type' => 'select',

'#value' => $element['#value'][$type],

'#attributes' => $element['#attributes'],

'#options' => $options,

);

}

return $element;

}

注意代码中红色的部分,3个子元素的顺序,是由日期格式决定的,我猜测,调整日期格式,就可以改变3个子元素的顺序,我尝试着将日期格式都改为了年月日:导航到admin/settings/date-time,将3中长,中,短的日期格式都调整为自定义格式,Y/m/d(D)
H:i。

这样,date元素中的顺序,就从“月,日,年”调整为了“年,月,日”。

玩转Drupal

Drupal确切地说就是面向程序员的,再准确一点说,它就是一个CMS开发框架,尽管Joomla,wp等等,也被人们称为框架,但是Drupal与它们相比,更难一些.

我认识一些人,不乏许多程序高手,不乏许多玩过其它CMS的高手,他们因为Drupal的灵活,选择了Drupal,但是却在灵活性上碰了壁,许多人最终不得不放弃Drupal.

还有大多数的人,搞过Drupal开发的人,更多准确的说,是在Drupal的基础上,写过几个PHP函数,用PHP的方式搞定了客户,做过两三个Drupal项目.

在中文的Drupal圈子内,大多数的人都是这样的,他们不懂表单API,不懂Drupal的菜单机制,许多人就连Drupal的主题系统也不明白,Drupal相关的其它方面,大多数人还是一知半解的.

我举个例子,我以前在公司的时候,有个国外的项目,很小的问题,就是修改一个表单的外国,两个同事搞了两天,他们接触Drupal很长时间了,但是都没有搞定,后来就让我帮忙,不到1小时就帮他们解决问题,其实很简单,就是去覆写一个表单元素的外观,他们不了解.

Drupal的问题,就是这样,如果你不了解它的底层机制,又不愿意去学习的话,那么在项目中,等待你的应该是老板的抱怨和客户的离去.

那种抱着1、2个月就能搞定Drupal的人,还是踏踏实实的去学习装装FCKeditor,搞定图片上传这样的基本问题吧。我每天花10个小时学Drupal,一个项目一个项目踏踏实实的去做,花了半年的时间,才感觉真正的入了门,即便是到了今天,还有许多问题没有接触过。

1、2个月就能搞定Drupal,一两个人花上一两个月的时间,就能搞定你的大想法。如果你怀着这样的心理,等待你的,只有钉子。

Drupal是什么

第一次听说drupal是在一年前的时候,那时根本就不知道它是干什么的,通过百度,谷歌了解到,它是一个php的cms。然后就开始学习PHP,drupal,PHP只是在drupal中学习了,所以到现在,对于一些很常见的php函数,我还是没有用过的。现在,已有一年多的时间了。对Drupal也有所了解,并实践一些项目了。所以想回过头来总结一下。

首先,什么是drupal呢?

Drupal是一个基于php+mysql的CMS系统。它是一个CMS,建立在php+mysql之上的。CMS能干的,drupal都可以胜任。比如搭建一个公司宣传类型的网站,比如为某个大学建个校园网,都可以使用
drupal。就连许多名人的个人网站,许多也都是用它建立的。比如最近在中国巡回演出的摇滚歌手艾薇儿(Avril Lavigne)的官方网站http://www.avrillavigne.com使用就是drupal.

Drupal是一个新型的操作系统,也是一个平台。这个是drupal创建者的一个目标。使用它,加上各种各样的第3方模块,你可以搭建各种类型的网站。就像垒积木一样,对于许多不懂得Php,许多不懂得编程的人都可以使用drupal搭建一个漂亮的网站。在drupal.org上,已经有成千上万个第3方模块了,覆盖了互联网上的各种应用,SNS,电子商务,视频,音频网站,博客,wiki,dig,等等,使用现成相关的模块就可以搭建一个。也有人将此称之为web3.0。

Drupal是一个php框架。就如同java中的struts一样,它自己为你封装了很多函数,在开发过程中,你只需要调用它的api就可以了。有时,你完全你可以撇开它所提供的一些功能,仅仅把它作为一个框架,在其基础之上开发自己的东西。所以,对于使用drupal进行定制开发的人,一定要熟悉它的API。

关于drupal是什么的相关介绍,还可可参看:

官网上的回答:http://drupal.org/about

官方的(acquia)回答:http://acquia.com/what-is-drupal

drupal中国的回答:http://drupalchina.org/about

百度知道fhileo的回答http://zhidao.baidu.com/question/44832523.html

相关链接: http://zhupou.cn

Parse error: syntax error, unexpected T_VARIABLE

你遇到过这样的错误吗,在编写drupal模块时,由于需要在中英文之间切换,不小心引入了以下错误:



Parse error: syntax error, unexpected T_VARIABLE in F:\xampp\htdocs\drupal-6.5\sites\all\modules\zixun\zixun.module
on line 30



我写的代码如下:

function zixun_menu() {

$items['admin/settings/zixun'] = array(

'title' => 'zixun',

'description' => 'peizhi',

'page callback' => 'drupal_get_form',

'page arguments' => array('zixun_admin_settings'),

//'access arguments' => array('admin zixun configuration'),

);

return $items;

}

function zixun_admin_settings(){

}

/*

function zixun_admin_settings(){ 

$form['mail'] = array('#type' => 'textfield',

'#title' => t('Your e-mail address'),

'#maxlength' => 255,

'#default_value' => $user->uid ? $user->mail : '',

'#required' => TRUE,

);

return system_settings_form($form);

}*/

//$form['zixun_nodetypes'] = array(

// '#type' => 'checkboxes',

//'#title' => t('用户可以对以下节点类型的文章进行咨询'),

//'#options' => node_get_types('names'),

//'#default_value' => variable_get('zixun_nodetypes',array('page')),

//'#description' => t('在这些节点类型下面,就会多出一个咨询的输入框'),

// );

// $form['array_filter'] = array('#type' => 'hidden');

// return system_settings_form($form);

整了半天,还以为我哪里写错了呢?看看这也对,那也对,是不是drupal6的模块的编写有特殊的规定,我没有遵守.怎么试都出错,最后没办法,google了以下,发现了解决方案。原来我使用了全角输入。

我的代码不是拷贝的,都是一个一个敲进去的,只不过自己用的是微软拼音,有时候需要中英文切换以下,不知道什么时候,搞成全角输入了。后来试了一下,果然是这个问题。

相关链接:http://zhupou.cn

Zend debugger 的配置安装

以前用过Zend debugger的,不过那时候是同事帮我配置的环境。由于新装了环境 ,而且换了XAMPP,以前用WDP的。由于要开发修改一个drupal模块,所以想搭个测试环境,跑一跑。

大概的印象还是有的,虽然自己不太会php,特别是一些配置的东西,不过还是会使用百度,google的。先google一下Zend debug,找到了知道要用的调试器为Zend
debugger,刚开始连名字都不记得了。然后就搜到了两篇安装指南。按照说明先到http://downloads.zend.com/pdt/server-debugger下载最新的debugger。我下载的是ZendDebugger-5.2.14-cygwin_nt-i386.zip。将其解压缩。得到一个目录:

<DIR> 4_3_x_comp
<DIR> 4_4_x_comp
<DIR> 5_0_x_comp
<DIR> 5_1_x_comp
<DIR> 5_2_x_comp
<DIR> 5_2_x_nts_comp
321 dummy.php
6,934 Inventory.xml
376 md5
832 README.txt

这里我用的是5_2_x_comp中的ZendDebugger.dll。

下面是具体的操作步骤。
1、请将ZendDebugger.dll复制到您的php安装目录下,比如:F:/xampp/php。
2、然后将下面的4行内容加到您的php.ini:
[Zend]
zend_extension_ts=F:\xampp\php\ZendDebugger.dll
zend_debugger.allow_hosts=127.0.0.1
zend_debugger.expose_remotely=always
其中,127.0.0.1是远程调试的文件所在机器的IP;我是本地web调试
3、将dummy.php复制到apache的document root目录。
4、重启apache。
打开浏览器运行:http://192.168.1.25/phpinfo.php

我照着作了,但是不对,始终建立不起来,不知道具体原因。又翻了好几篇文章,结果都是同一篇文章的转载。google虽好,但是解决不了我的问题。决定百度一下,很快找到一篇强文,因为对方也是用的xampp,里面说在xampp环境下php.ini文件指的是apache下面的F:\xampp\apache\bin中的php.ini,靠,我先前一直在改的是F:\xampp\php下面的php.ini和php5.ini,我说怎么不行啊。按照所说的修改F:\xampp\apache\bin下面的php.ini就可以了。由于我装的XAMPP版本比较新,自带了ZendExtensionManager,zendOptimizer,需要将

;zend_extension_ts = "F:\xampp\php\zendOptimizer\lib\ZendExtensionManager.dll"

;zend_extension_manager.optimizer_ts = "F:\xampp\php\zendOptimizer\lib\Optimizer"

;zend_optimizer.enable_loader = 0

;zend_optimizer.optimization_level=15

注释掉,原来是没有的。我觉得应该可以共存的,不过这里zend_extension_ts这个重复了,不注掉下面的apache起不来。这个我试了。

总结,XAMPP下面,搭建Zend debugger需注意两点:

1, php.ini文件指的是F:\xampp\apache\bin中的,apache/bin下面的。

2, 需要注释掉ZendExtensionManager的;zend_extension_ts等等。

不过第2点可能存在更好的解决方案。我所用的环境为XAMPP, 其中php为5.2.6,操作系统vista,调试工具zend debugger.

相关联接:http://zhupou.cn , http://loveboat0204.blog.hexun.com/12433730_d.html

drupal的中文文件名附件上传问题

开发过程中,使用Drupal上传中文文件,文件名出了问题,原来系统不支持中文名. http://blog.chinaunix.net/u/19419/showart_1108081.html
, http://www.5iphp.com/zh-hans/heart/180.html, http://www.blogme.cn/node/412, 这几篇文章给出了相应的解决办法,但是都是需要修改源代码的,所以决定找找看有没有别的办法.

使用Filefield模块来代替Upload模块,但是报错了.

warning: array_merge() [function.array-merge]: Argument #2 is not an array in F:\xampp\htdocs\rongzhi\modules\acquia\filefield\filefield.module
on line 297.

但是很快发现,我没有启用Upload模块,还是Filefield模块的原因.搜索相关的资料,找到了Transliteration,其下载地址为: http://drupal.org/project/transliteration,这个是专门用来解决文件名编码问题的.

drupal缓存清除小技巧

我今天发现的一个技巧,清除缓存的,那就是访问admin/build/modules也能够清除缓存。以前都是访问admin/settings/performance,点击里面的清除缓存数据按钮。

另外就是使用dev模块,清除缓存。后两者我都知道。

好像访问主题管理页面也能达到清除缓存的效果?最后这个我是猜测的,没有实验。

说到这里,就不得不提dev模块,模块很强大,我也使用过,但是开发的时候,我很少用它,不是因为这个模块不强大,而是最初的时候,我总是用写字板这样的工具拷贝和粘贴代码,所以在drupal中,会一些比较笨蛋的办法解决问题,而我觉得这些本方法已经很好用了,所以感觉不到对dev模块的需要。

drupal表单重构

function test_form(){

if (isset($form_state['amazonbob_item'])) {

$markup .= '<pre>'. print_r($form_state['amazonbob_item'], TRUE) .'</pre>';

$form['item_data'] =

array( '#type' => 'markup',

'#value' => $markup,

'#weight' => 10, );

}

return $form; }

function test_form_submit(){

$form_state['amazonbob_item'] = $item;

$form_state['rebuild'] = TRUE; }

drupal的表单重构,感觉可以用在多级表单上了,呵呵,不是最好的解决方案。'#type'=>'markup' 这里markup是drupal表单的一个属性。print_r('XXX',TRUE);这个TRUE好像是把print_r出来的内容转化了,具体的还待研究,<pre>
格式化代码。

warning: Missing argument 2 for variable_get()问题的解决

写模块的时候遇到的问题, warning: Missing argument 2 for variable_get(), called in…,发现问题以后,我很快大概知道问题出在哪里了,那就是variable_get()这个函数没有用对。我是修改的别的模块的代码,直接把第2个参数给删除了,为了省事,因为不删的话,就为空字符串了,觉得留着没用,就删了。

不过还是习惯的google了一下,找到一篇文章http://drupal.org/node/31792,讲的同一个问题。又查了查drupal api,果然是第2个参数,也就是默认值参数被删除的原因,那好,加上就可以了。

相关链接: http://zhupou.cn

你问我答:$content变量,想扩展它的功能,比如添加node-page.tpl.php

问题:

G089h515r806,你好。
请问一下怎么定义$content这个变量。
我想在首页的时候调用node-front.tpl.php,术语的时候调用node-taxonomy.tpl.php,节点的时候调用node-page.tpl.php,默认情况下调用node.tpl.php
谢谢
邓昌东

答复:

这个函数:
<?php
function _phptemplate_variables($hook, $vars = array()) {
switch ($hook) {
case 'node':
$vars['template_files'] = array('node-'. $vars['nid']);
break;
}
return $vars;
}
?>
你可以使用这种方法,如果用的是drupal5.X的话, 6.x我不知道这个方法是不是可行,不过也有相同的类似的方法.
就是在主题下面,建立一个template.php,然后向里面添加function _phptemplate_variables()函数,这个函数,里面根据你的实际作以下修改:
$vars['template_files'] = array('node-'. ‘front');
$vars['template_files'] = array('node-'. 'taxonomy');
$vars['template_files'] = array('node-'. 'page');

这样你就可以在你的主题下面使用node-front.tpl.php,node-taxonomy.tpl.php,node-page.tpl.php,这些模板的用法和node-nodetype.tpl.php是一样的。不过你需要在代码中加上一些判断条件,判断哪个是front,哪个是taxonomy,哪个是page。

具体怎么判断我就不多说了。
你可以参看相关的手册,特别是节点的那部分。

补充:这里还可以把 front, taxonomy, page归纳为变量$path, 可以这样用:

$vars['template_files'] = array('node-'.$path);

当然,前面你需要对$path进行一个处理。

如何将drupal节点置顶

无论是官方drupal.org,还是drupal china上,都有一篇文章置于最顶部,也就是最显眼的地方,由于我要搞drupal培训,发了篇培训信息,现在想把它置顶。现在看看怎么做?

找到“Zhupou.cn本周六,周日推出drupal培训课程”这篇文章,进入它的编辑页面,在“publishing options”(发布选项)中选中“Sticky
at top of lists”(置顶)。Ok,这样就搞定了。

以前在学习节点的时候,知道有个Sticky变量,而在drupal内部也有相应的字段,当时把它翻译为“粘的”,纯粹是按照字面意思翻译的,现在终于明白,这个是用来置顶的。汉语中也有对应的词汇“置顶”。

相关链接:http://zhupou.cn

如何翻译drupal的url(菜单路径)

我们知道,drupal的A语言的节点可以映射到另一个B语言的节点,而drupal的模块,也能够使用potx模块提取里面的可翻译字符串,生成模板文件,从而在多个语言之间切换。

对于语言的切换,你可以使用url的方式,比如说,admin/settings,这个路径,使用url的方式en/ admin/settings,cn/ admin/settings,这样就可以在en,cn两个语言之间切换了。

但是如果想对url也进行翻译呢?我的意思是说把admin/settings翻译成汉语拼音guanli/shezhi。我在实际项目中,就遇到了这样的问题。我要编写一个模块,让客户和网站联系。Drupal自带的contact
us满足不了需求。我们假定客户的需求是,对于英文的联系表单,使用路径http://example.com/contact-us,对于中文用户,路径使用http://example.com/lian-xi-wo-men
。然后下面是联系表单的各种字段,给出了中英文对应的文本。

编写一个模块,在菜单中定义路径contact-us,然后编写表单的逻辑,最后使用potx模板提取模块中的英文字段,然后将其中文化。将做好的po文件导入到drupal中,这个模块就汉化成功了。也就实现了中英文的切换,但是在切换的过程中,路径是不变的。怎么办?

我在网上看到许多人,问这样的问题,我在google上搜到了很多,比如:How to translate menu titles? Contact URL。等等,也看到有人写类似功能的实现,比如使用url别名,Multilingual
frontpage with translation and URL alias。

但是没有找到解决问题的办法,我仔细思考了drupal的国际化的机制,发现它并不支持url的翻译。这一点应该和drupal的菜单系统有关。那该怎么办呢?我从URL别名上获得了提示,使用两个别名,指向同一个内部路径,而两个别名之间是存在对应的翻译关系的。

实现的步骤如下,创建两个节点node1和node2,将两个节点用翻译关系对应起来,node1的本地语言为en,node2的本地语言为cn,设置node1的路径别名为contact-us,设置node2的路径别名为lian-xi-wo-men。

在模块中,实现一个区块钩子,这样模块中的表单就可以在区块中显示了,修改node1,node2对应的页面模板,去掉放置节点内容的congtent区域, 添加一个放置表单区块的区域,用来放置模块所生成的区块,最好放到正中央。配置模块生成的区块,将其仅显示在contact-u,lian-xi-wo-men这两个页面。

这样就实现了客户的要求了。在这里,节点node1和节点node2仅仅是一个壳子,作用就是放置表单中生成的页面的,而借助于节点之间的切换(使用localizer),就可以切换路径了。

不知道我讲的大家听懂了没有,应该还有更好的办法来翻译drupal的url吧,我这里仅仅是实现了功能,并没有真正改变内部的url。

相关链接: http://zhupou.cn



#253155 Changed theme_image... to theme('image'...
Ported path_to_subtheme() related code from D5.
#246701 IE 6 fixes. Thanks, CompShack. (Theme changes: Affects both .css files)



CONTENTS OF THIS FILE
-----------------------------------------------------------------------------------------
 * Introduction
 * Installation
 * Usage

INTRODUCTION
-----------------------------------------------------------------------------------------
Author Pane (http://drupal.org/project/author_pane) provides information about the author
of a node, comment, or page. From core, it collects the user picture, name, join
date, online status, contact link, and profile information. In addition, it gathers data
from many user related contributed modules and puts it together in a modifiable template
file.

INSTALLATION
-----------------------------------------------------------------------------------------
1. Copy the entire author_pane module directory into your normal directory for modules,
   usually sites/all/modules.

2. Enable the Author Pane module in ?q=admin/build/modules.

USAGE
-----------------------------------------------------------------------------------------
Advanced Forum:
If you have Advanced Forum installed, it will make use of Author Pane automatically on
forum posts. Advanced Forum provides its own Author Pane template and CSS so it can be
styled specifically for use in the forums.

Advanced Profile Kit:
If you have Advanced Profile Kit installed, it will make use of Author Pane automatically
on the default user page variant. Advanced Profile Kit provides its own Author Pane
template so it can be styled specifically for use on profile pages. Please note that if
you remove and re-add the Author Pane content type, you will need to edit the pane
settings and put "advanced_profile" back in the "Caller" field.

CTools content pane:
If you have Page Manager (from CTools) installed, you can add the Author Pane content
pane to any page variant. It requires the user context. You can choose an imagecache
preset to use for the user picture. You can also use the "caller" field to give this
instance a unique ID that can be accessed from the preprocess functions and the template
file.

Block:
There is an Author Pane block provided that you can enable. The block will show up on
user/NN, blog/NN, and node/NN where the node type is one that you allow in the block
config. If you want to exclude it from one of those page types, use the core block
visibility option. Exclusion of the /edit page happens automatically.

The block is disabled by default and must be enabled. Further options are available by
configuring the block:

* Node types to display on - Check on which node types the block should be shown. The
  block will show in the region it is placed, not literally on the node, and only on
  full node view pages. (ie: node/42 not when the node is part of a view)

* User picture preset - This is the Imagecache preset that will be used to format the
  user picture. Leave blank to show the full sized picture. Requires Imagecache module.

Theme function:
You can call the theme function directly and print the author pane anywhere in your code.
You must have a fully loaded user object to pass into the function. The rest of the
parameters are optional.

<?php
print theme('author_pane', $account, $caller, $picture_preset, $context, $disable_css);
?>

Parameters:
$account - The fully loaded user object. If all you have is a UID, you can get the object
with $account = user_load($uid); where $uid is a variable holding the user id.

$caller - (optional) This is an ID you can pass in as a way to track who is calling the
function. If you use Author Pane on your user profiles, on your blog pages, and in your
forums, you may want to display slightly different information in each Author Pane. By
passing in the caller, you can tell from within the preprocess functions where this is
going to be displayed.

$picture_preset - (optional) This is an imagecache picture preset that, if given, and
if imagecache is enabled, will be used to size the user picture on the author pane.

$context - (optional) This is usually a node or comment object and gives the context of
where the Author Pane has been placed so information from that context is available to
the template and preprocesses.

$disable_css - (optional) Because the Author Pane preprocess gets called after the code
that calls it, the Author Pane CSS file will be loaded last and clobber any earlier CSS.
This option tells Author Pane not to load its CSS so it uses the CSS of the caller. This
is mainly intended for Advanced Forum because the styles include Author Pane styling but
can be used for custom purposes as well.

#592692 by johnskulski: use theme_links instead of theme('links') for dropdown because we do not actually want a theme to change this output.

<?php
print theme('imagecache', 'preset_namespace', $image_filepath, $alt, $title, $attributes);
?>


    in theme('node'). theme('node') assumes it will be printing a title



api自己用勤用,不想老是想着自己写函数,要想着用人家的函数
1)node.tpl.php
    <?php  var_dump($node); ?>
    field_字段名[0]['view'];这些一般是cck来定义创建的
2)devel 模块 有了它 能更好的开发 主题(其实最方便的是主题)和模块  
    一)devel 可以查看每个页面调的变量
    二)Devel node access 看节点的访问权限
    三)Devel generate 生成测试用的用户 节点等
3)页面加载流程
    一)生成一堆变量,读入模板文件,呈现html给用户
4)dev   最基本的功能就是查看页面输出的变量
        dev load 在变量处理前读入的变量
    dev render输出前生成的变量 (初学者先用它吧)
      一)content变量 模板引擎处理过的要生成的内容的变量
      $content(是由数组串成的串) 也可以是 $node->content(它不行了,是一个数组)
5)drupal 有太多的主题theme函数,直接拿过来用 可 输出"用户名" 图像 表格等
    一)theme根据访问者的权限进行显示
    二)theme函数对html元素进行统一的 有规律的增加class类css
    三)theme函数网址 http://api.drupal.org/api/group/themeable/5
    四)重要的函数 theme() ;根据传来的变量寻找对应的函数
    theme('image',$path)...首先找theme_image函数,如果找到的话 就会
    调用theme_image($path)
    尽量使用 theme('image',$path) 尽量不使用 theme_image($path)
    再举个例子 <?php $user=user_load(array('uid'=>$node->uid)); ?>
          <?php print theme('username',$user); ?>
    五)常用的theme函数 (这些函数要实践一下)
        theme_block      模块开发时用到
        theme_box        显示div里面是传来的内容,只是自动生成class 不能手动添加class
        theme_image     通常在使用cck 创建图像后,传路径过来得到img
        theme_item_list  输出ul li 传进来的是数组,数组里的每个元素放在li里
        theme_links     用于显示超链接 好像与l函数差不多() 形如<ul><li><a href="#">AA</a><a href="#">BB</a></li></ul>的形式
        //比如首页 l('Return to index page','<front>')
        them_table     根据变量 输出带表头的表格
        theme_usename    输出带链接的用户名
    六)重写theme函数 theme函数调用机制(Hook机制)
       theme('username',$user)按下列顺序从所有文件中找
            theme-name_username()  //theme-name 是主题名
            比如主题名是mytheme 那么找 mytheme_username()
            theme-engine_username()//theme-engine 模板引擎名
            如果没有 找模板引擎 找 phptemplate_username()
            theme_username()
            如果没有 执行 theme_username() 输出结果
    七)重写在 自定义主题目录下的 template.php文件里
        例子//重写 _username     //$user不可以引用(&$user 至少在drupal 6 不可以)
            function phptemplate_username($user){
                return 'hello '.$user->name;
            }
   

<?php
function drop_preprocess_comment(&$variables) {

  // Setup a few variables.
  $comment = $variables['comment'];
  $title = l(
    $comment->subject,
    comment_node_url(),
    array('fragment' => "comment-$comment->cid")
  );
  $new_marker = $comment->new ? t('new') : '';
  $by_line = t('by') .' '. theme('username', $comment);

  // Form the markup.
  $summary = '<div>';
  $summary .= '<span>' . "$title $new_marker</span>";
  $summary .= '<span>' . "$by_line</span>";
  $summary .= '</div>';

  // Set the comment into the right region.
  drupal_set_content('right', $summary);
}
?>



- #243172 Theme('calendar_empty') should be theme('calendar_empty_day'), patch


#592692 by johnskulski: use theme_links instead of theme('links') for dropdown because we do not actually want a theme to change this output.



api自己用勤用,不想老是想着自己写函数,要想着用人家的函数
1)node.tpl.php
    <?php  var_dump($node); ?>
    field_字段名[0]['view'];这些一般是cck来定义创建的
2)devel 模块 有了它 能更好的开发 主题(其实最方便的是主题)和模块  
    一)devel 可以查看每个页面调的变量
    二)Devel node access 看节点的访问权限
    三)Devel generate 生成测试用的用户 节点等
3)页面加载流程
    一)生成一堆变量,读入模板文件,呈现html给用户
4)dev   最基本的功能就是查看页面输出的变量
        dev load 在变量处理前读入的变量
    dev render输出前生成的变量 (初学者先用它吧)
      一)content变量 模板引擎处理过的要生成的内容的变量
      $content(是由数组串成的串) 也可以是 $node->content(它不行了,是一个数组)
5)drupal 有太多的主题theme函数,直接拿过来用 可 输出"用户名" 图像 表格等
    一)theme根据访问者的权限进行显示
    二)theme函数对html元素进行统一的 有规律的增加class类css
    三)theme函数网址 http://api.drupal.org/api/group/themeable/5
    四)重要的函数 theme() ;根据传来的变量寻找对应的函数
    theme('image',$path)...首先找theme_image函数,如果找到的话 就会
    调用theme_image($path)
    尽量使用 theme('image',$path) 尽量不使用 theme_image($path)
    再举个例子 <?php $user=user_load(array('uid'=>$node->uid)); ?>
          <?php print theme('username',$user); ?>
    五)常用的theme函数 (这些函数要实践一下)
        theme_block      模块开发时用到
        theme_box        显示div里面是传来的内容,只是自动生成class 不能手动添加class
        theme_image     通常在使用cck 创建图像后,传路径过来得到img
        theme_item_list  输出ul li 传进来的是数组,数组里的每个元素放在li里
        theme_links     用于显示超链接 好像与l函数差不多(类似 但不一样)
        theme('links',$primary_links, array('id'=>'site_menu'));//$primary_links数组
        http://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_links/6
        //function theme_links($links, $attributes = array('class' => 'links'))
        l($links->title, 'node/'.$links->nid); //$links->title, 'node/'.$links->nid只是一个
        //比如首页 l('Return to index page','<front>')
        them_table     根据变量 输出带表头的表格
        theme_usename    输出带链接的用户名
    六)重写theme函数 theme函数调用机制(Hook机制)
       theme('username',$user)按下列顺序从所有文件中找
            theme-name_username()  //theme-name 是主题名
            比如主题名是mytheme 那么找 mytheme_username()
            theme-engine_username()//theme-engine 模板引擎名
            如果没有 找模板引擎 找 phptemplate_username()
            theme_username()
            如果没有 执行 theme_username() 输出结果
    七)重写在 自定义主题目录下的 template.php文件里
        例子//重写 _username     //$user不可以引用(&$user 至少在drupal 6 不可以)
            function phptemplate_username($user){
                return 'hello '.$user->name;
            }
   

主题包含的文件
  1)主题名.info文件
  2)page.tpl.php (可以没有)
  3)node.tpl.php (可以没有)
  4)block.tpl.php (可以没有)
  5)logo.png 主题的网站标志  (可以没有)
  6)screenshot.png 主题显示效果截图  (可以没有)

1)info文件
    name = management    name 必须,主题名称,与当前主题文件夹名称相同
    description = management template 推荐,主题描述
    version = 1.x        推荐,当前主题的版本号
    core = 6.x        必须,drupal 的版本号,还对cvs有帮助
    engine = phptemplate    多数情况下必须,如果有父主题,可以不用指明
    stylesheets[all][] = style.css    样式表
    scripts[] = script.js    script脚本
    screenshot = screenshot.png
    regions[left] = Left sidebar  右边是用户可读的区域名字
    regions[right] = Right sidebar
    regions[content] = Content
    regions[header] = Header
    regions[footer] = Footer
    base theme 基主题 子主题可以声明一个基主题 这允许主题的继承
    features  //不太懂 许多由主题控制输出的页面元素,可以在主题的配置页面启用或者禁用
    php = 4.3.3     这个定义了主题支持的PHP最低版本。而对于大多数的主题,都不应该添加这一项。
只有建好info文件 才能在后台看到主题
2)没有效果截图,在主题文件夹下加上screenshot.png
    如果info中没有配置,默认是screenshot.png
3)建空的 page.tpl.php 清空缓存

    注:如果输出了空白页面,下次无法清空缓存,可以访问如下地址:
    admin/settings/performance这时候只要在页面的page.tpl.php标签内部输入
    print $content;这时就会输出页面内容,
    (admin/settings/performance网址始终是不用缓存的)
    就可以看到“clear cached
    data”按钮了,清空之后再把我们加上的print $content;去掉后继续我们
    的内容)。
    如果是在linux下
    开发,可能会遇到文件权限问题,导致源代码也看不到输出,我的习惯首先将
    使用的文件夹设置成当前用户作为文件夹所有者,这样一般不会导致上述问题
    出现
4)变量含义
 $head 页头的html,比如页面编码声明,ico标识等内容。
 $head_title 网页标题
 $styles 样式表
 $scripts js文件
 $site_name 站点名字
 $header 是body里的header 与 $head 不要混淆了 regions[header]
 $left  regions[left]
 //我们不对regions定义 ,这样就使用默认的regions
 $right  regions[right]
 //我们可以定义以下:
 regions[lefttop] = leftTop
 此时必须还要定义 regions[left] regions[right]等 否则 $left $right失效
 $search_box //是什么东西?查一下

5)函数含义
    print theme('links',$primary_links, array('id'=>'site_menu'));
    
    //$primary_links 是主导航接组成的数组
            array(3) {
          ["menu-144"]=>
          array(3) {
            ["attributes"]=>
            array(1) {
              ["title"]=>
              string(0) ""
            }
            ["href"]=>
            string(27) "http://www.drupalstudy.shi/"
            ["title"]=>
            string(6) "首页"
          }
          ["menu-145"]=>
          array(3) {
            ["attributes"]=>
            array(1) {
              ["title"]=>
              string(0) ""
            }
            ["href"]=>
            string(32) "http://localhost/drupal/node/10 "
            ["title"]=>
            string(9) "毛太祖"
          }
          ["menu-146"]=>
          array(3) {
            ["attributes"]=>
            array(1) {
              ["title"]=>
              string(0) ""
            }
            ["href"]=>
            string(30) "http://localhost/drupal/node/8"
            ["title"]=>
            string(9) "邓太宗"
          }
        }



Drupal主题制作指南(v6).chm 这个文件比较难 ,但知识丰富

1)当你需要管理UI设置或者logo、搜索、使命(mission)等等以外的“特性”时,
  可以使用"theme-settings.php"文件。这是一个高级特性。
2)对于颜色模块(color module)的支持,需要一个"color"目录,里面放置"color.inc"文件,
  以及其它各种支持文件。
3)http://drupal.org/node/43816 多站点安装
4)主题函数theme_menu_local_tasks,是一个用来输出一级和二级标签的简单函数。
    theme是主题名,也可以是引擎名
    本例中,Garland是使用引擎名来覆写的。如果你的主题是基于Garland的子主题,
    那么你必须使用你的主题名了。
    <?php
    function drop_menu_local_tasks() {
      $output = '';

      if ($primary = menu_primary_local_tasks()) {
        $output .= "<ol class=\"tabs primary\">\n". $primary ."</ol>\n";
      }
      if ($secondary = menu_secondary_local_tasks()) {
        $output .= "<ol class=\"tabs secondary\">\n". $secondary ."</ol>\n";
      }

      return $output;
    }
    ?>
5)下面为search-theme-form.tpl.php的一个例子。
  注意在这里,主题钩子就是"search_theme_form",
6)Drupal以模板的方式识别主题钩子是自动完成的。下面是完成修改所需的所有必要条件:
  模板名必须与主题钩子匹配。
  主题钩子中的下划线必须改为连字符。
  模板文件必须使用扩展名".tpl.php"。(根据主题引擎的不同,扩展名会有所不同)
  假如主题函数为theme_user_signature。这里的主题钩子就是"user_signature"。
  创建一个名为"user-signature.tpl.php"的文件,清空注册表,就会告诉Drupal现在钩子已改为模板方式了。
  现在该文件中的内容将替代相应的函数。
  这里的难点是,设置模板文件中用到的变量,这可以通过预处理函数来完成。
7)对于大多数主题开发者来说,都不需要直接与注册表打交道。
  只需要记住,当添加或者删除主题函数和模板时,要清空它。
  编辑已有的函数和模板时,则不需要清空。
8)清空主题缓存 使用API函数drupal_rebuild_theme_registry。 只清空主题注册表的缓存
9)位于"Administer > Site configuration > Performance"的clear按钮。  也同时也清空了.info的缓存。
  如果启用了devel区块(devel模块创建的),点击"Empty cache"连接。  也同时也清空了.info的缓存。
10)对于可疑字符串,一定要用check_plain。
11)建议只有和基模板放在一块时,才起作用。
  模板可以放在主题下面的恶任意子目录下,但是必须将其放到一块。
  建议的修改添加删除,不需要清空主题注册表。只有基模板注册时才需要。而Drupal可以自动识别建议的。
  建议只有和基模板放在同一个目录下面时,才能工作.换句话说,
  为了让comment-blog.tpl.php正常工作,你需要把comment.tpl.php也放到同一个目录下.

 
12)maintenance-page-[offline].tpl.php
  基模板: maintenance-page.tpl.php
  当数据库不可用时,应用该模板建议.用来为用户展示一个不带错误信息的页面.
  首先需要设置维护页面的主题化.
13)在默认情况下,如果你主题的.info文件中没有定义样式表的话,将会使用"style.css"文件。
  添加其它的样式表非常简单,只需要定义一个新的'stylesheets'键,
  媒体属性(media property)和样式表的名称。
  注意,定了了定制的样式表后,就不再加载默认的"style.css"了。
  如果你的主体需要使用它的话,你需要在info文件中明确声明它。
  ; Add a stylesheet for all media
  stylesheets[all][] = theStyle.css
  ; Add a stylesheets for screen and projector media
  stylesheets[screen, projector][] = theScreenProjectorStyle.css
  ; Add a stylesheet for print media
  stylesheets[print][] = thePrintStyle.css
  注意[]的使用,在[media]和“= styleName.css”之间,使用了[]。
  这里定义的顺序,就是样式表在页首出现的顺序。
  样式表可以出现在子目录下面,比如stylesheets[all][] = stylesheets/styleName.css.
  这样易于管理样式表。
14) js
  Drupal.theme.prototype.powered = function(color, height, width) {
    return '<img src="/misc/powered-'+ color +'-'+ height +'x'+ width +'.png" />";
  }
  我调用它的方式是            
  $('.footer').append(Drupal.theme('powered', 'black', 135, 42));
  Drupal.theme.prototype.powered = function(color, height, width) {
    return '<img src="/misc/powered-'+ color +'-'+ height +'x'+ width +'.png" />";
  }
  我调用它的方式是            
  $('.footer').append(Drupal.theme('powered', 'black', 135, 42));
  这将在页脚添加一个按钮。
15)如果我想在我的主题中覆写这个函数,可以使用我主题目录下面的文件来代替/misc,我可以这样:
  Drupal.theme.prototype.powered = function(color, height, width) {
    return '<img src="/sites/all/themes/powered_images/powered-'+ color +'-'+ height +'x'+ width +'.png" />";
  }
  这个利用了普通JavaScript的优点。前面的函数放在主题里面的一个JavaScript文件中,
  从而避免修改相关模块的JavaScript文件。
  JavaScript主题函数的返回类型可以多种多样。既可以是简单的字符串,
  也可以是复杂的数据类型,比如对象,数组,
  和jQuery元素。参考原始的函数,看它返回什么,在你的定制主题函数中就应该返回什么。
16)     这些复选框,是根据.info文件中的特性(features)生成的.声明方式为'features'+“[]”+“=”+特性本身,例如features[] = the_feature。如果一个也没有定义的话,将会使用下面的默认值
    features[] = logo
    features[] = name
    features[] = slogan
    features[] = mission
    features[] = node_user_picture
    features[] = comment_user_picture
    features[] = search
    features[] = favicon
    features[] = primary_links
    features[] = secondary_links
    为了禁用一些特性,只需要在.info文件中添加你需要的特性就可以了。
    定义需要的,就会将不需要的忽略掉。有些特性也会启用一些相关的表单字段。
    例如,'logo'将启用一个上传字段,用于上传图片。
    已不再支持hook_features()
17)主题作者可以使用高级表单API(auto-completion,可伸缩字段集)
  和JQuery javascript来创建复杂的动态的表单
18)
    在你的template.php文件的顶部附近添加下面的代码:
    <?php
    /*
    * Initialize theme settings
    */
    if (is_null(theme_get_setting('garland_happy'))) {  // <-- change this line
      global $theme_key;

      /*
       * The default values for the theme variables. Make sure $defaults exactly
       * matches the $defaults in the theme-settings.php file.
       */
      $defaults = array(             // <-- change this array
        'garland_happy' => 1,
        'garland_shoes' => 0,
      );

      // Get default theme settings.
      $settings = theme_get_settings($theme_key);
      // Don't save the toggle_node_info_ variables.
      if (module_exists('node')) {
        foreach (node_get_types() as $type => $name) {
          unset($settings['toggle_node_info_' . $type]);
        }
      }
      // Save default theme settings.
      variable_set(
        str_replace('/', '_', 'theme_'. $theme_key .'_settings'),
        array_merge($defaults, $settings)
      );
      // Force refresh of Drupal internals.
      theme_get_setting('', TRUE);
    }
    ?>

19)维护使用新的主题
    <?php
        $conf['maintenance_theme'] = 'themeName';
    ?>
20)先你需要确保你的HTML或者xHTML通过合法性验证,
  然后才能开始修改你的CSS来修正你的bugs。Firefox 的Web Developer toolbar
 (web开发者工具栏)内置了一个web验证器。Opera也内置了合法性验证,
  只需要按下Ctrl+Alt+V就可以了。
   两个扩展插件,开发者工具栏和查看格式化源文件
  一个更高级的工具是Watchfire WebXACT tool,可用于检查代码,分析HTML页面,定位错误。

21)使用PHP变量
  禁止对容器使用固定的宽度
  对于一些复杂的或者灵活的设计,比如fullheight,需要大量的工作来实现max-width 和min-width。
  当插入一个设计者想要的图形效果时,要保证在IE下面也能正常工作。
  IE和Firefox的兼容性问题
  从头编写一个主题

22)
  以用户1的身份登录.
  为了得到一些菜单项,启用下面的模块: aggregator, blog, node, page, search, story 和tracker.
  打开主题支持的特性(logo(标识), site name(站名), slogan(标语), search box(搜索框)).如果需要的话,可以添加一些一级和二级链接.我们建议使用"Link 1" "Link 2" "Link 3",你可以将它们链接到,比如"user/1".
  将站名设为Drupal,标语设为Community Plumbing
  创建一个story节点:
  查看该节点,确保所有标签都能被看到.截图.
  对截图进行切图,大小为420x254,对生成的图片调整大小, 调整为150x90(原始尺寸的35%).
  在这里只展示有用的页面元素(菜单,标签,标题,链接)。不要包括浏览器的东西(工具栏,状态栏,滚动条等)。
  为了更加清晰一些,可以对缩略图使用一个标准的'sharpen'过滤器。
  保存为PNG格式,选择paletted colorspace,这样可以减小文件大小。


 


weblinks_blocks.module
文件的大约166行
  if ($show_image && $node->iid) {
 应改成  if ($show_image && $node->iids) {

总而言之把 166行下面几行改成
 if ($show_image && $node->iids) {
       theme('image_attach_attached_images_block', $node->nid, $image_nodes);
      foreach($node->iids as $key=>$iid){
          $firstIid = $iid;
          $imageObj = node_load($firstIid);
          $image = "<img alt='".$node->title."' src='".$imageObj->images['_original']."' />";
          $options['html']=true;
          $image =   l($image, $node->url,$options);
           //$image = theme('image_attach_teaser', $node);
           break;
      }
  }

190行下面既显示图像又显示文字
  return array(
    'data' => weblinks_blocks_build_link($node, $title_length, $urlnode, $options) . $image . $description,
    'class' => 'weblinks weblinks-item weblinks-link-'. $row['nid'],
    );
}
如果不显示文字 自然 就把weblinks_blocks_build_link($node, $title_length, $urlnode, $options) .去掉



api自己用勤用,不想老是想着自己写函数,要想着用人家的函数
1)node.tpl.php
    <?php  var_dump($node); ?>
    field_字段名[0]['view'];这些一般是cck来定义创建的
2)devel 模块 有了它 能更好的开发 主题(其实最方便的是主题)和模块  
    一)devel 可以查看每个页面调的变量
    二)Devel node access 看节点的访问权限
    三)Devel generate 生成测试用的用户 节点等
3)页面加载流程
    一)生成一堆变量,读入模板文件,呈现html给用户
4)dev   最基本的功能就是查看页面输出的变量
        dev load 在变量处理前读入的变量
    dev render输出前生成的变量 (初学者先用它吧)
      一)content变量 模板引擎处理过的要生成的内容的变量
      $content(是由数组串成的串) 也可以是 $node->content(它不行了,是一个数组)
5)drupal 有太多的主题theme函数,直接拿过来用 可 输出"用户名" 图像 表格等
    一)theme根据访问者的权限进行显示
    二)theme函数对html元素进行统一的 有规律的增加class类css
    三)theme函数网址 http://api.drupal.org/api/group/themeable/5
    四)重要的函数 theme() ;根据传来的变量寻找对应的函数
    theme('image',$path)...首先找theme_image函数,如果找到的话 就会
    调用theme_image($path)
    尽量使用 theme('image',$path) 尽量不使用 theme_image($path)
    再举个例子 <?php $user=user_load(array('uid'=>$node->uid)); ?>
          <?php print theme('username',$user); ?>
    五)常用的theme函数 (这些函数要实践一下)
        theme_block      模块开发时用到
        theme_box        显示div里面是传来的内容,只是自动生成class 不能手动添加class
        theme_image     通常在使用cck 创建图像后,传路径过来得到img
        theme_item_list  输出ul li 传进来的是数组,数组里的每个元素放在li里
        theme_links     用于显示超链接 好像与l函数差不多(类似 但不一样)
        theme('links',$primary_links, array('id'=>'site_menu'));//$primary_links数组
        http://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_links/6
        //function theme_links($links, $attributes = array('class' => 'links'))
        l($links->title, 'node/'.$links->nid); //$links->title, 'node/'.$links->nid只是一个
        //比如首页 l('Return to index page','<front>')
        them_table     根据变量 输出带表头的表格
        theme_usename    输出带链接的用户名
    六)重写theme函数 theme函数调用机制(Hook机制)
       theme('username',$user)按下列顺序从所有文件中找
            theme-name_username()  //theme-name 是主题名
            比如主题名是mytheme 那么找 mytheme_username()
            theme-engine_username()//theme-engine 模板引擎名
            如果没有 找模板引擎 找 phptemplate_username()
            theme_username()
            如果没有 执行 theme_username() 输出结果
    七)重写在 自定义主题目录下的 template.php文件里
        例子//重写 _username     //$user不可以引用(&$user 至少在drupal 6 不可以)
            function phptemplate_username($user){
                return 'hello '.$user->name;
            }
   

主题包含的文件
  1)主题名.info文件
  2)page.tpl.php (可以没有)
  3)node.tpl.php (可以没有)
  4)block.tpl.php (可以没有)
  5)logo.png 主题的网站标志  (可以没有)
  6)screenshot.png 主题显示效果截图  (可以没有)

1)info文件
    name = management    name 必须,主题名称,与当前主题文件夹名称相同
    description = management template 推荐,主题描述
    version = 1.x        推荐,当前主题的版本号
    core = 6.x        必须,drupal 的版本号,还对cvs有帮助
    engine = phptemplate    多数情况下必须,如果有父主题,可以不用指明
    stylesheets[all][] = style.css    样式表
    scripts[] = script.js    script脚本
    screenshot = screenshot.png
    regions[left] = Left sidebar  右边是用户可读的区域名字
    regions[right] = Right sidebar
    regions[content] = Content
    regions[header] = Header
    regions[footer] = Footer
    base theme 基主题 子主题可以声明一个基主题 这允许主题的继承
    features  //不太懂 许多由主题控制输出的页面元素,可以在主题的配置页面启用或者禁用
    php = 4.3.3     这个定义了主题支持的PHP最低版本。而对于大多数的主题,都不应该添加这一项。
只有建好info文件 才能在后台看到主题
2)没有效果截图,在主题文件夹下加上screenshot.png
    如果info中没有配置,默认是screenshot.png
3)建空的 page.tpl.php 清空缓存

    注:如果输出了空白页面,下次无法清空缓存,可以访问如下地址:
    admin/settings/performance这时候只要在页面的page.tpl.php标签内部输入
    print $content;这时就会输出页面内容,
    (admin/settings/performance网址始终是不用缓存的)
    就可以看到“clear cached
    data”按钮了,清空之后再把我们加上的print $content;去掉后继续我们
    的内容)。
    如果是在linux下
    开发,可能会遇到文件权限问题,导致源代码也看不到输出,我的习惯首先将
    使用的文件夹设置成当前用户作为文件夹所有者,这样一般不会导致上述问题
    出现
4)变量含义
 $head 页头的html,比如页面编码声明,ico标识等内容。
 $head_title 网页标题
 $styles 样式表
 $scripts js文件
 $site_name 站点名字
 $header 是body里的header 与 $head 不要混淆了 regions[header]
 $left  regions[left]
 //我们不对regions定义 ,这样就使用默认的regions
 $right  regions[right]
 //我们可以定义以下:
 regions[lefttop] = leftTop
 此时必须还要定义 regions[left] regions[right]等 否则 $left $right失效
 $search_box //是什么东西?查一下

5)函数含义
    print theme('links',$primary_links, array('id'=>'site_menu'));
    
    //$primary_links 是主导航接组成的数组
            array(3) {
          ["menu-144"]=>
          array(3) {
            ["attributes"]=>
            array(1) {
              ["title"]=>
              string(0) ""
            }
            ["href"]=>
            string(27) "http://www.drupalstudy.shi/"
            ["title"]=>
            string(6) "首页"
          }
          ["menu-145"]=>
          array(3) {
            ["attributes"]=>
            array(1) {
              ["title"]=>
              string(0) ""
            }
            ["href"]=>
            string(32) "http://localhost/drupal/node/10 "
            ["title"]=>
            string(9) "毛太祖"
          }
          ["menu-146"]=>
          array(3) {
            ["attributes"]=>
            array(1) {
              ["title"]=>
              string(0) ""
            }
            ["href"]=>
            string(30) "http://localhost/drupal/node/8"
            ["title"]=>
            string(9) "邓太宗"
          }
        }


1)警告!模块的内部名称如果与主题的内部名称重名的话,那么你的站点将不能工作。
  因为可能会造成同名函数的存在,
  这在PHP中是非法的。每个安装了的部件(模块或者主题)都必须有一个唯一的名字。
2).info文件中的内容是缓存在数据库中的,所以对它的修改不会在Drupal中立马生效。
  (不要与主题注册表的缓存相混淆了。)为了清除缓存,须这样做:
3)看主题 http://drupal.org/node/171206  http://drupal.org/node/171205#example#example
4)主题的结构和继承 http://drupal.org/node/225125
5)增加样式表 druap_add_css($directory.'/node-job_app.css');


1)尽管在Drupal 6中PHPTemplate.engine还存在,但它已不再覆写主题函数了
2)不需要直接与注册表打交道。只需要记住,当添加或者删除主题函数和模板时,
  要清空它。编辑已有的函数和模板时,则不需要清空。
3)清空主体注册表,有3方式:
    1.    位于"Administer > Site configuration > Performance"的clear按钮。
    2.    如果启用了devel区块(devel模块创建的),点击"Empty cache"连接。
    3.    使用API函数drupal_rebuild_theme_registry。
4)主题注册表是主题钩子相关信息的缓存数据,包括Drupal可用的主体钩子,钩子类型,即如何处理它们。
    你主题用到的引擎应该为你自动的注册所有的主题钩子。
5)在一些特殊情况下,你需要直接与注册表打交道。
    如果你的主题需要注册一个新的钩子,而该钩子不在底层中(内核,模块,引擎)。
    比如说一些表单,内核或者模块没有明确对其主体化,而仅仅使用了默认的表单输出。
6)不要将主题注册表与主题的.info文件混淆了,两者都被缓存了。清空主题注册表的第1点和第2点,
    同时也清空了.info的缓存。
7)预处理函数仅适用于模板形式的主题钩子.它的主要作用是设置模板文件(*.tpl.php)中所用到的变量。
    在预处理器(Preprocessor)中,一般涉及不到普通的主题函数。
    在提供模板建议(template suggestions)时也会用到预处理器。
    在drupal5中,函数_phptemplate_variables提供了同样的功能,在drupal6中,
    为了以后版本的兼容性,最好不要用这个函数。
8) 下面是预期的预处理器。当它们同时存在时,按照下面的顺序运行:此处略1230字
9)  themes/engines 目录下,Drupal 就会去使用它们,并查找出所对应的有效的主题。
    下面是Drupal 查找Theme 的流程:(1)查找themes 目录下的所有子目录,
    找出以.theme 为扩展名的文件。
    这些文件的名称一定要和子目录的名称一致,这样这个theme 就会被Drupal 收录。
10)tpl.php中的四大变量  $user,$node,$comment,$block



1)所谓主题注册表缓存了可用的主题数据的信息。
  要在你的主题中添加或删除模板文件或者主题函数,你需要重设主题注册表。
2)自定义函数, 重写主题函数或者其他任何对原始输出的自定义都应该在这里(template.php)完成。
  此文件(template.php)必须以PHP的开始标记(<?php)打头,但是结束标记并非必需,并且我们建议您不要添加它。
3)子主题(sub-theme)
  表面上,子主题的表现和其他主题一样。唯一的区别就在于它能够继承“父主题”的资源。
  要创建子主题,需要在.info文件里添加一个”base theme”(基础主题)条目。子主题就是从那儿继承父主题的资源。可以使用多重继承。
  也就是说,一个子主题可以声明为另一个主题的基础主题(base theme)。
  对于多重继承没有硬性限制。Drupal 5及更低版本要求子主题必须在父主题的子文件夹里。
  现在已经没有这样的限制了。
4)要提供自定义的主题管理界面和设置,或者logo、搜索、站点宗旨(mission)之外的“特性”设置,
  可以添加一个”theme-settings.php” 文件。 这是一个高级功能。
5)要启用色彩模块支持,包含”color.inc”的名为”color“的文件夹以及
  相应的css文档和图像文件就是必须的。
6)如果你打算以某个核心主题为基础开始工作,请使用子主题功能或者复制后重命名为你自己
  的文件夹。强烈建议你不要直接修改默认主题Garland或者Minnelli,
  因为这两个主题在系统安装和升级时会用到。
7)所以主题都应该安装在”sites/all/themes” 文件夹,与核心文件分开。
  阅读关于多站点支持的内容来了解在其他文件夹安装主题的情况。
8)要声明一个父主题,或成为“基本主题”,将下列语句添加到子主题的.info文件中
  themeName”替换为您的父主题的内部名字。
  base theme = themeName
  下列资源会被继承:
    父主题中定义的所有样式表,但是这也是可以通过某些选项来控制的。
    父主题中定义的所有JavaScripts。
    所有的模板文件(.tpl.php)。
    文件”template.php”中定义的所有内容。包括主题函数重写, 预处理器和其他所有东西。
    所有子主题把它自己的template.php文件和父主题的该文件包含在一起。
    父主题的截图,只要.info文件使用了和他的父主题一样的设置。
  下列资源不会被继承:
    为父主题制定的logo.png文件。不包括用户上传的logo,因为他们总是会被使用。
    .info文件定义的某些设置。 This includes regions. If you are not using the default regions, then make sure your “page.tpl.php” file for the sub-theme matches what is set for regions in the .info file. Each base and sub-theme can have their own region settings.
    Anything set within the “theme-settings.php” file for the 主题高级设置.
    Anything set within the “color” directory for color模块支持.
9)从Drupal 6开始,每个主题都需要一个信息文件。这个文件必须一直在你的主题的根目录下。
    没有这个文件,    你的主题将不会被Drupal侦测到。  .info文件必须是以”.info”为文件后缀名。
    “机器” 可读的主题的[内部名]来源于这个文件。例如,如果这个文件的被命名为”drop.info”,
    那么Drupal就好认为相应的主题名为”drop”。请注意不要用特殊字符,
    因为Drupal会在很多PHP函数中用到这个名字因此在PHP语言中命名字符串的限制也适用于这个内部名的命名。
    必须以字母开头,不可带空格和标点。可以使用下划线(_)但不可以使用连字号(-)。
    数字也是被允许的,只是不能用作首字符。
10)和你的主题内部名相同的模块可能会造成站点无法工作。因为这可能引起函数的重复定义,
    而这是不被PHP允许的。你安装的所有外部组件都必须有唯一的名字。
    info文件的内容被换成在数据库中,所有替换或者修改这个文件并不会引起Drupal的注意。
    (不要将这种情况和主题注册表的缓存好混淆。)要清空缓存
    三种方法清缓
     一)管理(Administer) > 站点设置(Site configuration) > 性能(Performance)”的”清除缓存数据(clear)” 按钮。
http://www.drupalstudy.shi/admin/settings/performance
       二)devel区块(由模块devel提供) ,点击链接 “清空缓存(Empty cache)” 。
     三)再次访问位于”管理(Administer) > 站点构建(Site building) > 主题(Themes)”的主题选择页面。
11)语法与 INI 文件类似。.info文件本质上就是一个配置主题的文本文档。
    分号用以在行外面添加注释。
    Drupal只懂得下列的键名(带!号的为必须设定的键值)。Drupal会为没有在.info文件中指定的键使用默认值。
    name !  人读
    description *
    screenshot
    version *
    core !
    engine *
    base theme
    regions
    features
    stylesheets
    scripts
    php

12)regions
    如果没有块域被定义,Drupal会假定下列块域可用。如果需要,你可以覆写这些值。
    regions[left] = Left sidebar
    regions[right] = Right sidebar
    regions[content] = Content
    regions[header] = Header
    regions[footer] = Footer
13)features 不太懂
    在主题设定页面可以选择开关的主题特性。”features” 键控制在主题设置页面哪些特性可以设定。
    当你的主题没有定义某些元素的时候你就可以使用这个键值来关闭这些元素显示与否的可设置性。
    要停用某项设置的复选框,略过这个条目不写即可。但是,如果所有条目都不写,由于系统的默认假定,
    所有的复选框都会被显示出来。下面的例子显示了所有可用的设定项。.
    通过注释掉primary_links和secondary_links元素,
    相应的复选框就被禁止显示,不会被站点管理员看到。
    features[] = logo
    features[] = name
    features[] = slogan
    features[] = mission
    features[] = node_user_picture
    features[] = comment_user_picture
    features[] = search
    features[] = favicon
    ; These last two disabled by redefining the
    ; above defaults with only the needed features.
    ; features[] = primary_links
    ; features[] = secondary_links
14)stylesheets
    stylesheets[all][] = theStyle.css
15)scripts[与stylesheets同理]
16)php
    定义主题可以支持的最低PHP版本。
17)project = "drupal"
18)datestamp = "1202913006"



Drupal主题制作指南(v6).chm 这个文件比较难 ,但知识丰富

1)当你需要管理UI设置或者logo、搜索、使命(mission)等等以外的“特性”时,
  可以使用"theme-settings.php"文件。这是一个高级特性。
2)对于颜色模块(color module)的支持,需要一个"color"目录,里面放置"color.inc"文件,
  以及其它各种支持文件。
3)http://drupal.org/node/43816 多站点安装
4)主题函数theme_menu_local_tasks,是一个用来输出一级和二级标签的简单函数。
    theme是主题名,也可以是引擎名
    本例中,Garland是使用引擎名来覆写的。如果你的主题是基于Garland的子主题,
    那么你必须使用你的主题名了。
    <?php
    function drop_menu_local_tasks() {
      $output = '';

      if ($primary = menu_primary_local_tasks()) {
        $output .= "<ol class=\"tabs primary\">\n". $primary ."</ol>\n";
      }
      if ($secondary = menu_secondary_local_tasks()) {
        $output .= "<ol class=\"tabs secondary\">\n". $secondary ."</ol>\n";
      }

      return $output;
    }
    ?>
5)下面为search-theme-form.tpl.php的一个例子。
  注意在这里,主题钩子就是"search_theme_form",
6)Drupal以模板的方式识别主题钩子是自动完成的。下面是完成修改所需的所有必要条件:
  模板名必须与主题钩子匹配。
  主题钩子中的下划线必须改为连字符。
  模板文件必须使用扩展名".tpl.php"。(根据主题引擎的不同,扩展名会有所不同)
  假如主题函数为theme_user_signature。这里的主题钩子就是"user_signature"。
  创建一个名为"user-signature.tpl.php"的文件,清空注册表,就会告诉Drupal现在钩子已改为模板方式了。
  现在该文件中的内容将替代相应的函数。
  这里的难点是,设置模板文件中用到的变量,这可以通过预处理函数来完成。
7)对于大多数主题开发者来说,都不需要直接与注册表打交道。
  只需要记住,当添加或者删除主题函数和模板时,要清空它。
  编辑已有的函数和模板时,则不需要清空。
8)清空主题缓存 使用API函数drupal_rebuild_theme_registry。 只清空主题注册表的缓存
9)位于"Administer > Site configuration > Performance"的clear按钮。  也同时也清空了.info的缓存。
  如果启用了devel区块(devel模块创建的),点击"Empty cache"连接。  也同时也清空了.info的缓存。
10)对于可疑字符串,一定要用check_plain。
11)建议只有和基模板放在一块时,才起作用。
  模板可以放在主题下面的恶任意子目录下,但是必须将其放到一块。
  建议的修改添加删除,不需要清空主题注册表。只有基模板注册时才需要。而Drupal可以自动识别建议的。
  建议只有和基模板放在同一个目录下面时,才能工作.换句话说,
  为了让comment-blog.tpl.php正常工作,你需要把comment.tpl.php也放到同一个目录下.

 
12)maintenance-page-[offline].tpl.php
  基模板: maintenance-page.tpl.php
  当数据库不可用时,应用该模板建议.用来为用户展示一个不带错误信息的页面.
  首先需要设置维护页面的主题化.
13)在默认情况下,如果你主题的.info文件中没有定义样式表的话,将会使用"style.css"文件。
  添加其它的样式表非常简单,只需要定义一个新的'stylesheets'键,
  媒体属性(media property)和样式表的名称。
  注意,定了了定制的样式表后,就不再加载默认的"style.css"了。
  如果你的主体需要使用它的话,你需要在info文件中明确声明它。
  ; Add a stylesheet for all media
  stylesheets[all][] = theStyle.css
  ; Add a stylesheets for screen and projector media
  stylesheets[screen, projector][] = theScreenProjectorStyle.css
  ; Add a stylesheet for print media
  stylesheets[print][] = thePrintStyle.css
  注意[]的使用,在[media]和“= styleName.css”之间,使用了[]。
  这里定义的顺序,就是样式表在页首出现的顺序。
  样式表可以出现在子目录下面,比如stylesheets[all][] = stylesheets/styleName.css.
  这样易于管理样式表。
14) js
  Drupal.theme.prototype.powered = function(color, height, width) {
    return '<img src="/misc/powered-'+ color +'-'+ height +'x'+ width +'.png" />";
  }
  我调用它的方式是            
  $('.footer').append(Drupal.theme('powered', 'black', 135, 42));
  Drupal.theme.prototype.powered = function(color, height, width) {
    return '<img src="/misc/powered-'+ color +'-'+ height +'x'+ width +'.png" />";
  }
  我调用它的方式是            
  $('.footer').append(Drupal.theme('powered', 'black', 135, 42));
  这将在页脚添加一个按钮。
15)如果我想在我的主题中覆写这个函数,可以使用我主题目录下面的文件来代替/misc,我可以这样:
  Drupal.theme.prototype.powered = function(color, height, width) {
    return '<img src="/sites/all/themes/powered_images/powered-'+ color +'-'+ height +'x'+ width +'.png" />";
  }
  这个利用了普通JavaScript的优点。前面的函数放在主题里面的一个JavaScript文件中,
  从而避免修改相关模块的JavaScript文件。
  JavaScript主题函数的返回类型可以多种多样。既可以是简单的字符串,
  也可以是复杂的数据类型,比如对象,数组,
  和jQuery元素。参考原始的函数,看它返回什么,在你的定制主题函数中就应该返回什么。
16)     这些复选框,是根据.info文件中的特性(features)生成的.声明方式为'features'+“[]”+“=”+特性本身,例如features[] = the_feature。如果一个也没有定义的话,将会使用下面的默认值
    features[] = logo
    features[] = name
    features[] = slogan
    features[] = mission
    features[] = node_user_picture
    features[] = comment_user_picture
    features[] = search
    features[] = favicon
    features[] = primary_links
    features[] = secondary_links
    为了禁用一些特性,只需要在.info文件中添加你需要的特性就可以了。
    定义需要的,就会将不需要的忽略掉。有些特性也会启用一些相关的表单字段。
    例如,'logo'将启用一个上传字段,用于上传图片。
    已不再支持hook_features()
17)主题作者可以使用高级表单API(auto-completion,可伸缩字段集)
  和JQuery javascript来创建复杂的动态的表单
18)
    在你的template.php文件的顶部附近添加下面的代码:
    <?php
    /*
    * Initialize theme settings
    */
    if (is_null(theme_get_setting('garland_happy'))) {  // <-- change this line
      global $theme_key;

      /*
       * The default values for the theme variables. Make sure $defaults exactly
       * matches the $defaults in the theme-settings.php file.
       */
      $defaults = array(             // <-- change this array
        'garland_happy' => 1,
        'garland_shoes' => 0,
      );

      // Get default theme settings.
      $settings = theme_get_settings($theme_key);
      // Don't save the toggle_node_info_ variables.
      if (module_exists('node')) {
        foreach (node_get_types() as $type => $name) {
          unset($settings['toggle_node_info_' . $type]);
        }
      }
      // Save default theme settings.
      variable_set(
        str_replace('/', '_', 'theme_'. $theme_key .'_settings'),
        array_merge($defaults, $settings)
      );
      // Force refresh of Drupal internals.
      theme_get_setting('', TRUE);
    }
    ?>

19)维护使用新的主题
    <?php
        $conf['maintenance_theme'] = 'themeName';
    ?>
20)先你需要确保你的HTML或者xHTML通过合法性验证,
  然后才能开始修改你的CSS来修正你的bugs。Firefox 的Web Developer toolbar
 (web开发者工具栏)内置了一个web验证器。Opera也内置了合法性验证,
  只需要按下Ctrl+Alt+V就可以了。
   两个扩展插件,开发者工具栏和查看格式化源文件
  一个更高级的工具是Watchfire WebXACT tool,可用于检查代码,分析HTML页面,定位错误。

21)使用PHP变量
  禁止对容器使用固定的宽度
  对于一些复杂的或者灵活的设计,比如fullheight,需要大量的工作来实现max-width 和min-width。
  当插入一个设计者想要的图形效果时,要保证在IE下面也能正常工作。
  IE和Firefox的兼容性问题
  从头编写一个主题

22)
  以用户1的身份登录.
  为了得到一些菜单项,启用下面的模块: aggregator, blog, node, page, search, story 和tracker.
  打开主题支持的特性(logo(标识), site name(站名), slogan(标语), search box(搜索框)).如果需要的话,可以添加一些一级和二级链接.我们建议使用"Link 1" "Link 2" "Link 3",你可以将它们链接到,比如"user/1".
  将站名设为Drupal,标语设为Community Plumbing
  创建一个story节点:
  查看该节点,确保所有标签都能被看到.截图.
  对截图进行切图,大小为420x254,对生成的图片调整大小, 调整为150x90(原始尺寸的35%).
  在这里只展示有用的页面元素(菜单,标签,标题,链接)。不要包括浏览器的东西(工具栏,状态栏,滚动条等)。
  为了更加清晰一些,可以对缩略图使用一个标准的'sharpen'过滤器。
  保存为PNG格式,选择paletted colorspace,这样可以减小文件大小。


 主题包含哪些文件
    1)主题名.info文件
    2)page.tpl.php(可能还有各种分支)
    3)node.tpl.php(可能还有各种分支)
    4)block.tpl.php(也许可能没有)
    4)box.tpl.php 评论的容器设置,其实一般不用改,一般用不到(也许可能没有)
    5)comment.tpl.php(也许可能没有)
    6)template.php文件(也许可能没有)
    7)phptemplate.engine一般用不到(也许可能没有)里面的函数可以重写的

themes->engines-> 模板引擎目录
去drupal网站上找smarty,因为drupal已为它封装
 不要在smarty网站上找smarty
sites/all/themes 的目录下
1)http://drupal.org/project/smarty
  放到 engine的目录中就可以了
2)主题的目录在 sites/all/themes 下面
themes 的 主题目录中应包含的文件
block.tpl.php 区块的tpl文件
box.tpl.php 评论容器的显示 一般不需要更改 ,但是是可以更改的
default.tpl.php 暂时无用
phptemplate.engine 函数库 里面包含模板函数 不必要拷到主题目录中 是可以重写的
3)模板机制的原理
  设置好各种变量
  传递给模板变量 page.tpl.php,node.tpl.php等
  显示
  phptemplate根据不同的内容,重新组织页面,页面的不同部分
    是由不同的主题文件来控制的
4)phpTemplate页面的组成
  page.tpl.php模板来控制整个页面的显示
  有一部分是区块来显示的,读的是 block.tpl.php
  另有一部分是node.tpl.php来控制
  以摘要形式显示的时候也是读node.tpl.php,它也是读title及body的部分(摘要) 其它就不读取了
  如果不读view 也可以手动的修改 node.tpl.php文件来进行摘要简单的列表的处理

 创建主题步骤
 一)创建主题文件夹
 二)准备设计 somepage.html
         somestyle.css
             images
 三)决定是否在现有的主题上开发,drupal的主题它一般不规范
    有一种叫zen的主题非常适合在它上面开发
    将theme/engines/phptemplate/下的
    除default.tpl.php和 phptemplate.engine外的所有文件,
    copy到mytheme
 四)Garland 默认的 较友好的 可通过UI调节颜色配置
    Chameleon(不建议,因为未使用phpTemplate主题引擎
      不是某种意义上的MVC,不能更好的表示层与逻辑层分离)
   Zen是drupal的一个主题框架
      自带两个主题 普通版 像Garland主题使用
      经典版(Zen Classic) 比较优秀 效率高
      自带一个创建工具包 StarterKit 其实是一堆模板文件
     简洁 良好的布局 可以随意修改主题 兼容各个浏览器 符合标准(对宽窄屏也友好)
 五)page.tpl.php 根据url来决定调用哪个模板文件
    http://localhost/?q=node/2/edit
    找(1)page-node-edit.tpl.php
      (2)page-node-2.tpl.php  
      (3)page-node-tpl.php(不是它)  page-node.tpl.php(是它)
      (4)page.tpl.php
      如果还找不到 就回到引擎中,根据默认的形式输出来
      http://localhost/   page-front.tpl.php(首页)
  六)page.tpl.php 代码片断
    预定义的变量
  七)node.tpl.php
    每个内容都是node
    只要和内容的显示有关 一定调用node.tpl.php
    在列表中显示,(view除外)使用node.tpl.php
        views中(full, teaser)是会调用node.tpl.php
     views中(table view, list view)不会调用node.tpl.php
    node会根据节点类型,可以调用不同的node.tpl.php
      比如  node-blog.tpl.php node-story.tpl.php
    //这里也是一种优先级
    
    
    

 主题包含哪些文件
    1)主题名.info文件
    2)page.tpl.php(可能还有各种分支)
    3)node.tpl.php(可能还有各种分支)
    4)block.tpl.php(也许可能没有)
    4)box.tpl.php 评论的容器设置,其实一般不用改,一般用不到(也许可能没有)
    5)comment.tpl.php(也许可能没有)
    6)template.php文件(也许可能没有)
    7)phptemplate.engine一般用不到(也许可能没有)里面的函数可以重写的

themes->engines-> 模板引擎目录
去drupal网站上找smarty,因为drupal已为它封装
 不要在smarty网站上找smarty
sites/all/themes 的目录下
1)http://drupal.org/project/smarty
  放到 engine的目录中就可以了
2)主题的目录在 sites/all/themes 下面
themes 的 主题目录中应包含的文件
block.tpl.php 区块的tpl文件
box.tpl.php 评论容器的显示 一般不需要更改 ,但是是可以更改的
default.tpl.php 暂时无用
phptemplate.engine 函数库 里面包含模板函数 不必要拷到主题目录中 是可以重写的
3)模板机制的原理
  设置好各种变量
  传递给模板变量 page.tpl.php,node.tpl.php等
  显示
  phptemplate根据不同的内容,重新组织页面,页面的不同部分
    是由不同的主题文件来控制的
4)phpTemplate页面的组成
  page.tpl.php模板来控制整个页面的显示
  有一部分是区块来显示的,读的是 block.tpl.php
  另有一部分是node.tpl.php来控制
  以摘要形式显示的时候也是读node.tpl.php,它也是读title及body的部分(摘要) 其它就不读取了
  如果不读view 也可以手动的修改 node.tpl.php文件来进行摘要简单的列表的处理

 创建主题步骤
 一)创建主题文件夹
 二)准备设计 somepage.html
         somestyle.css
             images
 三)决定是否在现有的主题上开发,drupal的主题它一般不规范
    有一种叫zen的主题非常适合在它上面开发
    将theme/engines/phptemplate/下的
    除default.tpl.php和 phptemplate.engine外的所有文件,
    copy到mytheme
 四)Garland 默认的 较友好的 可通过UI调节颜色配置
    Chameleon(不建议,因为未使用phpTemplate主题引擎
      不是某种意义上的MVC,不能更好的表示层与逻辑层分离)
   Zen是drupal的一个主题框架
      自带两个主题 普通版 像Garland主题使用
      经典版(Zen Classic) 比较优秀 效率高
      自带一个创建工具包 StarterKit 其实是一堆模板文件
     简洁 良好的布局 可以随意修改主题 兼容各个浏览器 符合标准(对宽窄屏也友好)
 五)page.tpl.php 根据url来决定调用哪个模板文件
    http://localhost/?q=node/2/edit
    找(1)page-node-edit.tpl.php
      (2)page-node-2.tpl.php  
      (3)page-node-tpl.php
      (4)page.tpl.php
      如果还找不到 就回到引擎中,根据默认的形式输出来
      http://localhost/   page-front.tpl.php(首页)
  六)page.tpl.php 代码片断
    预定义的变量
  七)node.tpl.php
    每个内容都是node
    只要和内容的显示有关 一定调用node.tpl.php
    在列表中显示,(view除外)使用node.tpl.php
        views中(full, teaser)是会调用node.tpl.php
     views中(table view, list view)不会调用node.tpl.php
    node会根据节点类型,可以调用不同的node.tpl.php
      比如  node-blog.tpl.php node-story.tpl.php
    
    api自己用勤用,不想老是想着自己写函数,要想着用人家的函数
1)node.tpl.php
    <?php  var_dump($node); ?>
    field_字段名[0]['view'];这些一般是cck来定义创建的
2)devel 模块 有了它 能更好的开发 主题(其实最方便的是主题)和模块  
    一)devel 可以查看每个页面调的变量
    二)Devel node access 看节点的访问权限
    三)Devel generate 生成测试用的用户 节点等
3)页面加载流程
    一)生成一堆变量,读入模板文件,呈现html给用户
4)dev   最基本的功能就是查看页面输出的变量
        dev load 在变量处理前读入的变量
    dev render输出前生成的变量 (初学者先用它吧)
      一)content变量 模板引擎处理过的要生成的内容的变量
      $content(是由数组串成的串) 也可以是 $node->content(它不行了,是一个数组)
5)drupal 有太多的主题theme函数,直接拿过来用 可 输出"用户名" 图像 表格等
    一)theme根据访问者的权限进行显示
    二)theme函数对html元素进行统一的 有规律的增加class类css
    三)theme函数网址 http://api.drupal.org/api/group/themeable/5
    四)重要的函数 theme() ;根据传来的变量寻找对应的函数
    theme('image',$path)...首先找theme_image函数,如果找到的话 就会
    调用theme_image($path)
    尽量使用 theme('image',$path) 尽量不使用 theme_image($path)
    再举个例子 <?php $user=user_load(array('uid'=>$node->uid)); ?>
          <?php print theme('username',$user); ?>
    五)常用的theme函数 (这些函数要实践一下)
        theme_block      模块开发时用到
        theme_box        显示div里面是传来的内容,只是自动生成class 不能手动添加class
        theme_image     通常在使用cck 创建图像后,传路径过来得到img
        theme_item_list  输出ul li 传进来的是数组,数组里的每个元素放在li里
        theme_links     用于显示超链接 好像与l函数差不多() 形如<ul><li><a href="#">AA</a><a href="#">BB</a></li></ul>的形式
        //比如首页 l('Return to index page','<front>')
        them_table     根据变量 输出带表头的表格
        theme_usename    输出带链接的用户名
    六)重写theme函数 theme函数调用机制(Hook机制)
       theme('username',$user)按下列顺序从所有文件中找
            theme-name_username()  //theme-name 是主题名
            比如主题名是mytheme 那么找 mytheme_username()
            theme-engine_username()//theme-engine 模板引擎名
            如果没有 找模板引擎 找 phptemplate_username()
            theme_username()
            如果没有 执行 theme_username() 输出结果
    七)重写在 自定义主题目录下的 template.php文件里
        例子//重写 _username     //$user不可以引用(&$user 至少在drupal 6 不可以)
            function phptemplate_username($user){
                return 'hello '.$user->name;
            }
   

    

 








































普通分类: