【问题标题】:How can I prevent endless recursion with Drupal's node_load()?如何使用 Drupal 的 node_load() 防止无休止的递归?
【发布时间】:2011-02-24 00:47:37
【问题描述】:

我正在使用 Ubercart 产品和 product_kit 模块。这非常适合从相关产品套件链接到包含的产品,但我也想从单个产品链接到它可能属于的任何套件。

我想我可以对 SKU/型号进行数据库搜索(轻松完成该部分),然后使用 node_load($nid) 获取相关套件。

到目前为止我有这个:

function amh_shop_nodeapi(&$node, $op, $a3 = null, $a4 = null)
{
    if ($node->type == 'product') {
        if ($op == 'load') {
            error_log("product::load");

            $bundles = array();
            $results = db_query('SELECT DISTINCT n.nid FROM {node} n RIGHT JOIN {uc_products} up ON up.nid = n.nid WHERE up.model LIKE "%s /%" OR up.model LIKE "%/ %s /%" OR up.model LIKE "%/ %s"', $node->model, $node->model, $node->model);

            while ($bundle = db_fetch_object($results)) {
                error_log("bundle::load");
                $bundles[] = node_load($bundle->nid);
            }
        }
    }
}

但是,由于产品套件也在加载产品,所以我最终陷入了递归循环。

我想我的问题实际上分为两部分:

  1. 本文标题的问题:如何防止这种递归?

  2. 稍微不同的问题,无论如何可能会回答第一个问题:我应该在加载节点时执行此操作,还是在此过程的后期(例如,查看或更改)?

    李>

【问题讨论】:

    标签: drupal drupal-6 drupal-hooks


    【解决方案1】:

    嘿,有一个名为 http://drupal.org/project/contemplate 的模块。他们在该模块中遇到了类似的递归问题,但他们通过设置 recursion_limit 找到了解决方法。

    我不确定它是否能解决您的问题,但绝对值得通过他们的模块并在代码中搜索 contemplate_max_recursion_depth。这可能会给你一些指导。

    希望对你有帮助..

    【讨论】:

      【解决方案2】:

      解决方案之一,product_kit不调用node_load,子产品就不会调用node_load,通过db_query手动查询需要的数据:

      function amh_shop_nodeapi(&$node, $op, $a3 = null, $a4 = null)
      {
          if ($node->type == 'product') {
              if ($op == 'load') {
                  $bundles = array();
                  $results = db_query('SELECT n.nid, n.title FROM {node} n INNER JOIN {uc_product_kits} k ON n.nid=k.nid WHERE n.product_id=%d ORDER BY n.title', $node->nid);
                  while ($bundle = db_fetch_object($results)) {
                      $bundles[] = l($bundle->title, 'node/'.$bundle->nid);
                  }
              }
          }
          $node->amh_bundles = $bundles; // Here's array of links to product_kits
      }
      

      【讨论】:

      • 问题是 - 我想要的不仅仅是产品套件的节点 ID 和标题,而且 node_load 似乎是最好的方法来避免我必须重写查询如果和当我想要更多详细信息时......任何事件 - 我将此代码移至视图操作
      • 好主意,但不提倡重用。我只会设置节点 ID 并将它们变成主题层中的链接。
      • Rimian 我同意,应该有节点 ID,我只是举个例子。 2HorusKol,根据我优化drupal的经验,有时调用node_load并不适合每次调用(在这个事件中触发了太多模块),最好只使用db_query,如果它发生了,缓存会有所帮助。
      【解决方案3】:

      这个怎么样:它引入了递归变量检查。

      function amh_shop_nodeapi(&$node, $op, $a3 = null, $a4 = null)
      {
        static $recursion_nid = NULL;
          if ($node->type == 'product') {
              if ($op == 'load') {
                  error_log("product::load");
      
                  $bundles = array();
                  $results = db_query('SELECT DISTINCT n.nid FROM {node} n RIGHT JOIN {uc_products} up ON up.nid = n.nid WHERE up.model LIKE "%s /%" OR up.model LIKE "%/ %s /%" OR up.model LIKE "%/ %s"', $node->model, $node->model, $node->model);
      
                  while ($bundle = db_fetch_object($results)) {
                      error_log("bundle::load");
                      if (isset($recursion_nid) && $recursion_nid == $nid) {
                         // recursion detected
                      }
                      else {
                        $recursion_nid = $node->nid;
                        $bundles[] = node_load($bundle->nid);
                        unset($recursion_nid);
                      }
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        您应该考虑像这样缓存数据。如果你一直在加载它,它真的会消耗资源。我会考虑一个自定义模块,它可以存储单个项目和相关套件之间的关系。

        【讨论】:

        • 并没有真正回答我的任何一个问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多