Hello,

I'm testing Drupal since a few days, and I still haven't found how to manage my categories and their display for my project.

Testing taxonomy, good tool, but as far as I've understood it, there's no way to aggregate some informations, like short text or an image.

Using custom nodes with the View module seems to be the more flexible way to build those categories with related data, but now I'm stuck with conditional display, which doesn't works.
Let say that I have a "Manufacturer" custom node, so I have made a page and a block view to list those. If I want to show all products of one particular manufacturer, I can click on it, and there's another node with a path conditional block view. This view is set to show the product, but it shows me all products, not only those which contain the related manufacturer.

How can I deal with this ? Do I have to downgrade Drupal to get some modules dedicated to this ?

Best regards and thanks for reading.

Comments

alan d.’s picture

Couple things to check.

Is Manufacturer a content type or tax, Is products a custom content type to? Have you set up a node reference field between the fields. Add this to product if you haven't

What are you filtering on? node status == published and node type == Product and Node Reference: man. = M. in question

Have you defined any arguments? Make sure this is not set to display all for the default


Alan Davison
www.caignwebs.com.au

Alan Davison
citronized’s picture

Hi,

So, for now, as I'm testing my website project structure, I've defined "Manufacturer" or "Product" as custom types of nodes, one type for each. Taxo looks great, but I haven't found any way to agregate to terms some "more" informations, so I've skipped this option.

There's a node reference between Manufacturer and Product (Product -> Manufacturer), and in the View module settings, I'm filtering on :
- Node: Published True
- Node: Type = Product
I haven't filtered on "Node reference = Manufacturer", because this would imply that I'd have to create a View for each Manufacturer. As users can add new manufacturers, I'd like them not to have to deal with some View module settings x_x

There are no arguments defined, for the same reasons that I've already mentioned, it would imply one arg./term for each Manufacturer's product list.

I don't understand why I do have to set manually a manufacturer if there's a link between Man. and Product? Isn't there a way to limit/filter using this relationship? I have still some others categories with similar relationships between other node types, so it would help me a lot to figure this out!

Thanks for helping !

Best regards.

alan d.’s picture

For the blocks:

When your viewing the product page, the page url is actually index.php?q=node/nid

This allows you to hook the current page view. Using the custom argument handling code, you can manually parse the relationship and set $arg[0] = manufacturer_nid;

Then using an argument filter on the relationship based on the arg[0], you can create a real view of the manufacturers products.

This is one example that shows related pages based on the current pages author:

<?php
$nids = array();
if(arg(0) == 'node' && is_numeric(arg(1) ) ){
  $nid = (int)arg(1);
  $node = node_load(array('nid'=>$nid));
  if ($node && $node->type == 'page') {
    $query = db_query('SELECT nid from {node} WHERE uid = %d AND nid <> %d LIMIT 0,10', $node->uid, $nid);
    while($row = db_fetch_object($query)) {
      $nids[] = $row->nid;
    }
  }
}
return array(implode('+',$nids));
?>

Since I do not know your exact schema, I'm hoping you can modify this to your problem.

A quick break down follows:

1) on on node pages
2) grab the id and load the node
3) if node is of type page
4) get all of the related pages by user and collect these up into an array
5) pass these back to the server a multiple value argument, 4+45+56, etc

In your case, it is a bit easier once you have the node relationship field data, it will be something like $node->field_relationship[0].

Here you need to set arg[0] to manufacturer, and arg[1] to the node nid

Then the argument filters are on == manufacturer, and <> node id

For page views, create a custom menu item pointing to the view url along with the manufacturing id, eg http://example.com/man-view/23 for example, and then filter on arg[0] (no argument code needed here)

This will be a second view.

Hope this is not too much, have a go and I can help if you get stuck.


Alan Davison
www.caignwebs.com.au

Alan Davison
citronized’s picture

Hi again Alan,

Thanks for your help with this example code, I'm not sure I'm using it the way I should. I've read a few times your answer, and some things are still dark for me : I have created a normal "page" to list the product and insert the customized php code you gave me :

<?php
$nids = array();
if(arg(0) == 'node' && is_numeric(arg(1) ) ){
  $nid = (int)arg(1);
  $node -> field_related_manufacturer[0];
  if ($node && $node->type == 'manufacturer') {
    $query = db_query('SELECT nid from {node} WHERE uid = %d AND nid <> %d LIMIT 0,10', $node->uid, $nid);
    while($row = db_fetch_object($query)) {
      $nids[] = $row->nid;
    }
  }
}
return array(implode('+',$nids));
?>

My php knowledge is close to zero, so you may scream looking at this code. x_x

What I don't get is that I think your example code is using the url args to set up the array, but I haven't clearly understood how, as the current page the php is in, isn't a manufacturer page. So I've tested it in a manufacturer page, it gave me the same result : no list, but the word "array" standing by its own…

I'll try to explain my structure, maybe that's the problem :
- I have created a manufacturer type of node, in which I've customized the title label in order to set the manufacturer name,
- I have created a product type of node, in which I've added a new field, as "node reference", the "related_manufacturer". Looking at phpMyAdmin, I can tell that it's the manufacturer id that is stored.
- I have a menu item pointing on the manufacturer, in which I'd like to see the related products listed.

Another question about the code and its returned data : if I properly understand your code, this code shows an array, should I use some View module functions to display the related product ?

So, right now, I'm a bit lost…
I'll be glad if you could help me one more time !

alan d.’s picture

This code segment was to pass back an array of id's to the view

Before trying to write some embedded code, can you work out the database SQL. This is dependent a number of factors depending how you set up the CCK

This is getting hacky though, and it would be best trying a view and the insert_view module first. I didn't realise that you were going to embed the code into the page.

Start with a simple view that shows all products and move on from there. For example, once the product list is showing, you can pass in the man. id via the insert_view tag, and use the argument code to filter on that.

The code segment was more to hook into a page from a block.


Alan Davison
www.caignwebs.com.au

Alan Davison
citronized’s picture

Ok, I think I though this code segment has to be embed in a page because I don't get how I can pass it as an argument in my block display View settings.

For the simple view starting, I'm OK :
- I set my filters and stuff,
- I set an URL for each manufacturer (manufacturer/manufacturer-name),
- I set my View block to be displayed on page that matches the page arg : "manufacturer/*"

So my View is displayed on every manufacturer page, with products from all manufacturer. Unfortunately, I can't use Insert_View because this module isn't available for 6.x :(

I'd a look at CCK tables and fields, and I think there's a kind of correlation table that stores the 'nid' and the 'manufacturer_nid' in records. Without thinking about SQL or Php, I guess my plan is to find, for the current manufacturer page (lets say 'nid' is 15), the corresponding manufacturer_nid in this CCK table, where the 'nid' matches a 'node.type' = 'product'. Is that right ?

alan d.’s picture

OK, using blocks, similar to the first post:

There should be a table that stores the CCK field data for the products called something like content_type_xxx or something similar. Get me a structure of that and I'll try a get the query sorted.


Alan Davison
www.caignwebs.com.au

Alan Davison
citronized’s picture

Thanks again for your help.

Here's the structure of the 'content_type_product' table :
Field --- Type
vid --- int(10)
nid --- int(10)
field_related_manufacturer_nid --- int(10)
field_product_num_value --- int(11)

Do you need any extra info ?

alan d.’s picture

Firstly, set up the view to accept a single argument, the manufacturer id

And in the argument code try this:

Load the node, as it will not be in scope

Pass back the man. id

And thats about it for this one.

<?php
// only show on node pages
$args = array();
if(arg(0) == 'node' && is_numeric(arg(1) ) ){
  // grab the node id and load it
  $nid = (int)arg(1);
  $node = node_load(array('nid'=>$nid));
  // was it a real node, and of type 'manufacturer
  if ($node && $node->type == 'manufacturer') {
    // found, set the first argument
    $args[0] = $nid;
  }
}
// return args
return $args;
?>

Make sure that there is no display when the argument is not found.

Theres more info here too if you need it: http://drupal.org/node/70145

To get related products from a product page, you need a more complex query


Alan Davison
www.caignwebs.com.au

Alan Davison
citronized’s picture

I don't want to bother you Alan, looks I don't get it right.

When you talk about "setting up the view to accept a single argument, the manufacturer id", am I right setting this :
Block: Configure Argument "Content: Node reference: Related manufacturer (field_related_manufacturer)"?

Then, Action to take if argument is not present is set to "Hide view / Page not found (404).

I've been pasting the code sequence into the PHP Validator, deleting the and , as asked above the php code area.

Wildcard is set to "all"

I've been trying many combinations :
- changing node URL,
- adding a related_manufacturer_nid field in the product content type
- adding a relationship based on the Related manufacturer (using it or not in the argument)

But the result of the preview is always the same : No query was run
x_x

All documentation I can read is about View 1.x and I think my version is 2.x. Is that a good reason for this arg not to work ?

citronized’s picture

Maybe this explains why the code doesn't work with my view :

Block displays have no source of arguments at all; they cannot pull arguments from the URL, and often require use of the PHP code default in order to get arguments.

I'm gonna test the code with a page display...

citronized’s picture

Adding a page display for my view make me focus on the query a bit more. I'm new to Sql, so I've done what Alan told me : test the query with phpMyAdmin (and I've found that MySql can't do sub-queries o_O, but that's not the point ) and see what I get. Then, after changing the page url settings, I've seen that the query was wrong. For some Url and args reasons, the WHERE predicates where wrong as :

WHERE (node.status <> 0) AND (node.type in ('product')) AND (node_data_field_related_manufacturer.field_related_manufacturer_nid = '<em>node</em>')

The preview query was something like "node/20". So I did change the Url settings of page display to "%" and it seems to work !

My only issue is to have a warning on each page I use the view in :

warning: preg_match() expects parameter 2 to be string, array given in .../includes/bootstrap.inc on line 718.

Any ideas about how to solve this warning ? I've found some project issues about it :
#225211: warning: preg_match() expects parameter 2 to be string - SRSLY, WON'T FIX, EVER.
and
#224201: warning: preg_match() expects parameter 2 to be string, array given in .../bootstrap.inc on line 718
But there's no clue in them to solve this warning with the modules I use...