【问题标题】:Drupal - logic of the template.php fileDrupal - template.php 文件的逻辑
【发布时间】:2010-11-19 15:12:10
【问题描述】:

我今天花了很多时间研究扩展我继承的一个 drupal 站点,确信我面临的问题归结为我定制的 SQL 查询。

我已经意识到 SQL 没问题(在 PHPMYadmin 中检查并在 drupal 网站中执行了各种操作)。所以我很高兴我能从我需要的数据库中获取所有结果,循环它们并以特定标记将它们输出到页面上。

我遇到的问题是循环显示的位置。我似乎无法弄清楚主题系统或理解 template.php 中发生的事情。

让我解释一下:

我需要更改的代码位于 template.php 文件中。我的理解是这个文件允许你覆盖某些功能和主题元素。

在 template.php 文件中,这是我需要更改的代码:

//old function from original development
function abc($node,$submitted,$node_url) {
//execute code

}

所以我在函数 abc() 中添加了我的代码,因为我希望它在输出旧代码的地方输出。

这是我的 sql 和循环的伪代码:

 function abc($node,$submitted,$node_url) {
$sql = 'my sql query'
$results =db_query($sql);
while ($data = db_fetch_array($results)) {
  //output my results here
}

}

让我相信 sql 错误的是我应该得到 23 个结果,但我得到了更多的重复条目。在浪费了很多时间寻找错误的地方并仔细检查了 sql 之后,我意识到这是多次执行 sql 和循环的函数,而不是 sql 返回重复条目。我是这样做的:

function abc($node,$submitted,$node_url) {
 $sql = 'my sql query'
 $results =db_query($sql);
 $x = 1;
 while ($data = db_fetch_array($results)) {
   if ($x == 1) {
     echo '<p style="background-color:#ccc;">'. $x . '. '.$data['title'] . '</p>';
   }else{
 echo '<p>'. $x . '. '.$data['title'] . '</p>';
   }
 $x = $x + 1;
}

}

在执行代码时,我希望增加的数字会继续处理尽可能多的重复条目,并将第一个条目的背景设置为灰色,但事实并非如此。在结果 23 处,它将自身重置为 1 并将该条目的背景着色为灰色,向我表明它是多次执行 sql 和循环的函数。

我不完全确定这个 abc() 函数是什么,除了当我将代码放入其中时,输出会显示在特定页面上我需要它的位置,而其他任何地方都没有(没有重复的条目) .

当我从这个函数中取出我的代码时(仍然在 template.php 中),我的代码输出在所有页面的头部,这是不可取的。

是否有人对可能发生的事情有任何想法,我可以在哪里查找此函数是什么或知道我确定代码显示的方法?

我一直在阅读一些关于主题等的内容,但是使用其他人的代码正在变成一个有点混乱的噩梦。

提前干杯!

【问题讨论】:

  • “abc”只是您在此处用于实际函数名称的别名吗?通常在 template.php 中,函数名称很重要,因为它表明了被你的 template.php 文件所在的主题所覆盖的模块函数。您能否提供完整函数名称及其覆盖的模块的详细信息?
  • 叫我愤世嫉俗,但它可能被称为 abc 和 poss 一样无害。
  • 您不应将其他信息作为答案发布,而应将其嵌入您的原始问题中,以免答案被您的信息淹没。此外,这将使您更容易为您提供帮助,因为无需通读答案即可获取所有信息,这些信息可能因赞成/反对票而有序或不有序。您应该将信息复制到您的问题中,将其标记为附加信息并删除您的“答案”。
  • 听起来你在 Drupal 学习曲线中处于困难的一边(我们都经历过),你可能会发现你在 irc 上的#drupal 上得到了一些很好的帮助。

标签: php sql drupal function templates


【解决方案1】:

你在这里走错了路,可能是因为你对 Drupal 的工作方式缺乏经验,所以让我给你一些信息和建议。

你可以说 Drupal 必须在其中执行代码、模块/核心和主题的层。一般来说,你可以说第一层,模块/核心是数据的生成/获取,而第二层是数据的呈现。您正在做的是在表示层中获取数据,这确实应该避免。这也是为什么你很难找到原因的原因,因为混淆了获取数据的内容和呈现数据的内容。你所做的也非常浪费资源,我稍后会谈到,但首先发生了什么?

你已经接管了一个可能有自定义主题的网站,我可以看出它是以一种骇人听闻的方式制作的。也许做它的人不知道正确的方法,但做了一些“有效”的东西。现在什么试图改变它,你打破了它。当 Drupal 呈现一个节点(一个节点是一段内容)时,它会获取大量数据,模块可以挂钩并添加、更改或删除该数据,最后数据到达模板(所有模板文件都是表示为 tpl.php - 除非使用不同的模板引擎)。它的工作方式是,它使用“页面”模板来创建站点、导航、不同区域等的基础知识。现在,当显示节点列表时,每个节点将通过将其数据输出到节点模板来显示在页面模板中。通常有很多 div 等。结合一些php打印数据。在您的示例中,还调用了一个函数。在某些情况下,如果您对多语言网站使用 fx 翻译功能或为您检查某些内容的简单功能,这可能会很好。但是,在您的情况下,您使用该功能来获取数据。通过查看您创建的 SQL,您似乎实际上是在尝试获取您想要显示的博客节点列表。如果只显示一个节点,这可能会起作用,但是当显示节点列表时,您运行 SQL 并打印列出的每个节点的结果,这就是让您陷入困境的原因。这也是非常无效的,因为每次使用节点模板时都会运行查询。如您所见,在主题层中控制获取数据非常混乱且难以控制。但是你怎么做呢?

有一些不同的方法可以做一些事情,甚至为此制作了模块。现在您似乎想要显示基于 2 个 CCK 日期字段的博客节点列表。
简单的非编码方式:
只需使用视图模块创建一个视图。您可以在 cck 字段中选择基于博客和过滤器类型的节点以及当前数据和日期。您可以选择不同的显示器。显示完整节点或仅显示部分节点、列表、表等。最后,为视图选择一个 URL,就完成了。 更难的编码方式:
创建自定义模块。首先,您需要实现 hook_menu() 来创建一个菜单项,这就是您设置 URL 的方式。这样做您分配一个必须为该 URL 创建的函数。在其中您放置了上述大部分代码,使用 SQL 获取数据,但是您还需要通过各种主题函数运行该数据,这些函数将生成标记并最后返回数据。如果您了解 Drupal 的工作原理,这实际上很容易做到。如果没有,则很难正确执行此操作,因为您需要调用很多您不知道的函数,并实现钩子等。

这最终比我计划的要长一点,但我希望它对您的新 Drupal 站点有所帮助。

编辑:

实际上,您发布的 SQL 看起来像是从看起来正在运行的视图生成的 SQL。唯一的缺陷是您要求两个日期字段都大于或等于现在。 CCK 字段可以有一个默认值,但我相信您在编辑节点时始终可以将其编辑为您喜欢的任何内容,除非已编辑节点表单以隐藏字段。此外,没有任何理由使用 CCK 日期字段作为发布日期。该信息与上次编辑日期一起在每个节点上都可用。

您可以在Lullabot 找到很多好东西。他们做了很多关于如何使用 CCK 和视图的东西。有些是他们卖的,有些是免费的。在您的示例中,困难的部分是获得您想要的节点。为此,您需要添加过滤器。当您想按任何日期排序时,您需要添加位于日期组中的日期过滤器。在其中,您可以检查要使用的字段。但是,在您的情况下,您希望为每个日期字段添加两次日期过滤器,因为您有不同的字段值。这可能是你的缺陷所在,也是给你带来问题的地方。

【讨论】:

  • 谢谢 googletorp - 我可以再问一个问题吗?您说“简单的非编码方式 - 使用视图和 cck 字段”我相信 cck 字段上的日期是发布日期。我需要在用户指定的日期而不是发布日期之前订购 - 不幸的是,这是我的全部问题,也是我需要首先修改代码的原因。对于 cck/views,你有什么好的 tuts 建议吗?我怎样才能创建视图并让自己访问数据库中的更多字段,就像我在无法弄清楚之前尝试这样做时一样。再次感谢!
【解决方案2】:

首先,您不应该使用echo,因为它会在代码运行时打印(例如在页面顶部加载时),而不是打印到模板在适当位置显示的变量中页面中的点。 (这并不是说echo 不会永远工作,但使用它并不是最佳实践。)

之前的函数是用什么输出数据的? (可能会有一个名为 abc.tpl.php 的页面(如果您的函数名为 abc),它将帮助您找到合适的变量名称。

如果您添加您正在使用的 SQL 字符串,我也可以诊断出该问题。

编辑:

根据您之前的评论,假设您正在尝试格式化博客节点(我基于您提到缺少 node-blog.tpl.php):

Drupal 的假设是,在渲染页面时,会像这样(简化):

  1. 加载内核。从数据库中获取内容。获取分类和其他好东西,并将它们提供给模块和主题

  2. 然后,查看所有模块以查看 如果他们有钩子,基于 他们的函数名,会修改 页。如果有,请运行这些函数。 如果他们不这样做,请不要理会该页面。

  3. 然后,在所有主题中查看 如果 template.php 有钩子, 根据它们的函数名称,将 修改页面。如果他们这样做,请运行 职能。如果他们不这样做,请离开 单独的页面。

  4. 最后,查看 tpl.php 文件并使用这些文件显示页面。如果没有正确文件名的 tpl.php 文件,则使用 node.tpl.php 加载它

http://drupal.org/node/173880的所有内容进行了很好的总结

如果您在 template.php 中没有看起来会修改页面的函数,并且您没有与您要查找的节点匹配的 tpl.php 文件,这意味着您的所有页面正在使用默认模板。

(这可能是你的前任设置他所做的奇怪构造的原因。使用这样的函数是一种有点 hacky 的方式来完成 Drupal 可以通过主题函数自动执行的操作)

所以:

继续制作 tpl.php 文件。如果您的内容类型是博客节点或其他内容,则将其称为 node-blog.tpl.php。您现在可以只复制现有的 tpl.php 文件。然后,在 template.php 中创建一个预处理函数来配合它。

(您需要为 Drupal 重建主题注册表以识别更改 - 您已经安装了 Devel 模块,因此从那里开始应该很容易。访问您网站上的 /admin/build/modules 也可以.)

然后,访问 http://drupal.org/node/223430http://drupal.org/node/337022 获取一些快速解释和代码 sn-ps,让您将数据作为变量传递,然后模板可以在您的页面上呈现

最后一次编辑:

这个函数是否会建立一个博客文章列表,并以摘要形式呈现信息(例如,待处理文章列表)?

我问是因为如果是这样,Views 模块可能会为您完成所有的工作。除非函数 abc() 中的数据处理真的非常非常奇特,否则这似乎正是 Views 的目标。

【讨论】:

    【解决方案3】:

    devel module 是了解主题挂钩和模板文件发生了什么的一个很好的开始。启用它并转到该站点并启用“主题开发人员”模块将在页面的左下角为您提供一些小工具,您可以在其中选中一个框,然后单击页面上的任何元素 - 它会向您展示它正在执行什么、为什么以及它可能正在执行什么。

    可能是一个开始。

    【讨论】:

      【解决方案4】:

      为了澄清我的评论,它应该看起来像这样:

      function getData(){
         $sql='my sql query';
         results =db_query($sql);
         $return_string = '' ;
         while ($data = db_fetch_array($results)) {
            //Loop through data and save to $db_data
            $return_string .= $db_data;
         }
         return $return_string;
      
      }
      

      听起来你在 page.tpl.php 中调用这个函数是正确的;请注意,您可以通过有条件地为 $node->nid 的特定值调用它来使其仅显示在特定页面上:

      <?php if ($node->nid == xxx || $node->nid == yyy) print getData() ;?>
      

      如果您使用 CCK 并仅针对特定内容类型显示函数的结果,Contemplate 是一个很好的模块,尤其是。对于刚开始使用 Drupalers 的人来说,这使得其中一些变得更容易。

      【讨论】:

        【解决方案5】:

        好的,看看如何使用主题开发者:

        父母:theme_taxonomy_term_page

        在这里查看 modules/node/node.tpl.php 并找到对 abc 函数的引用

         <?php print abc($node,$submitted,$node_url); ?>
        

        找不到node-blog.tpl.php,也找不到对函数template_preprocess + template_preprocess_node + content_preprocess_node + nodereference_preprocess_node + views_preprocess_node的任何引用

        难倒。

        【讨论】:

        • 可能是我做错了。我有我需要的代码,我可以把它放在一个函数中到 template.php 我怎样才能在我需要的页面中返回那个函数?
        • 这似乎是一个奇怪的结构。在下面查看更详细的回复——我无法在评论中进行格式化
        【解决方案6】:

        回答您提出的几个问题:

        之前的函数是这样做的:

        function abc($node,$submitted,$node_url) {
        echo $node->taxonomy['color'];
        $a = explode(",",$submitted);
        $b = explode("-",$a[1]);
        
        // THIS IS THE DESCRIPTION
        if(strlen($node->content['body']['#value'])>180)
        {
        $c = str_split($node->content['body']['#value'],180);
        $d = $c[0]."...";
        
        }
        else{
        $d = $node->content['body']['#value'];
        }
        
        
        $multiple = $node->field_mul_event[0]['view'];
        $eventcode = $node->field_event_code[0]['value'];
        
        $strdata="";
        $strdata.="specific markup to output here";
        return $strdata;
        

        }

        这个函数只是提取了一个开始和结束日期以及一个描述

        我的代码中的sql字符串是:

        select DISTINCT node.nid AS nid, node.title AS node_title, 
                  content_type_blog.field_date_from_value AS node_data_field_date_from_field_date_from_value, 
                  DATE_FORMAT(content_type_blog.field_date_from_value, '%%d/%%m/%%Y') AS dateFrom, 
                  content_type_blog.field_date_from_value2 AS node_data_field_date_from_field_date_from_value2, 
                  content_type_blog.nid AS node_data_field_date_from_nid, 
                  field_mul_event_value AS multiEvent,
                  field_event_code_value AS eventCode,
                  node.type AS node_type, 
                  content_type_blog.field_event_excerpt_value AS node_data_field_date_from_field_event_excerpt_value, 
                  image_attach.iid AS image_attach_iid, 
                  node_images.filepath AS imagePath,
                  color AS catColour
                  FROM node 
                  node LEFT JOIN content_type_blog content_type_blog ON node.vid = content_type_blog.vid
                       LEFT JOIN image_attach image_attach ON node.nid = image_attach.nid
                       LEFT JOIN node_images node_images ON node.nid = node_images.nid
                       LEFT JOIN term_node term_node ON node.nid = term_node.nid
                       LEFT JOIN term_data term_data ON term_node.tid = term_data.tid
                WHERE node.type LIKE 'blog' AND content_type_blog.field_date_from_value >= DATE(NOW()) AND content_type_blog.field_date_from_value2 >= DATE(NOW()) 
                ORDER BY content_type_blog.field_date_from_value ASC
        

        我相信你会知道,这个 sql 会抓取所有相同的数据(以及一些额外的信息),除了比今天日期更早的数据,然后按日期顺序对其进行排序。

        我看了一下主题文件夹,里面有两个tpl.php文件,里面的代码是一样的:

        <?php print $fields['title']->content; ?>
        <?php print $fields['introduction']->content; ?>
        

        我在站点/所有/模块中看不到任何自定义模块。这是那里的列表(但它们对我来说似乎都是固有的模块):

        1. cck
        2. 日期
        3. 开发
        4. extlink
        5. fckeditor
        6. 图片
        7. imce
        8. menu_breadcrumb
        9. nice_menus
        10. node_images
        11. 自动路径
        12. 部分
        13. swftools
        14. 令牌
        15. 观看次数
        16. 所见即所得

        请原谅我的无知-但我正在学习drupal。如果您知道我的意思,通常更多的是 wordpress gal。不习惯节点/分类/drupal系统等,这是我缺乏知识的基本借口。

        我需要找到该函数并确定它的作用 - 啊!!!

        谢谢大家!

        【讨论】:

        • 这可能是手头问题的附带问题,但为什么 SQL 在 term_data 和 term_node 上有 LEFT JOIN? Drupal 核心已经加载了该信息,因此除非函数 abc() 使用该信息来处理它的输出,否则您可能可以摆脱它并使函数更快。
        【解决方案7】:

        虽然 template.php 用于覆盖各种主题函数,但它也可用于简单地存储在模板上调用的函数(您也可以强制 template.php 在自定义模块中可用,具体取决于站点的 hacky 程度由原始开发人员完成)。所以仅仅因为一个函数在 template.php 中并不会自动假定它是一个主题覆盖(如果你可以为函数提供实际名称,这将有助于确定它是否是)。

        而将代码从函数中取出但将其保留在 template.php 中的原因会导致每个页面上的输出是因为 template.php 包含在每个页面中。从理论上讲,您可以在 template.php 中放置不仅仅是函数。在一个大型网站上,我为其中一位开发人员工作,将函数分解为几个较小的文件,因此 template.php 只有 2 或 3 个函数和 3 或 4 个 include()。

        知道函数的实际名称确实有助于确定这是自定义函数还是主题覆盖。

        【讨论】:

        • @Lyndsey:例如,如果函数的真实名称是 foo_event_upcoming_item(),我们就会知道它覆盖了事件模块中的“即将发生的事件”显示。函数名在 Drupal 中很重要。
        • 感谢大家到目前为止的所有输入。有什么想法可以找出函数的名称吗? - 你们有什么技巧可以在看不见的代码上找到函数调用 - 还是只是拖网的情况?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-15
        相关资源
        最近更新 更多