get page type attribute values

Permalink 4 users found helpful
How on earth do you get a list of values entered for a custom page type attribute? I've created a select box attribute and I want to display the values on the front end of the website for a search filter. Any help?

View Replies: View Best Answer
Mnkras replied on at Permalink Reply
Mnkras
Loader::model('attribute/categories/collection');
$ak = CollectionAttributeKey::getByHandle('handle');
$selectedOptions = $c->getAttribute($ak->getAttributeKeyHandle());
if($selectedOptions->count() > 0) {
   foreach($selectedOptions as $opt) {
      echo $opt;
   }
}

That should do it
netnerd85 replied on at Permalink Reply
Thanks for your reply but it only works if the page it's on has the custom attribute set as a property (with all values checked). I want the list of options (attribute values) to display on a serach filter page so that you can search for pages with only the selected attributes. So I just need a list of all the attributes values, is there any way to do that?

I can just set the property for the page with the search filter block on it but I need to select all the options. If the user adds new option values to the attribute then they would have to select them for the page which is a pain from the users point of view.
Mnkras replied on at Permalink Reply
Mnkras
try $ak->getOptions(); then doing a foreach on it
netnerd85 replied on at Permalink Reply
getOptions() isn't a valid function. "Call to undefined method CollectionAttributeKey::getOptions()"
jordanlev replied on at Permalink Best Answer Reply
jordanlev
I just had to do this for a project. It was a huge pain in the rear. Here's the code:
Loader::model('attribute/type');
Loader::model('attribute/categories/collection');
$ak = CollectionAttributeKey::getByHandle('your_attribute_handle');
$satc = new SelectAttributeTypeController(AttributeType::getByHandle('select'));
$satc->setAttributeKey($ak);
$values = $satc->getOptions();
foreach ($values as $v) {
    echo 'ID: ' . $v->ID;
    echo 'Value: ' . $v->value;
}


Note that when you actually run the search that's filtered by a select value, there's a bug in C5 right now that puts newline characters around values in the database table. For example, in my project, I used the above code to populate a dropdown menu in a block's add/edit form (so users could choose a category of pages to display links to in the sidebar). Once I actually had the user's selection for which attribute value they wanted to filter on, I needed to do this to actually retrieve those pages:
Loader::model('page_list');
$pl = new PageList();
$pl->sortByPublicDate();
$pl->setItemsPerPage(3);
$relatedCategoryOptionValue = "\n{$relatedCategoryOptionValue}\n"; //<--THIS IS THE TRICKY THING RIGHT HERE
$pl->filterByRelatedCategory($relatedCategoryOptionValue); //NOTE: You must pass in the attributeValue's name, not the attributeValue's ID!
$relatedPages = $pl->getPage();


-Jordan
netnerd85 replied on at Permalink Reply
Thank you very much Jordan, the code to get the attribute values works great!

The search code you provided gave me the following error:
mysql error: 1054: Unknown column 'ak_related_category' in 'where clause'

I changed the filterByRelatedCategory function to filterByAttribute and that works but, it will only match pages that have the exact amount of attribute values selected. On my search page the attribute values are services and they are displayed as checkboxes. So you select the services you want then it should get all the pages with those services assigned. I would like it to match one or more services, not be required to have the exact services selected. How could I achieve this?

I tried using a LIKE comparison but that is flawed due to it comparing compiled strings based on the services selected. It would match "service1service2service3" but not "service1service3" for instance.
jordanlev replied on at Permalink Reply
jordanlev
The filterByRelatedCategory is just an example, because in my code, the attribute handle is "related_category" -- but if your attribute name is "favorite_color", then the function name would be "filterByFavoriteColor".

And unfortunately I don't know how to do what it is you want to do -- I was only coding it to pull up all pages with one specific attribute value, not all pages with any number of selected attribute values.
netnerd85 replied on at Permalink Reply
Ah okay I get it now. I've done a bit of hacking to get it working, so I'm still looking for a better solution if anyone has any ideas.

item_list.php, line 83 has been changed to:
if($column == 'ak_services'){
$q .= 'and ' . $column . ' ' . $comp . ' ' . $value . ' ';
}else{
$q .= 'and ' . $column . ' ' . $comp . ' ' . $db->quote($value) . ' ';}

Basically just removing the quote escaping. Then I have:
Loader::model('page_list');
$pl = new PageList();
$_service = "";
foreach($_REQUEST['services'] as $service)
{
$service = addslashes($service);
$_service .= "\\n{$service}\\n%' or ak_services like '%";
}
$_service = rtrim($_service, " or ak_services like '%");
$pl->filterByAttribute('services', "'%".$_service."%'", 'like');
$relatedPages = $pl->get();
jordanlev replied on at Permalink Reply
jordanlev
Oh boy this thread is SO old now, but I had to dig this up for a new project and I can now understand what the problem with your code was:

The $db->quote() function escapes quotes in the string (so they're safe for use in a SQL query), *and* surrounds the string in quotes. In your code, you're calling filterByAttribute() like this:
$pl->filterByAttribute('services', "'%".$_service."%'", 'like');

...which means you are surrounding your value with quotes and then the c5 code in item_list.php surrounds it again. Instead what you want to do is this:
$pl->filterByAttribute('services', "%".$_service."%", 'like');

(the difference is that the single-quotes were removed from around the percentage signs).

And you absolutely do **NOT** want to **EVER** remove the $db->quote() function from the item_list.php file, as this opens you up to serious SQL injection attacks! (All someone has to do is put a quotation mark in a service name and you're potentially hosed). Seehttp://www.concrete5.org/community/forums/customizing_c5/pagelist_f...

EDIT: Also note that the 2nd argument of the rtrim() function is not a substring to trim, but rather a list of characters -- so this is probably not doing the right thing either. For removing a substring at the end of a string, seehttp://stackoverflow.com/q/5573334/477513...
netnerd85 replied on at Permalink Reply
Thanks!, I'll need to check this... if I can... remember... where...

Agreed on SQL issue. I'm sure I sorted it.

[Edit]Actually that rtrim looks dumbass doesn't it. I normally use it for one character but that... doesn't... o0
midlight replied on at Permalink Reply
midlight
thanks.. i just felt like i've never coded c5 before. you saved me. :D
tudorsv replied on at Permalink Reply
$at_cat = AttributeKeyCategory::getByHandle('collection');
$at_key = $at_cat->getAttributeKeyByHandle('your_at_key_handle');
$at_key_id = $at_key->getAttributeKeyID();

$at_key->render('form');
$at_key->outputSearchHTML(); //similar to render