2
votes

I'm banging my head trying to figure this out and I feel like I'm over thinking it.

So I've built 2 DataObjects (Brand, Product) and 1 Controller/Page (ProductType).

  • ProductType has many Products
  • Product has one Brand
  • Product has one ProductType
  • Brand has many Products

What I'm looking to do is:

ProductType pages should make available a list of Brands that are used ONLY by the Products of that Type.

Now I have one somewhat working but it feels hacky and not very portable. Example below:

ProductType Controller:

public function getBrands() {

        if($products = $this->Products()) {
            $group = GroupedList::create($products->sort('BrandID'))->GroupedBy('BrandID');
        }

    }

Product Type Template:

<% if Brands %>
    <ul>
        <li><a href="{$Link}">All</a></li>
        <% loop Brands %>
            <% loop Children.Limit(1) %>
                <li><a href="{$Top.Link}brand/{$Brand.URLSegment}">$Brand.Title</a></li>
            <% end_loop %>
        <% end_loop %>
    </ul>
<% end_if %>

Is there a way I can build a method in the ProductType controller that would return a DataList of just the Brands used by Products of that type?

Using Silverstripe 3.1.3

Let me know if I need to be more clear about something and thanks!

1
Normally it should only group by the brands used int $this->Products(); So what's the problem? You get a list of all brands? or of brands not used by that products in $this->Products()? have you double checked the latter and checked your database? BTW: which version of SS are you using? - wmk

1 Answers

1
votes

Ah, i guess you had a misunderstanding of a GroupedList

You already have the Datalist of all products of this product type.

It's the has_many relation

$this->Products()

now you want to group the current products by BrandID. Your method naming might be confusing, so let's rename it a bit:

public function getProductsGroupedByBrands() {

    if($products = $this->Products()) {
        $group = GroupedList::create($products->sort('BrandID'))
            ->GroupedBy('BrandID');
    }

}

So in your template you have a GroupedList you can loop over.

<% if Products %>
    <ul>
        <li><a href="{$Link}">All</a></li>
        <% loop ProductsGroupedByBrands %>
            <li>
                <%-- here you should be able to see the grouping relation --%>
                <a href="{$Top.Link}brand/{$Brand.URLSegment}">$Brand.Title</a>


                <%-- in doubt use the First element to get the current Brand, it's a has_one -->
                <% with $Children.First %>
                    <a href="{$Top.Link}brand/{$Brand.URLSegment}">$Brand.Title</a>
                <% end_with %>
                <ul>

                <% loop Children %>
                <%-- here are the products grouped by brand --%>
                    <li>$Title</li>
                <% end_loop %>
                </ul>
            </li>
        <% end_loop %>
    </ul>
<% end_if %>

See also Silverstripe Docs or Grouping Lists