Conditionalizer
This is an open discussion with 44 replies, filed under Extensions.
Search
With Conditionalizer you can use conditional filtering to prevent data source from querying database when it's not needed.
After adding this field to section, you will be able to filter data source like this:
(if value of ({$entry}) is (welcome))
to make data source load entries only if $entry value is "welcome".
Or this:
(if any of ({$ds-list}) is in (one,two,three,{$param}))
to load entries only if any of the values found in $ds-list parameter is equal to "one", "two", "three" or value of $param parameter.
Of course most of that is also possible with built-in filtering, so Filter field is useful mostly when filtering by data source generated parameters or with really complicated stuff (which probably could be simplified by changing site structure :).
In some cases it can be useful to minimize number of SQL queries, because when expression evaluates to false, database is not queried at all and data source outputs empty set.
View README.markdown file for description of syntax and more examples.
Download
Marcin, where would I be without you! This functionality was on the top of my wish-list, for existing filtering functionality enables me to avoid some queries but still leaves me with 1214 queries for dynamically listing 5 latest items added to a certain category, while the greater amount of them is needed only when viewing items in more detail.
Thanks, glad You like it! :).
I wonder how many queries did You manage to cut down with this extension? It probably depends on number of entries returned by data source.
I'm using it on site where one page has many data sources, but uses only some of them, depending on URL path params passed to it. There are not many entries there yet, so number of queries this field removed was not that high, but still worth a try :).
Let me know if You'll need more functions. I was thinking about some basic math checks (adding, subtracting, counting), but decided it will be hardly useful and slowing down parsing of common cases.
I'll let you know how many queries I am able to cut down when I have implemented this extension, but I guess it will be a lot. I am also going to use it on a site where one page has many data sources and uses only one of them depending on the category, display type, and language.
I am having problems with the filter syntax and can't figure out the syntax to filter for 2 variables (or more).
These don't work:
(if all of ((if value of ({$categorie}) is (cookie)), (if value of ({$language}) is (english)))) (everything shows) (if all of ((if value of ({$categorie}) is (cookie)), ({$language}) is (english))) (everything shows) (if all of ((if value of ({$categorie}) is (cookie), ({$language}) is (english)))) (nothing shows)
Your 1st try was almost right:
(if all of ((if value of ({$categorie}) is (cookie)), (if value of ({$language}) is (english))) is (yes))
When sub-condition evaluates to true, it's value is turned into "yes". Otherwise it's "no". After that, resolving "main" condition is continued.
I thought about making them "true" and "false", but Symphony uses "yes" and "no" for values of checkboxes and i wanted to keep as much as possible of Symphony style to make syntax easier to learn. Do You think i should change it?
It would be best to tell user that entered syntax is invalid (so it would be much easier to test it) after he/she tries to save data source, but i have yet to find a way to implement that.
ahwayakchih -
is there a possibility you could post a basic step-by-step (with a couple of screenshots) and how one could utilize this extension? this sounds great but i'm having a hard time understanding what it is accomplishing. forgive me.
bzerangue, i found it useful when i wanted to use many data sources with page, but only some of them at a time, depending on value of URL parameters. But it also can be used to prevent SQL queries:
Example A
Let's say You have three sections: News, Photos and Places.
Each news can have photos attached, and each photo can have a place selected. We want to be able to re use photos for multiple news (maybe it is multilingual site, where each language has separate news entry, but they may want to use the same photos), so news has section link to photos section (doesn't matter if it is selectbox link, mediathek, subsection, built-in select or something else. it just matter that each news entry has list of IDs from photos section).
There's a page which shows latest news. You want to show teaser text, one photo and short info about a place (name and location, maybe with link to one of map services :), so page uses 3 data sources.
- News data source gets entries form news section and outputs
$ds-news
parameter which contains list of photo IDs, - Photos data source gets entries from photos section and outputs
$ds-photos
parameter which contains list of places IDs. It has filter by System:ID set to{$ds-news}
, - Places data source gets entries from places section. It has filter by System:ID set to
{$ds-photos}
.
When latest news don't have any photos attached, or photos don't have any places selected, SQL queries will be run anyway. They will not take much time, because database will probably optimize it enough to quickly return empty result, but it will still waste some time and CPU. To prevent that, You can add filter field to photos and places sections. After that, go to photos data source and add filter by filter field (i know it sounds strange, sorry :) and enter something like this:
(if value of ({$ds-news}) is not ())
That should prevent SQL query form being executed if there are no photos attached to any of the latest news. Almost the same will work for places data source:
(if value of ({$ds-photos}) is not ())
Example B
Now, let's say You want to build a page which shows news by selected place. Page takes one URL parameter called "place". So You build following data sources:
- place, which selects entry from Places section, has filter by name set to
{$place}
and outputs$ds-place
parameter containing value of System:ID, - photosByPlace, which selects entries from Photos section, has filter by place set to
{$ds-place}
and outputs$ds-photosbyplace
parameter containing System:ID of each photo found, - newsByPhoto, which selects entries from News section, has filter by photo set to
{$ds-photosbyplace}
.
You can configure place data source to require $place
parameter, but what if there are no photos (and thus news) mentioning that place or maybe You know people may try to look for it, but You don't want to see them unless they are logged-in? SQL queries will run anyway. But You can use filter field again.
Add filter by filter field to photosByPlace data source and use
(if all of ((if value of ({$ds-place}) is not ()), (if value of ({$cookie-username}) is not ())) is (yes))
Add filter field to News section, and then filter newsByPhoto by it
(if value of ({$ds-photosbyplace}) is not ())
Example C
Let's say that Your site is multilingual, and that You want to show some additional content for English readers. Maybe it's some contact information, but it's for English speakers only, so no point in showing it to others. Or maybe there is separate contact information for English and Gaelic, but there is no contact information for anyone else. Or maybe You want to reward Gaelic speakers, so You render some extra stuff for them. You can make data source which tries to select content every time (and then show it or not through XSLT), but You can also filter it by filter field:
(if any of (english, gealic) is ({$language}))
That will make data source run it's SQL only when value of $language
parameter is "english" or "gaelic". In any other case it will just generate empty result without a need to call database.
I hope those examples are understandable and can help despite my poor English :).
bzerangue let me know if those examples helped. It's hard for me to explain anything in English :(.
Example D
Let's say, that You have a Page which shows information about vehicles. You may want path to be like example.com/maker/type, where both maker and type are URL parameters. But different types of vehicles have different types of data. Motorcycles and cars usually contain very different set of informations. So You create 3 sections: makers, motorcycles and cars. Motorcycles and cars have section link field to makers section. There are two data sources: one which selects motorcycles and other which selects cars. Both filtered by "maker". Such setup will select both types every time. You could of course add field "type" to each section, and filter data sources by it, but that would still make both data sources build and run SQL queries. But if You add filter field instead of "type" selection field, You can filter motorcycles data source this way:
(if value of ({$type}) is (motorcycles))
and cars data source this way:
(if value of ({$type}) is (cars))
Of course You could create separate Page for each maker, and then separate page for each type of vehicle, but that's a lot of not-so-interesting work to do (even if You'll keep most of XSLT separate and just import it, to avoid duplication :).
Additionally, You can use the same $type
parameter as name of specific model of car or motorcycle. Just clone "cars" and "motorcycles" data sources, and change filter to something like:
(if value of ({$type}) is not in (cars, motorcycles))
and then additionally filter by name with {$type}
as it's value.
That will make single Page work with URLs like:
- example.com/porsche/cars
- example.com/porsche/motorcycles
- example.com/porsche/911-carrera
without too many SQL queries for every page view :).
Thank you for the examples, Marcin! I was wondering as well how to use the filter extension, but now I think I understand the possibilities. It seems to be a "powerful pre-execution filter" with two major advantages:
- it will stop the execution of a datasource if the filter fails
- it provides additional filter statements
(Please correct me if I am wrong.)
Maybe a different name like "pre-filter" or "intelligent pre-filter" would help to understand what it is doing.
ahwayakchih -
i haven't had a chance to try this out. your examples are very helpful and i'm going to try them out and let you know. again, thank you for taking the time to build this extension and for providing helpful examples for us to utilize this tool.
thanks again!
michael-e, yes, it's objective is to stop data source from executing if conditions are not met.
I don't know if "pre-filter" name will make it any better, because it is resolved only with other filters (not before them). I wanted short name, and thought "filter" will be ok. Maybe "data source optimization filter"? But that's a lot too long.
Just a better description with examples should do. Best would be one or two phrases summary (so reader is not bored before learning what this extension is about) followed by full description. Any volunteers? :).
bzerangue, i've just updated Example B to make it more useful.
I was able to use this filter to avoid a huge amount of queries! Because I only wanted to display certain information with certain categories, categories now have 561 to 1150 instead of +/- 1400 queries for all categories.
carsten, wow, that's really great! Thanks for the information :).
removed at the request of admin.
moonoo2, sorry to wrap your knuckles but please keep your discussions to a single thread. This is the second or third additional thread into which you have posted the same problem. By all means direct people to your original thread, but please do not re-post the same query in multiple threads.
Your original post: sort by system:id working nothing else does?.
If people are not responding to your initial thread, it means either people do not know the answer or you have no explained yourself fully. Posting to additional threads is not the solution.
deleted
Wow, I wish I found this sooner!
Going to have a play with it right now :)
I’m running 2.0.8RC1, and when I add the Filter: Field to a section, and then when I go to save my entry, I get the following Symphony Warning / Error …
Wrong parameter count for str_replace() An error occurred in /home/user/public_html/extensions/filterfield/fields/field.filter.php around line 166 161: if (is_array($v)) { 162: $v = implode(', ', $v); 163: } 164: $expression = str_replace($m[0], $v); 165: } 166: else $expression = str_replace($m[0], ''); 167: } 168: } 169: 170: $message = NULL; Backtrace: [:0] GenericErrorHandler::handler(); [/home/user/public_html/extensions/filterfield/fields/field.filter.php:166] str_replace(); [/home/user/public_html/symphony/lib/toolkit/class.entry.php:92] fieldFilter->checkPostFieldData(); [/home/user/public_html/symphony/content/content.publish.php:773] Entry->checkPostData(); [/home/user/public_html/symphony/content/content.publish.php:29] contentPublish->__actionEdit(); [/home/user/public_html/symphony/content/content.publish.php:38] contentPublish->__switchboard(); [/home/user/public_html/symphony/lib/toolkit/class.administrationpage.php:70] contentPublish->action(); [/home/user/public_html/symphony/lib/core/class.administration.php:88] AdministrationPage->build(); [/home/user/public_html/symphony/lib/core/class.administration.php:204] Administration->__buildPage(); [/home/user/public_html/index.php:20] Administration->display();
Have any of y’all run across this? Could any one of you give me pointers on how I can get this fixed?
The str_replace() function in PHP needs 3 parameters, what to search for, what to replace it with, and in what string to perform the search and replace.
You can see the function detail here http://php.net/str_replace
Hopefully that can help you.
Create an account or sign in to comment.
A new Extension, “Field: Filter” is now available for download. Comments and feedback can be left here but if you discover any issues, please post it on the issue tracker.