zyON

Handling Categories on a Product Catalogue

Recommended Posts

Hi,

First of all, I'm starting digging into Processwire after a long search about what CMS to use to tackle this project I need to develop. I'm really loving it. 

My question is related to this product catalogue I'm trying to develop and just need some info on how to handle it properly.

I have a large catalogue of products that a part of those products are related something like this:

Shoes>Brand1>Men>Collection1>Product1

Shoes>Brand2>Men>Collection1>Product1

Shoes>Brand1>Women>Collection1>Product2

(...)

You get the picture.

Now, what's the best strategy to handle this when I want to be able to also get results like this:

Shoes>Men   (Any Brand)

Shoes>Brand2 (Men or Women) 

Thanks in advance

Share this post


Link to post
Share on other sites

Welcome! Im sure youll get millions of answers within shortly. (Love it)

Share this post


Link to post
Share on other sites

Shoes>Brand2 (Men or Women)

$pages->get("/shoes/brand2")->find("template=product");

I was trying to answer to Shoes>Men   (Any Brand) in one line, but a "parents" selector is missing :) 

Share this post


Link to post
Share on other sites

zyON,

Check into the Page Fieldtype

Maybe something like this for organization:

Shoes

-- Men

---- Product A

---- Product B

---- Product C

-- Women

---- Product A

---- Product B

---- Product C

Brands (these are just the references, no products listed as children)

-- Brand 1

-- Brand 2

-- Brand 3

Collections (these are just the references, no products listed as children)

-- Collection A

-- Collection B

-- Collection C

Create page fields for Brand and Collection, and add them to your "Product" template.

Now you can associate brand and collection with each product.

So to get the output you need:

Shoes > Men   (Any Brand)

$pages->get("/shoes/men/")

Shoes > Brand2

$pages->find("has_parent=/shoes/, brand.title=Brand 2")

Shoes > Brand2 > CollectionB

$pages->find("has_parent=/shoes/, brand.title=Brand 2, collection.title=Collection B")

You could also pass $input values to the selector so this could be generated via use selections.

  • Like 6

Share this post


Link to post
Share on other sites

Reno, on your selectors, parent has to be "parent=/shoes/men/|/shoes/women/", or use the IDs, of course "parent=123|124"

  • Like 1

Share this post


Link to post
Share on other sites

@renobird, @diogo: ...or just use "has_parent=/shoes/". :)

  • Like 2

Share this post


Link to post
Share on other sites

@nik, @diogo,

Nice catch guys. "has_parent" is what I intended — I'll update the post.

Share this post


Link to post
Share on other sites
@renobird, @diogo: ...or just use "has_parent=/shoes/". 

Great! This is the selector I was looking for since my first answer!

So, answering the original question, apart from thinking that Reno's structure is more efficient than the original because there aren't pages (men, women, etc.):

Shoes>Brand2 (Men or Women)
$pages->get("/shoes/brand2")->find("template=product");
Shoes>Men   (Any Brand)
// I was convinced that this would work, but it doesn't 
$men = (string) $pages->find("name=men");
echo $pages->find("has_parent={$men}, template=product");
 

Surprise, surprise, it doesn't work... apparently, has_parent doesn't accept a 123|124|125 kind of string, but only one id. I get this error:

Notice: Array to string conversion in /not/of/your/business/pw/wire/core/PageFinder.php on line 808
 
Warning: preg_match() expects parameter 2 to be string, array given in /not/of/your/business/pw/wire/core/Sanitizer.php on line 296

Share this post


Link to post
Share on other sites

Shoes>Men   (Any Brand)

// I was convinced that this would work, but it doesn't 
$men = (string) $pages->find("name=men");
echo $pages->find("has_parent={$men}, template=product");
 

Surprise, surprise, it doesn't work... apparently, has_parent doesn't accept a 123|124|125 kind of string, but only one id. I get this error:

From the Docs :)

You can specify a Page object, Page ID, or path, like shown above. Note however that at present, you can only specify one page at a time here (meaning no has_parent=1|2|3).

You can use several though and they would work :) - has_parent!=2,  has_parent!=7. But that may not be practical where there's too many

Share this post


Link to post
Share on other sites

ah :)

yep, but using several here wouldn't work without iterating...

Share this post


Link to post
Share on other sites

Btw, Diogo,

I don't get why you are not using ->get here instead of find since names are unique and you will not be able to find more than one page with name=men?

$men = (string) $pages->find("name=men");

Share this post


Link to post
Share on other sites

Names are not unique. Look zyON's structure, the page "men" appears under different parents "brand1" and "brand2". The idea is to find all products that have a "men" page as ancestor.

Share this post


Link to post
Share on other sites

I get the ancestor bit. I thought Names are unique but Titles are not? I guess am just confused :):rolleyes:

Share this post


Link to post
Share on other sites

Names must be unique only under the same parent :)

edit: you can have this url if you want: domain.com/page/page/page/page/page/page/page

Share this post


Link to post
Share on other sites

I think changing the structure (like I suggested) would make it more efficient — even just from a product entry standpoint.

Grouping by the largest set first (Men/Women) and then creating any references from there. You could setup the template to show brand / collection in the page list, or you could get all fancy with Page List Better Label

  • Like 2

Share this post


Link to post
Share on other sites

I agree with Reno, and it's even possible to keep the same url structure with url segments.

edit: Well, Soma was right :D

Welcome! Im sure youll get millions of answers within shortly. (Love it) 
  • Like 1

Share this post


Link to post
Share on other sites

Deleted *was looking at the wrong thing*

Share this post


Link to post
Share on other sites

Hi,

First of all, let me say that I was really surprised by the amount of replies and the discussion that was started. Soma was right! This is really a healthy community built around a brilliant piece of software (and I'm still only scratching the surface of it). Thank you all.

Now, to complicate things (!) let me try to explain a bit more what I'm trying to achieve:

On my original post I mentioned the following hierarchy: 

Shoes>Brand1>Men>Collection1>Product1

Shoes>Brand2>Men>Collection1>Product1

Shoes>Brand1>Women>Collection1>Product2

(...).

 

But the structure is a bit more complicated, and it's more like this now:

 

Shoes>Men>Brand1>Casual>Collection1>Product1

Shoes>Men>Brand2>Sport>Collection1>Product1

Shoes>Women>Brand1>Fashion>Collection2>Product1

Shoes>Women>Brand3>Casual>Collection3>Product3

 

But this should also be reflected in the URL itself so it's possible to get a specific product by going to:

 

http://sitename.com/shoes/men/brand1/casual/collection1/product1

 

or get All the products of a specific Men Brand like this:

 

http://sitename.com/shoes/men/brand1

 

or even get all the men shoes at:

 

http://sitename.com/shoes/men/

 

Also the same kind of structure is applied to other products like, say, hats:

 

Hats>Women>Brand1>Collection2>Product1

In the backend, I don't see a real problem not having this hierarchy reflected in the pages but the problem is that I needed the possibility of the client be able to create another brand, for example or another category (like sport, casual, etc).

I hope I explained this in a understandable way.

Share this post


Link to post
Share on other sites

Diogo (Nice to see another portuguese user around here), 

Yes, that's exactly what I need, I wanted to try to keep the url segments like the catalogue structure in the backend, I think thats a really user friendly way. My question is how do I keep that structure without creating pages? (If I use Page fieldtypes like Renobird suggested).

I agree with Reno, and it's even possible to keep the same url structure with url segments.

edit: Well, Soma was right :D



Renobird,

Yes, I think that's a really good approach, but how do I keep the brands / collections on the URL structure with page fieldtypes? 

I think changing the structure (like I suggested) would make it more efficient — even just from a product entry standpoint.

Grouping by the largest set first (Men/Women) and then creating any references from there. You could setup the template to show brand / collection in the page list, or you could get all fancy with Page List Better Label

Share this post


Link to post
Share on other sites

Hi zyON,

I think $input->urlSegments would work here. Although, you may need to up the maximum allowed number of segments in your /site/config.php — I think the default is 4, so you might be OK.

Anyhow, for a URL like:

http://sitename.com/shoes/men/brand1/casual/collection1/product1

In this case you are already specifying the exact page you want, so you can do a simple:

$pages->get("name=$input->urlSegment4");

Putting it all together:

$brand = "";
$type = "";
$collection = "";

if ($input->urlSegment1) $brand = ",brand.name=".$input->urlSegment1;
if ($input->urlSegment2) $type = ",type.name=".$input->urlSegment2;
if ($input->urlSegment3) $collection = ",collection.name=".$input->urlSegment3;

if ($input->urlSegment4) { // if Segment 4, then we know what page to get
    $product = $pages->get("name=$input->urlSegment4");

} else if ($input->urlSegment1){ // check if we are using URL segments
    $products = $pages->find("parent=$page->path . $brand . $type . $collection");

} else {
    // do something else for pages without URL segments
}

This is untested, and written in the browser (there may also be easier methods, this is just off the top of my head while on lunch break.) 

...and of course, it may not work at all. Try it out and let me know.  ;)

  • Like 1

Share this post


Link to post
Share on other sites

On top of what Reno just wrote, it can even be as simple as this:

EDIT: As Reno pointed, this code is wrong, i was even taking in consideration only the last segment, which is not very clever... I will leave it here for the wall of shame  :unsure:

if ($input->urlSegment1) {

    $mypage = "";
    $template = "";

    if ($input->urlSegment4) {

        $name = $input->urlSegment4;
        $parent = products;

    } elseif ($input->urlSegment3) {

        $name = $input->urlSegment3;
        $parent = collections;

    } elseif ($input->urlSegment2) {

        $name = $input->urlSegment2;
        $parent = kind;

    } else {

        $name = $input->urlSegment1;
        $parent = sex;

    }

    $name = $sanitizer->name($name)
    $mypage = $pages->get("parent=$parent, name=$name");

    echo render($mypage);

} else {

// normal code for page without segments

}
 

Um Portuga, boa!

Benvindo :)

  • Like 1

Share this post


Link to post
Share on other sites

diogo, 

Nice.  I was revising my example while you were doing this. See my updated version.

:)

Share this post


Link to post
Share on other sites

diogo,

I'm not following your example. (sorry).

Wouldn't the parent always be either /shoes/men/ or /shoes/women/?

The other parts of the selector are looking for pageField values — and there could be multiple.

Maybe I'm being dense and just not getting it.

  • Like 1

Share this post


Link to post
Share on other sites

You're right... i edited my post.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.