Get attribute set by handle, loop thru attribute keys, output key name and key value

Permalink 6 users found helpful
Don't know where else to put this, but if you need to grab an attribute set, get the keys and loop through each attribute outputting the name and value: (this is within a custom template view, so $c is the page collection, which is normally passed to view and is available)

Here is the code:

<?php $attr_set = AttributeSet::getByHandle('your_handle'); ?>
<?php $attr_keys = $attr_set->getAttributeKeys(); ?>
<?php foreach($attr_keys as $ak) { ?>
  <?php echo $ak->akName ?>
  <?php echo $c->getAttribute($ak->akHandle) ?>
<?php } ?>


Hope this helps someone! (and if you are new to php, you can do a
echo '<pre>'; print_r($ak); echo '</pre>';

to see what the object looks like

 
chris123uk replied on at Permalink Reply
chris123uk
Thank you.
mrjcgoodwin replied on at Permalink Reply
mrjcgoodwin
Sorry to drag up an old thread but it seemed unnecessary to start a new one so similar.

Can anyone give me a pointer as to how this snippet can be modified to only return the attributes in a set that have been checked/set.

Thank you :-)
chris123uk replied on at Permalink Reply
chris123uk
Please paste here the output of print_r($ak);
mrjcgoodwin replied on at Permalink Reply
mrjcgoodwin
Hi Chris,

This is an output example - I've created a set of attributes with page categories. E.g. below 'Graphic Design'. The set handle is 'port_cats'.

I want to echo out the handles as html classes in my template - but only if they're present. I.e. the page is in a certain category.

</pre><pre>CollectionAttributeKey Object
(
    [searchIndexFieldDefinition:protected] => cID I(11) UNSIGNED NOTNULL DEFAULT 0 PRIMARY
    [error] => 
    [akID] => 16
    [akHandle] => cat_graphic
    [akName] => Graphic Design
    [akCategoryID] => 1
    [akIsInternal] => 0
    [akIsEditable] => 1
    [akIsSearchable] => 1
    [akIsSearchableIndexed] => 0
    [akIsAutoCreated] => 0
    [akIsColumnHeader] => 0
    [atID] => 3
chris123uk replied on at Permalink Reply
chris123uk
so if the current page your on is in a certain category you want to get the handle back as a css class and the category is defined by an attribute that is in a set?

Is that correct?
mrjcgoodwin replied on at Permalink Reply
mrjcgoodwin
Yes exactly, the only slight complication being that a page might be in multiple categories.

At the moment I'm successfully echoing out all the attribute handles in the set as classes (as below), just need to eliminate the empty ones. (As you can tell I'm no php whiz!)

$attr_set = AttributeSet::getByHandle('port_cats');
$attr_keys = $attr_set->getAttributeKeys();
      /*** The html from here down to the "endforeach" line is repeated for each page in the list... */ ?>
      <article class="column one-third portfolio-item
         <?php foreach($attr_keys as $ak) { 
               echo " " . $ak->akHandle;
               } ?>">
         <div class="portfolio-container">
         <div class="portfolio-item-cover">
            <p><img class="full-width" src="images/portfolio_img1.png" /></p>
         </div>
         <div class="portfolio-item-description">
               <h4><?php echo $title ?></h4>
               <p><?php echo $excerpt; ?></p>
               <p><a href="<?php echo $url ?>">Read more</a></p>
chris123uk replied on at Permalink Reply
chris123uk
This might be a bit over the top for what you need and is untested.
create a select attribute that you can select multiple options with then update your_select_attr_handle in the code below.

$results = array();
                      $attr_set = AttributeSet::getByHandle('port_cats');
                      $attr_keys = $attr_set->getAttributeKeys();
                      $pl = new PageList();
                      //$categoryPage = Page::getCurrentPage();                                 
                      //$pl->filterByPath($categoryPage->getCollectionPath()); // only get pages below this one.
                      //$pl->filterByCollectionTypeHandle("mix_child"); // only get pages with this pagetype Handle
                      $pl->sortByDisplayOrder(); // the order in the site map  
                      //$pl->filter(false, '(ak_exclude_page_list = 0 or ak_exclude_page_list is null)'); // dont show products that have the exclude from page list attr on them           
                      $pagelist = $pl->get();              
                      foreach ($pagelist as $page) {
                      foreach($attr_keys as $ak) {
                      if ($ak->atHandle == "your_select_attr_handle") {                         
                        $theStuffInside = $page->getAttribute($ak->atHandle); // get the attribute
                        if (is_object($theStuffInside)) {
mrjcgoodwin replied on at Permalink Reply
mrjcgoodwin
Wow - incredibly detailed reply thanks Chris - I'll give it a shot and let you know how I get on! Thanks so much for your help - love the C5 community! :-)
mrjcgoodwin replied on at Permalink Reply
mrjcgoodwin
Hi Chris (and anyone else who wishes to chime in!),

I've been digesting what you posted and giving this all some more thought. (Thanks again!)

I think you are right that this is probably overkill for what I'm trying to achieve - mainly as I don't necessarily need to output a completely new page list as my theme already handles the sorting via JS and html classes and works fine (when hard coded).

However I think you may be onto something regarding using a single select box attribute rather than separate text attributes.

That led me to various snippets on the forums along the lines of:
$arrOptions = array();
$ak = CollectionAttributeKey::getByHandle('portfolio_cats');
$akc = $ak->getController();
$arrOptions = $akc->getOptions();
foreach($arrOptions as $objOption){   
   echo $objOption->value . ' ';
}


This again however outputs *all* the options in the select attribute not just the *selected* options.

I'm sure there must be a way built into the core to check if the attribute options are selected or not, as that's what they're there for?

I've seen mentions of
GetSelectedOptions
being used, however if I use that in the code above it outputs nothing.
chris123uk replied on at Permalink Reply
chris123uk
looks like getOptions will get all the options added to a select independent of what page it is on.


$set = AttributeSet::getByHandle('sorting_options'); // set handle
   $keys = $set->getAttributeKeys();
   foreach($keys as $key) {
      $handle = $key->getAttributeKeyHandle();
      if( $handle == 'website_features' ) { // handle of a select with more that one option 
         $type = $key->getAttributeType();
         $cont = $type->getController();
         $cont->setAttributeKey($key);
         $terms = $cont->getOptions();
         foreach($terms as $value) {
          echo $value."<br>";
        }
         break;
      }
chris123uk replied on at Permalink Reply
chris123uk
you can get back the values of a select attr for the current page your on by using this:
$theStuffInside = Page::getCurrentPage()->getAttribute('website_features'); // your select attr handle
$results = array();
  if (is_object($theStuffInside)) {
    $foo = 1;           
    foreach ($theStuffInside as $value) { // this is needed in the situation that a page has more than one select value 
      if ($foo == 1) {
          $dropdownGroup .= str_replace(' ', '', $value); // fix value so it will work as a class in page
      }
      else {
          $dropdownGroup .= " ".str_replace(' ', '', $value); // fix value so it will work as a class in page
      }
      $foo++;                                               
    }    
    $results['website_features'][] = $dropdownGroup;  
    $dropdownGroup = NULL;


if you need to show other pages attributes on the current page then you have to use a page list.
mrjcgoodwin replied on at Permalink Reply
mrjcgoodwin
Thanks a million Chris you've been a super help and this was just the steer in the right direction I needed :-)
I knew it must be possible!... this is why I use proper devs when doing paid work not personal projects lol! But this has been a great help and also increased my php knowledge a bit!

If anyone else stumbles across this thread this is finished result:

This is a mod to Jordan's clean page list template so there's some other bits in there too. Basically loops through to retrieve the category attributes of a page in the list and utilises them as classes.
<article class="column one-third portfolio-item
         <?php 
               $theStuffInside = $page->getAttribute('portfolio_cats'); // your select attr handle
            $results = array();
              if (is_object($theStuffInside)) {
                $foo = 1;           
                foreach ($theStuffInside as $value) { // this is needed in the situation that a page has more than one select value 
                  if ($foo == 1) {
                      $dropdownGroup .= " cat_".str_replace(' ', '', $value); // fix value so it will work as a class in page
                  }
                  else {
                      $dropdownGroup .= " cat_".str_replace(' ', '', $value); // fix value so it will work as a class in page
                  }
                  $foo++;                                               
                }


Then on the portfolio page itself, I use the following to output the complete list of attributes available to output the list of categories for sorting with separate JS script.

<ul class="column full-width portfolio-filter">
                  <li><a class="button light-grey rounded active show-all" href="#">All</a></li>
                  <?php
                  Loader::model('attribute/type');
                  Loader::model('attribute/categories/collection');
                  $ak = CollectionAttributeKey::getByHandle('portfolio_cats');
                  $satc = new SelectAttributeTypeController(AttributeType::getByHandle('select'));
                  $satc->setAttributeKey($ak);
                  $values = $satc->getOptions();
                  foreach ($values as $v) {
                     echo '<li><a class="button light-grey rounded ' . ' cat_' .str_replace(' ', '', $v->value) . '" href="#">' . $v->value . '</a></li>';
                  }
                  ?>
               </ul>
chris123uk replied on at Permalink Reply
chris123uk
I have been using similar code to build mixitup into one of my sites.
http://mixitup.kunkalabs.com/
mrjcgoodwin replied on at Permalink Reply
mrjcgoodwin
That's actually remarkably similar to what I'm working with - will remember that plugin for future cheers -very impressive.

This whole page attributes/filtering page list setup also actually comes very close to replicating the experience of Wordpress category pages which I've seen a few people requesting on here before.
chris123uk replied on at Permalink Reply
chris123uk
haa am actually working on my first wordpress theme right now its a beeyatch! so odd how it works. I just want to add blocks... Why cant i add blocks...
mrjcgoodwin replied on at Permalink Reply
mrjcgoodwin
haha! Yeah it does my head in switching between the two - so many pros and cons to each!