开发者

How can I prevent endless recursion with Drupal's node_load()?

I'm using the Ubercart product and product_kit modules. This is great at linking from the relevant product kit to the products which are included, but I also want to link from the individual product to any kits it may be part of.

I figured I could do a database search on the SKU/Model number (got that part done easily), and then use node_load($nid) to get the related kit.

I have this so far:

function amh_shop_nodeapi(&开发者_StackOverflow社区$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);
            }
        }
    }
}

But, because the product kits are also loading the products, I end up in a recursive loop.

I guess my question actually comes in two parts:

  1. The question that is the title of this post: how do I prevent this recursion?

  2. Slightly different question that probably answers the first one anyway: should I be doing this when the node is being loaded, or later in the process (for example, at view or alter)?


Hey there is a module called http://drupal.org/project/contemplate. They had a similar problem of recursion within that module, but they figured out a workaround for it by setting a recursion_limit.

I am not sure if it solves your problem, but it will definitely be worth going through their module and search the code for contemplate_max_recursion_depth. That might give you some pointers.

Hope it helps..


One of solutions, just don't call node_load for product_kit, so it will not call node_load for subproducts, query need datas manually via 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
}


What about this: It introduces a recursion variable check.

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);
                }
            }
        }
    }
}


you should consider cacheing data like this. If you're loading it all the time it could really drain resources. I would consider a custom module that can store a relationship between individual projects and associated kits.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜