We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 37313
    • 6 Posts
    First time MODX user here - enjoying the experience so far! I've come across a stumbling block which is a bit beyond my rudimentary understanding of how MODX works, and am hoping someone might be able to help.

    The site I'm building needs to organise the client's products based on category. The end user will select categories from text-links, and they'll be presented with the products that match that category. Products can also exist under multiple category titles, so in a way it's like a tagging system where the tag titles are category titles.

    When the client creates a new product Resource, there will need to be a TV list of the current categories which allows for multiple selection. Ultimately I only want to have one place where the actual category text is inputted, so it is easy to create new categories or edit the wording of existing ones.

    What is the easiest way to go about this?

    Should I create a container resource, then create the categories as titled resources inside that, then pull those resource titles into a TV multi-list? Is that possible? Or should I just create a multi-checkbox TV with the Input Option Values set to "category1==category1||category2==category2...etc", then use getResources to somehow pull out the values from that TV for displaying as tag links? Is that possible? Which is the simplest way to achieve this?

    I have a feeling this is a really simple problem for the capabilities of MODX, but I'm too unfamiliar with MODX to easily solve this myself.

    Thanks for any help anyone can provide!
      • 36906
      • 34 Posts
      TheNewManifesto Reply #2, 15 years ago
      Hi,

      I've just been working on something like this.
      I needed multiple categories to apply to products.

      Probably too much to post here, but press me for details if needed - I appreciate this post might be a bit wooly...


      Your idea is along the right lines, but it kind of depends on the complexity and scale of the catalogue + products. Yes, you could 'Bind' the TV to a simple query to build the links...


      Definitely worth taking the time to find a good solution, rather than winging it and getting into hot water once the site goes live (and thousands of products/categories start getting pumped into it!).

      I would say that having the Categories as child Resources of a Container Resource is a nice easy way for your client to work with them in the CMS, but using a whole Resource to denote a category is overkill… (I think all MODXers come up against this at some point).



      Have you looked into using an XPDO package and custom tables?
      It sounds like hard work, but its trivial enough to do… You'll never look back.
      I can help you with this on ground level if needed.


      As a simplified starting point...

      Three custom tables within an XPDO package called 'Catalogue'

      Product (PK = product_id)
      Category (PK = category_id)
      ProductCategory (product_id + category_id)

      This DB architecture would allow you to assign multiple Categories to Products using ProductCategory.


      From there, you'd could create a custom snippet to replace 'getResources' (e.g, getProducts) that you would use in combination with 'getPage' on your 'category landing pages'.

      http://mysite.com/category/?category=foo

      ]] getPage? &element=`getProducts` &tpl=`categoryListItem` [[

      'getProducts' would look at your $_GET params and then use them as a basis for the query, with a join onto ProductCategory as a filter (getPage just splits this into 'offset' + 'limit' queries for paging).


      (pseudo code)

      select
      x,
      y,
      z
      from `product` p
      join `product_category` pc
      on (`pc`.`product_id` = `p`.`product_id`)
      join `category` c
      on (`c`.`category_id` = `pc`.`category_id`)
      where `p`.`active` = '1'

      if($_GET['category']) {
      and `c`.`alias` = 'foo'
      }

      Please note, there are native/better XPDO methods for doing the above query, but you get the idea.


      Any requests without a category will get all of the products.

      You could also take things a step further to use URLs like:
      http://mysite.com/category/foo/
      This could be done with webserver rewrites, or by using the MODX 'PageNotFound' event.


      Sorry if this is all a bit vague - its fairly simple once you get a foot in the door.
      Hopefully, someone else will post a better response for you!


      I would definitely recommend getting to grips with the XPDO core of Modx.
      Feel free to message me if you need more details, code examples etc...

        • 37313
        • 6 Posts
        Thanks very much for the reply! I'll check out XPDO and see how it fits. Thanks also for the generous offer of providing help for this - much appreciated.

        One thing I forgot to mention though - the scale of our site when completed will be very small; in fact only about 7 categories and 12 products or so. By the time the client has more categories and products than that, they will probably be wanting a new website anyway! So therefore, XPDO may be fairly extreme overkill!

        In addition, the ability to create a new category is probably not so critical right now, as the categories are tied into various static elements of the site which the client will not be able to change. However, the ability to create a new product and file it under one of the existing categories is required.

        What would be your suggestion? For something this small, would using Bindings be the best choice? Or perhaps a tagLister combination?
          • 36906
          • 34 Posts
          TheNewManifesto Reply #4, 15 years ago
          I think in the case of a few products, your Resource/Category/Binding setup sounds alright...

          It also means that the client will be happy adding/editing content against each category resource - they can make each category distinctive with introductions, banners etc.

          This is an example of a binding for that multi-select TV/Category Resource relationship:

          @SELECT CONCAT(`pagetitle`,'==',`alias`,'||') FROM `site_content` WHERE `deleted` = '0' AND template = '12' and `parent` = '8' 


          (template=12 being the 'Product Template', and 8 being the Categories Container.)

          Its possible that GetResources will do a '%LIKE%' comparison on TVs, in which case that should handle the multiple category aspect because they (multi-selects) are stored as 'sports||casual' in the DB.

          If GetResources does do LIKE as a TVFilter, its all good…
          You would just pass the Category 'alias' to the GetResources 'TVFilter' parameter.

          If GetResources doesn't do LIKE on TVs, then a simple lightweight database query in a Snippet could get you valid Resource IDs that can then be passed directly to GetResources, or via GetPage.

          A snippet called 'getCatProdIdsSnpt', with a DB query along the lines of:

          SELECT CONCAT(`contentid`,',') `contentid` FROM `site_tmplvar_contentvalues` tvv 
          JOIN `site_content` sc 
          ON (sc.`id` = tvv.`contentid` AND sc.`parent` = '0' AND	sc.`published` = '1' AND sc.`deleted` = '0')
          WHERE `tvv`.`tmplvarid` = '11' 
          AND `tvv`.`VALUE` LIKE '%$category_alias%' 


          (tmplvarid=11 being the ID of your multi-select TV)

          Would give you a string of Resource IDS that could be used something like:
          [[!getResources? &resources=`[[!getCatProdIdsSnpt?]]`]]



          Either way, GetResources could then handle the display/loop of your 'ProductListItemChk' chunk as normal.

          Again, look up the above snippets to get the exact syntax!

          I'm just trying to help you think about the overall process.

          Its sounds like TagLister could also be an avenue… [ed. note: thenewmanifesto last edited this post 15 years ago.]
            • 37313
            • 6 Posts
            Wow, thank you so much Manifesto for taking the time out to explain all that. I'll study it all thoroughly.

            I'm beginning to think though that perhaps it might be better not to have the categories titles as individual resources. The client is not so computer savvy, and having the category titles listed as resources might give a false impression that they are easily added or edited, which is not really what I want.

            So if it is OK to have the category titles buried a bit deeper down, what other simple options are there for achieving all this?
              • 36906
              • 34 Posts
              TheNewManifesto Reply #6, 15 years ago
              Hi,

              The easiest way to render the category list could be to replace the TV Binding with a manually typed list.

              eg, in your Category TV, just type:
              CategoryTitle==categoryalias||CategoryTitle2==categoryalias2 etc...

              I do it this way for small 'TV select menus' that don't warrant a full database table/resource etc...



              All you would need to do to add new categories is a bit of copy and paste with this list - keeping them alphabetical...

              Is this what you mean?
              Its still fully/easily controllable for you - but something the client might not stumble across themselves.

              [ed. note: thenewmanifesto last edited this post 15 years ago.]
                • 37313
                • 6 Posts
                Thanks again for your help Manifesto! Yes, this is what I was thinking to do also. I guess this might be the simplest way to achieve all this.

                Just one last question: If I did have my categories based inside the TV like this, what would be the best way to pull out just one of the category titles for display as a link somewhere?

                For example if my TV looks like this:
                categoryTitle1==categoryAlias1||categoryTitle2==categoryAlias2||categoryTitle3==categoryAlias3

                .. and I want to create a link that uses either the text from categoryTitle1 or categoryAlias1, is there a way to pull out just this one section? That way if the client wants to make a minor change to the wording of a category, I only need to edit it once here in the TV list and all is well.

                Thanks so much for taking the time out to help. (oh.. I say that in every reply I write.. shit.. OK.. yeah, you get the idea! smiley
                  • 36906
                  • 34 Posts
                  TheNewManifesto Reply #8, 15 years ago

                  Hi,
                  I think I follow…
                  Yes, the category TV would be the only place where they were edited.


                  You'll probably need to loop over them to create the menu:
                  1) Get hold of the category field value in a snippet.
                  2) explode() on '||' and loop.
                  3) on each iteration, explode() on '==' to get your title/alias values.
                  4) Use a chunk to display.

                  I couldn't think of a scenario where I would need to only get one of the values - do you have any examples?