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.


An introductory example

An Filtercode filter string consists of comparisons, separated by commas. Here is an example:

Code

something=value,somethingelse>value
This defines two comparisons. Both must hold true for any result returned (i.e. they are ANDd).

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)
You are allowed to specify that comparisons may work on multiple fields, by separating field names with pipe (|) symbols. This is particular useful for a search filter, to make the typed string look across multiple fields.

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

Image

An automatic news filter form

An automatic news filter form

(Click to enlarge)

There is an Filtercode-based parameter for the following blocks:
  • main_multi_content
  • main_gallery_embed
  • main_cc_embed

As well as active support within the following modules:
  • catalogues
  • downloads
  • galleries
  • members
  • news
(the filter used will be read from any GET/POST active_filter parameter that is set)

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:
  1. Show the block for your content type, with no parameters
  2. Grab the auto-generated Filtercode filter string and customise it, then show the block using your customised filter

Image

Inspecting the block's HTML to get the auto-generated Filtercode filter string, which we'll use as a starting point

Inspecting the block&#039;s HTML to get the auto-generated Filtercode filter string, which we&#039;ll use as a starting point

(Click to enlarge)

Once you have built a default form for a content type, inspect the HTML to get the auto-generated active_filter value (see the image to the right).

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).

Image

A refined filter form

A refined filter form

(Click to enlarge)

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
Some of these may also appear as sorting options in various blocks.

Concepts

Filtercode
Composr's syntax for filtering returned content

See also


Feedback

Please rate this tutorial:

Have a suggestion? Report an issue on the tracker.