Usually the section's objects that BEdita loads automatically are what you need for your frontend app, but sometimes you would want filter objects inside a section to obtain a more specific list of items to use in  views.

In these cases the FrontendController::sectionOptions attribute is what suits you. Through this attribute you can control pagination results and other things, like how many and which contents get and in which order you want them.

Overriding the key "filter" in this class attribute you can easily handle children's section results. You can override $sectionOptions for an entire frontend redefining it in PagesController, but usually you'll override it just in some specific section. To do so you should use the section callback nicknameBeforeFilter, before section data loading, to set your filter.

Default behavior

Suppose that you have a section nicknamed "my-section" that contains different kind of object type (documents, galleries, events, ...) and that you want to fetch only documents, then you can set the filter option as

protected function my_sectionBeforeFilter() {
	$this->sectionOptions['childrenParams']['filter'] = array(
		'object_type_id' => Configure::read('objectTypes.document.id')
	);
}

where object_type_id is a field of objects table. See also $config[objectTypes] definition. Note also that in BEdita 3.2 or higher the method name would camelize i.e. mySectionBeforeFilter.

The SQL conditions

WHERE object_type_id = '22'

 will be generated.

If you want to select galleries too then write

$this->sectionOptions['childrenParams']['filter'] = array(
	'object_type_id' => array(
		Configure::read('objectTypes.document.id'),
		Configure::read('objectTypes.gallery.id')
	)
);

The SQL conditions

WHERE object_type_id IN ('22', '29')

 will be generated.

You can of course add other kind of fliters, for example using specific database table fields want to add other filter. Say you want to filter using publication start_date you may want to use this

$this->sectionOptions['childrenParams']['filter'] = array(
	'object_type_id' => array(
		Configure::read('objectTypes.document.id'),
		Configure::read('objectTypes.gallery.id')
	),
	'Content.start_date' => ">= '2011'"
);

In that way a one to one relation is used to join objects to contents table and the SQL conditions

WHERE object_type_id IN ('22', '29') AND Content.start_date >= '2011'

is used.

 

Other filter rules

Some other filter rules are defined in BuildFilter Behavior located in bedita-app/models/behaviors folder. These rules are usually used in BEdita backend but you can use it for your need. Every rule is defined with a method named with the rule name followed by "Filter" word.

For example you could use the category filter to filter objects by category.

$this->sectionOptions['childrenParams']['filter'] = array(
	'category' => 'documentation'
);

where "documentation" is the name of the category you want to filter for.

Pay attention on the fact that not all filter rules that you find in BuildFilter Behavior are useful in frontend app, if used through $sectionOptions attribute, because filter results are refined at a later stage.
For example, if you want to use a filter in order to add fields to results you must use model bindings instead.
So if your section's objects have to show the user that has created them and you apply the filter

$this->sectionOptions['childrenParams']['filter'] = array(
	'user_created' => true
);

the result does not reflect what you would expect, because it is refined getting objects' details through model bindings. You should instead check that all objects bindings contain UserCreated.

Create your own rules

From BEdita higher than 3.1.6 the filter is highly customizable extending the BuildFilter Behavior class and following some simple rules.
We're going to explain how to do it in a next article.