Composr Tutorial: Filtering using Filtercode syntax
Written by Chris Graham (ocProducts)
Composr contains a filtering system for selecting content based upon defined filters. Filtercode is the language for defining filter strings, and is an advanced feature of Composr. Filtercode is not to be confused with Selectcode, which is the language for determining what results to return via ID, ID range, category, or tree-position.
Table of contents
An introductory example
An Filtercode filter string consists of comparisons, separated by commas. Here is an example:Code
something=value,somethingelse>value
In this example, the first is an = comparison, and the second is an > comparison. Anyone who knows very basic maths will understand what these mean.
something and somethingelse would be database field names for the main database table of whatever content type is being filtered.
The full language
The field names must match field names in the content type's main database table, or one of the following special values:- average_rating (the rating)
- compound_rating (popularity: what has been given most likes/stars by summing up all ratings – something with lots of 2 star ratings would be more 'popular' than something with only a few 5 star ratings)
- meta_keywords (the SEO keywords / tagging)
- meta_description (the SEO description)
- field_<id> (custom fields, where <id> is the field ID of the custom field)
We support the following comparison types…
Security note
For security reasons, some fields are not available to Filtercode, such as password fields
GET/POST?
GET/POST parameters are the technical name for how parameters are passed to web pages. The &something=value stuff you see in URLs are GET parameters, and POST parameters are what forms pass around behind-the-scenes.
Symbol | Meaning |
---|---|
< | Less than |
> | Greater than |
<= | Less than or equal to |
>= | Greater than or equal to |
= | Equal to, where blank means skip |
== | Equal to, where blank means literally a blank value will be matched |
<> | Not equal to, where blank means skip |
!= | Not equal to, where blank means literally a blank value cannot be matched |
~= | Contains substring |
~ | Seems to match, according to database full-text search matching; minimum of 4 search characters required, matches words not substrings, inexact matching |
@ | Falls within a range, e.g. 1-4 |
# | Value on the right is within the comma-separated list field referenced on the left |
You can use pipe symbols (|) to split alternative acceptable values on any equality/contain comparators (=, ==, ~, #, ~=).
Parameter binding
The comparison value can either by given directly, like in the introductory example, or it can be written like <name>, which will tell it to look within a GET/POST parameter called filter_<name>. This is the mechanism by which you hook up forms to the filter strings.You can also read in operators from GET/POST parameters, by referencing the comparison types like <name_op> and having the same GET/POST parameter be read. This is useful for particularly advanced forms, if you want users to define how each field should match.
More advanced filtering (for programmers)
If you want to make a filter match on another field (a field-to-field comparison), you can surround it in curly brackets in its own clause, like {Maker=Owner}. In this example, we're selecting entries where the maker is the owner (so maybe unsold goods).(Note that @ and ~ operators are not supported for field-to-field comparisons.)
If we want to match against a condition in a(nother) catalogue (or table if the main entity is a table), then we can do this using the dot notation. For example, events.id=3 would connect to a catalogue called events, connecting to records where the ID value is 3. This is the same as an "inner join" in SQL: you may wish to read up about these.
Both the above examples are quite contrived, but put together we can use them to define proper join conditions so that we can limit results based on a check into another catalogue (or table).
For example, imagine this Filtercode was used on a catalogue named products:
{Manufacturer=manufacturers.id},manufacturers.Trading=1
This finds products entries that have a manufacturer that is trading. It combines the products catalogue with the manufacturers catalogue, under the basis that the products catalogue has a field named Manufacturer that points to a manufacturers entry. It then adds an additional check that will limit overall results so that only products entries will be returned that can match to an manufacturers entry where Trading is checked.
We do a field-to-field comparison across two catalogues, to make a match up, so that we can then add in a check on what we can match up. Note that if there are no matches across the two catalogues before the check is processed, this would be the same thing as the check not passing.
Another example, imagine this Filtercode was used on a catalogue named locations:
{events.Venues#id},events.Performer=Justin Bieber
This would find all locations that was a venue for an event performed by Justin Bieber. It combines the locations catalogue with the events catalogue, under the basis that the events catalogue has a field named Venues that points to multiple events entries. It then adds an additional check that will limit overall results so that only locations entries will be returned that can match to an events entry where Justin Bieber is performing.
Where the filters can be used
- main_multi_content
- main_gallery_embed
- main_cc_embed
As well as active support within the following modules:
- catalogues
- downloads
- galleries
- members
- news
As explained above, Filtercode works by reading GET/POST parameters and matching them using the rules specified in the defined Filtercode filter string. In the case of the filtering for the modules, the filter string is also supplied as a GET/POST parameter.
Generating filters
The concept of writing Filtercode filter strings, and matching forms, can be a bit daunting. This is why the main_content_filtering block exists. It will automatically construct filters and forms for content types.You don't actually need to use this block in production at all. It is a good way to build up a default form, which you can then get HTML from as a starting point.
There are two steps in getting your HTML ready:
- Show the block for your content type, with no parameters
- Grab the auto-generated Filtercode filter string and customise it, then show the block using your customised filter
In our case the auto-generated Filtercode filter string was:
Code
allow_comments<allow_comments_op><allow_comments>,allow_rating<allow_rating_op><allow_rating>,allow_trackbacks<allow_trackbacks_op><allow_trackbacks>,author<author_op><author>,date_and_time<date_and_time_op><date_and_time>,edit_date<edit_date_op><edit_date>,news<news_op><news>,news_article<news_article_op><news_article>,news_views<news_views_op><news_views>,notes<notes_op><notes>,submitter<submitter_op><submitter>,title<title_op><title>,validated<validated_op><validated>,average_rating<average_rating_op><average_rating>,meta_keywords<meta_keywords_op><meta_keywords>,meta_description<meta_description_op><meta_description>
We will take that and modify it. In this case I think the following filter is much better:
Code
author~=<author>,date_and_time><date_and_time>,news|news_article|title|meta_keywords|meta_description~=<news>,submitter=<submitter>,average_rating>=<average_rating>
We then feed back into the same block's param setting to get our refined filter form (see the image below).
Putting the filter form into the site
If we are happy with how our refined filter form looks, we can continue with the main_content_filtering block.Otherwise, we can grab the HTML that the block output and tune it. The only thing that Composr needs is the GET/POST fields to match what the Filtercode filter string wants, otherwise you can use whatever HTML you want.
We'll assume we'll continue to use the main_content_filtering block for the following continuations of our news filtering example.
Putting into a panel (example)
If you want to place a filter on the news module, with it shown in a panel only on the news module, you'd put something like this into your panel's Comcode:Code
{+START,IF,{$MATCH_KEY_MATCH,site:news}}[block="author~=<author>,date_and_time><date_and_time>,news|news_article|title|meta_keywords|meta_description~=<news>,submitter=<submitter>,average_rating>=<average_rating>" content_type="news" labels="date_and_time=Newer than,news=Containing,submitter=Submitted by,average_rating=Minimum rating" types="date_and_time=days"]main_content_filtering[/block]{+END}
Putting into a news template (example)
If you wanted it on the news archive screen, you'd edit the NEWS_ARCHIVE_SCREEN.tpl template and add:Code
{$BLOCK,block=main_content_filtering,param=author~=<author>\,date_and_time><date_and_time>\,news|news_article|title|meta_keywords|meta_description~=<news>\,submitter=<submitter>\,average_rating>=<average_rating>,content_type=news,labels=date_and_time=Newer than\,news=Containing\,submitter=Submitted by\,average_rating=Minimum rating,types=date_and_time=days}
Sorting
Filtercode has support for a number of hard-coded special field names…- average_rating – rating
- compound_rating – total likes
- fixed_random – a pseudo-random number for the entry that changes daily
- meta_description – meta description
- meta_keywords – meta keywords
See also
- The form field filter system
- Comcode and the attachment system
- Advanced Comcode
- Using blocks
- Filtering using Selectcode syntax
Feedback
Please rate this tutorial:
Have a suggestion? Report an issue on the tracker.