Both sides previous revisionPrevious revisionNext revision | Previous revision |
en:create:php-filters [23.09.2019 08:54] – Titles admin | en:create:php-filters [08.02.2025 22:26] (current) – admin |
---|
====== Filters and Conditional Questions (PHP Filters) ====== | ====== Filter Questions (PHP Filters) ====== |
| |
If the participant's answer to a question is to have an effect on the further course of the interview, it is a filter question. You can define filters either directly in the question ([[en:create:simple-filters|question filter]], simple variant) or in the **questionnaire** (//PHP filter//). | If the participant's answer to a question is to have an effect on the further course of the interview, it is a filter question. You can define filters either directly in the question ([[en:create:simple-filters|question filter]], simple variant) or in the **questionnaire** (//PHP filter//). |
| |
PHP filters allow much more sophisticated filters than question filters, but require the use of a little PHP program code. A warning in advance: Most project administrators that use SoSci Survey have never before written computer programming code. You'll learn some very basic knowledge about programming with PHP in this chapter. __Don't worry__: The first step is always the hardest. You'll see that it's not as hard as it may seem – and you'll be awarded by a steep learning curve. Some little frustration, you may suffer, will be compensated by a even more happy aha! | PHP filters allow much more sophisticated filters than question filters, but require handling of a little PHP program code. Most users of SoSci Survey have never worked with a programming language before. To create filter questions, you will learn some basic knowledge of programming with PHP in this chapter. __Don't worry__: The first step is always the hardest. all beginnings are difficult, but the programming of filters is absolutely feasible and the reward of the effort is a steep learning curve. Any frustrations are usually compensated for by a joyful aha experience. |
| |
**Important**: For a better understanding, we recommend the chapter [[en:create:php|Introduction to PHP]]. | **Important**: To understand this chapter, the chapter [[en:create:php|Introduction to PHP]]is strongly recommended. |
| |
**Important**: Should a filter not work as it should, please take a look into [[en:create:filter-solving|Problem solution for filters]]. | **Important**: If a filter does not work as desired, , please take a look into [[en:create:filter-solving|Problem solution for filters]]. |
| |
**Important**: SoSci Survey saves all data from a respondent. If you allow a back button, the following situation may occur: A respondent answers question A, goes back, changes a filter question, and will not be presented question A any more in the subsequent questionnaire. The answers given to question A are still in the data record – although the data tells that this respondent should not have seen question A. | |
| |
**Tip**: If you separate respondents into a control group and an experimental group ([[en:create:questions:random|Random generator]], [[en:create:randomization|Randomization]]) and present them different questionnaire pages, it may be useful to (early) use ''[[:en:create:functions:setpageorder]]'' instead of ''[[:en:create:functions:gotopage]]'': The earlier in the interview SoSci Survey knows that pages will be skipped, the better can it adapt the progress bar. | **Tip**: If the participants are divided into control and experimental groups ([[en:create:questions:random|Random generator]], [[en:create:randomization|Randomization]]) and see different questionnaire pages, then it usually makes sense to work with ''[[:en:create:functions:setpageorder]]'' instead of ''[[:en:create:functions:gotopage]]'': The earlier SoSci Survey knows in the questionnaire process that pages are being skipped, the more accurately the progress bar can be adjusted. |
| |
| Tip: PHP filters are also used in the video tutorial [[https://www.soscisurvey.de/de/screencast#extra4|Advanced Filter Questions]] |
| |
===== Example: Yes-No Filters ===== | ===== Practical Example: Yes-No Filters ===== |
| |
Before explaining filters and their function in depth, we will show you a quick-and-dirty solution for those of you who don't have the time. A Yes-No-Filter is probably the most used filter. | Before filters and their function are explained in detail, here is the solution for those who have little time. A yes-no filter is probably the most common use for filters. |
| |
**Example 1:** If a questionee answers "yes", another question is shown. | **Example 1:** If a participant answers "yes", an additional question will be displayed. |
| |
**Example 2:** If a questionee answers "no", multiple pages are skipped. | **Example 2:** If a participant answers "no", several pages are skipped. |
| |
| |
==== Preparations ==== | ==== Preparations ==== |
| |
What you need to know to implement the filter: | You need the following information for the installation of the filter: |
| |
* The ID of the variable that contains the yes-no-question | * The identifier of the variable in which the yes-no answer is stored, |
* the answer codes of this question | * the answer codes of the question and |
* the page on which the questionnaire should continue, in case the questionee answers “no” | * the identifier of the question to be displayed in the event of a "yes" (example 1) |
| * the page where it continues with a "no" (example 2) |
| |
You will find the ID of the variable in the **Variables Listing**. This could look like this: | |
| You can find the variable identifier in the variable overview . It says something like this |
| |
[PT01] Dropdown selection | [PT01] Dropdown selection |
-9 = no answer | -9 = no answer |
| |
So the ID of the variable is “PT01”, the answer code for “yes” is “1” and the code for “no” is “2”. Ideally you have configured the question to demand a complete answer (tab //Check for completion//). In this case the code -9 won't be applicable. | So the variable is called PT01, the answer code for "yes" is 1 and the code for "no" is 2. Ideally, you have determined for the filter question that the participant must answer it (check the answer tab). Then the code -9 can no longer occur |
| |
**Attention:** Should there be more variables, e.g. ''PT01_01'' and ''PT01_02'', check the question type. It is important you chose the question type "Selection" or "Dropdown Selection" if you only allow the choice of one option, __not__ "Multiple Choice". | **Attention:** Should there be more variables, e.g. ''PT01_01'' and ''PT01_02'', check the question type. It is important you chose the question type "Selection" or "Dropdown Selection" if you only allow the choice of one option, __not__ "Multiple Choice". |
| |
| |
===== Entering a PHP Code ===== | ===== Insert a PHP Code ===== |
| |
The filter should be entered as a //PHP code// when **Creating A Questionnaire**, at the exact point where the filter should be active (e.g. where the second question is shown or skipped). Simply drag-and-drop a //PHP code// from the right sight into your questionnaire page ([[::en:create:php|Introduction to PHP]]). | The filter should be entered as a //PHP code// when **Creating A Questionnaire**, at the exact point where the filter should be active (e.g. where the second question is shown or skipped). Simply drag-and-drop a //PHP code// from the right sight into your questionnaire page ([[::en:create:php|Introduction to PHP]]). |
**Important:** A PHP filter can __never__ be on the same page as the filter question (the question the answer refers to, in this case ''PT01''). SoSci Survey loads the questionnaire page by page in order to show the questionee the whole page. The moment the page with the filter question loads, the questionee cannot possibly have answered the questions - and thus the filter cannot react to the answer (''[[:en:create:functions:value|value()]]''). | **Important:** A PHP filter can __never__ be on the same page as the filter question (the question the answer refers to, in this case ''PT01''). SoSci Survey loads the questionnaire page by page in order to show the questionee the whole page. The moment the page with the filter question loads, the questionee cannot possibly have answered the questions - and thus the filter cannot react to the answer (''[[:en:create:functions:value|value()]]''). |
| |
===== Frequent Use Cases ===== | ===== Common Use Cases ===== |
| |
If you can handle the PHP function ''[[:en:create:functions:value]]'', you can implement a number of filters with it. | If you can handle the PHP function ''[[:en:create:functions:value]]'', you can implement a number of filters with it. |
| |
| |
==== Whether to Display a Question or Not ==== | ==== Show a question or not ==== |
| |
The following PHP code uses ''[[:en:create:functions:value]]'' to check whether response code ''1'' has been stored for variable ''PT01''. If this is the case, the question ''AB01'' is displayed using ''[[:en:create:functions:question|question()]]''. | The following PHP code uses ''[[:en:create:functions:value]]'' to check whether response code ''1'' has been stored for variable ''PT01''. If this is the case, the question ''AB01'' is displayed using ''[[:en:create:functions:question|question()]]''. |
==== Skip Pages ==== | ==== Skip Pages ==== |
| |
When **compiling the questionnaire**, you now select the page on which you want to continue with a "no". Enter an //identifier// for this page, e.g. "no TV" (assign an identifier for a page). | When **Assembling the Questionnaire**, you now select the page on which you want to continue with a "no". Enter an //identifier// for this page, e.g. "no TV" ([[en:glossary#page_ids|Page IDs]]). |
| |
Then go to the page where you have placed the //PHP code// element for the filter (see above). Write the following: | Then go to the page where you have placed the //PHP code// element for the filter (see above). Write the following: |
===== The Keyword IF ===== | ===== The Keyword IF ===== |
| |
Filters are programmed through IF-THEN-ELSE-relations in the element //PHP-code//. **If** and **else** are the keywords in programming language. | Filters are programmed in your questionnaire using IF-THEN-ELSE relationships in a PHP code element. In the PHP programming language, the corresponding keywords are ** if ** (IF-THEN) and ** else** (ELSE). |
| |
Following **if**, you set the condition into brackets. If this condition is complied with, the command following the condition will be executed: | After ** if ** there is a so-called condition in brackets. If the condition is met, then the command (which is in turn behind the condition) is executed: |
| |
''**if (**condition**)** demand'' | ''**if (**condition**)** demand'' |
The following example bases on a question on page 2 of the questionnaire, asking the questionee how much he earns per month. He had to choose between several categories: 1=no income, 2=up to 500$, and so on. This will be the filter question. | The following example bases on a question on page 2 of the questionnaire, asking the questionee how much he earns per month. He had to choose between several categories: 1=no income, 2=up to 500$, and so on. This will be the filter question. |
| |
It's important to know that SoSciSurvey doesn't know the questionees answer when building page 2. The server won't know this until the questionee has answered the question and pressed the “next” button (this is when the data will be sent back to the server). This is why putting filter questions and their respective filters on the same page won't work. After getting the questionees data through him pressing “next”, the server can start building page 3. | Now it is important to know that SoSci Survey - while page 2 is being created - has no idea what the respondent will answer. The page is first created in full, then displayed to the respondent. The respondent selects an option and clicks "Next". Only when "Next" is clicked is the answer to page 2 sent to the survey server and saved. Immediately afterwards, the server creates page 3 and sends it to the participant to fill out. |
| |
{{fig.filters.principle.png?nolink|Prinzipielle Funktion von Filtern durch Springen}} | {{fig.filters.principle.png?nolink|Prinzipielle Funktion von Filtern durch Springen}} |
| |
Now, what if the questions on page 3 should be skipped if any option except option 1 was chosen? (in other words: Page 3 should only be shown if the questionee chose option 1) We need to think a little further: To achieve this, the filter needs to redirect all questionees who did __not__ choose option 1 to page 4. | The key point here is that an answer from page 2 is only known to the server on page 3. Therefore, the filter for the question can only be created on page 3 at the earliest. |
| |
This is how most filters work in SoSciSurvey: You skip certain questions or whole pages. In some cases you need to cling several filters together. | But what if the questions on page 3 should only be displayed if the first option has been selected? Then you have to think outside the box: the filter redirects all respondents who have not selected the first option directly to page 4. |
| |
An example: on page 10 you show a multiple choice question with 5 car brands to choose from. About each brand, you want to ask 4 questions on 2 pages. To do so, you will need 5 filters. The first filter will be on page 11. It checks whether option 1 was chosen. If not, it will skip page 11 and 12 and redirect to page 13 (because the questions about brand 1 were spread about two pages). On page 13 the next filter kicks in: it checks whether option 2 was chosen. Then it goes on like this. | Most filters in SoSci Survey work according to this principle: you skip individual questions or entire pages. In some cases, several filters have to be added one after the other: |
| |
When the filter reaches a point where an option was actually chosen (let's say, option 3 was checked) then the filter on page 15 does not redirect but asks the questions on page 15 and 16, right until page 17 where the next filter checks if option 4 was chosen. | For example, if you show a multiple choice with 5 car brands on page 10 and want to ask 4 questions about each of the well-known brands (across 2 pages), you need 5 filters. The first filter checks on page 11 whether the first item of the multiple choice has been clicked. If not, it jumps directly to page 13 (pages 11 and 12 contain the questions about the first brand). The next filter is on page 13. If the second brand (i.e. the second item) has not been clicked, it goes directly to page 15. |
| |
| If the third mark is checked, the filter on page 15 does not respond. The questions on the page are displayed as normal and SoSci Survey waits for the respondent to click on "Next". Then page 16 is displayed with the two questions. The next filter is not until page 17: it either directs the participant directly to page 19 or not... |
| |
{{fig.filters.jump.png?nolink|Überspringen von Fragen durch Filter}} | {{fig.filters.jump.png?nolink|Überspringen von Fragen durch Filter}} |
===== Skip Pages ===== | ===== Skip Pages ===== |
| |
Back to the simple example: On page 1 of the questionnaire we ask the question AB01 (selection about the income). Our goal is to ask the questions EK01 and EK 02 only if the questionee chose option 1 in AB01. | Let's go back to the simple example: On page 1 of the questionnaire, question AB01 is asked (a choice about income). The aim is that questions EK01 and EK02 are only asked if the respondent selects the first option in question AB01. |
| |
This means also: if the questionee chooses an option greater than 2 (income up to 500$), page 3 will be skipped. | Conversely, this means: If the respondent chooses an answer option greater than 2 (income up to 500 EUR), then page 3 is skipped. |
| |
The following example describes a questionnaire with 3 pages. On page 2 a filter will check whether the questionee has selected an income greater than 500$. In this case, the rest of the page will be skipped and the questionnaire continues on page 3. | The following example describes a questionnaire with 3 pages. On page 2, it is checked whether the person has declared an income of more than 500 EUR. If not, the rest of the page is skipped and the questionnaire continues directly on page 3. |
| |
**Tip**: How to implement php in the questionnaire is fully described in the chapter [[php|Introduction to PHP]]. Essentially, to use filters you need to drag-and-drop the element //PHP-Code// (above the list of questions in the “compose questionnaire”-area) into the questionnaire. | **Tip**: How to implement php in the questionnaire is fully described in the chapter [[php|Introduction to PHP]]. Essentially, to use filters you need to drag-and-drop the element //PHP-Code// (above the list of questions in the “compose questionnaire”-area) into the questionnaire. |
==== Using as much PHP Code as Possible ==== | ==== Using as much PHP Code as Possible ==== |
| |
Usually you will try to use PHP-code only where needed – like above. Just because questionnaires can be written much quicker in PHP, this manual often uses the following form. Contentwise, the following form is identical to the above. | Normally, you will only use PHP code in the questionnaire where you need it - as above. However, because the contents of the questionnaire page can be presented so succinctly in PHP code, you will often find the following form in the instructions. In terms of content, the function is identical to the above implementation with little PHP code. |
| |
**Page 1** | **Page 1** |
===== Instruction Blocks ===== | ===== Instruction Blocks ===== |
| |
The example shows a curly bracket following the if-condition (''{''). Curly brackets in PHP summarize several functions/commands (e.g. several questions). Although there is not always more than one command following the IF-condition, we recommend that you always use the brackets: If you add another command later on and forget the brackets, you will most probably spend a long time figuring out why that error occurs. | In the example, the IF condition is followed by a curly bracket ( {). Curly brackets are used in PHP to group together several functions/commands (e.g. several questions). It is generally a good idea to put the statement(s) after an IF construction in curly brackets - if you do not use brackets and insert further commands, you will often spend a long time looking for the error. |
| |
**Tip**: Use curly brackets for every instruction block and indent the PHP-code using spaces (don't use tabs as the entry fields have problems with those). This way you won't lose the overview even if writing long passages of php. | ** Tip **: Use curly brackets for each statement block and indent the PHP code with spaces as in the example (unfortunately the input fields still have problems with tabs). This way you don't lose track of things even with more complex filters and avoid mistakes. |
| |
**Example for page 2** | **Example for page 2** |
** | ** |
| |
Tip**: The option **This question demands a complete answer** should in general be used very sparse. But as filters need to decide things upon this answer, it is recommended to use the option for filter questions. | Tip** : The option **This question demands a complete answer** should in general be used very sparse. But as filters need to decide things upon this answer, it is recommended to use the option for filter questions. |
| |
| |
The condition checks, whether the answer was equal to 1. In our words, whether the questionee has chosen “yes”. If this condition is true, page 2 will ask three questions about the internet usage (IN01 to IN03). | The condition checks, whether the answer was equal to 1. In our words, whether the questionee has chosen “yes”. If this condition is true, page 2 will ask three questions about the internet usage (IN01 to IN03). |
| |
All questionees – regardless of their answer to the filter question TF01 – will see the question AB01. Did the questionnee answer “no” to TF01, he will only see one question on page 2: AB01. Did he answer “yes”, he will see four questions in total on page 2. | All respondents – regardless of whether they have an internet connection at home or not – also receive question AB01. People without an internet connection only see this one question on page 2 – people with an internet connection see a total of 4 questions. |
| |
| |
==== Using else ==== | ==== Using else ==== |
| |
Using the command else you can ask questions that should be shown, in case the IF-condition returns “false”. In our example, we could ask, why the questionee does not have an internet connection: | By using , elseyou could also ask why you don't have a connection at home: |
| |
| |
<code php> | <code php> |
The following examples will output the same page (if the questionnee has answered “no”), because following the ''goToPage()'' command, nothing will be executed. The ''goToPage()''-command leaves the current page and will never return. | The following examples will output the same page (if the questionnee has answered “no”), because following the ''goToPage()'' command, nothing will be executed. The ''goToPage()''-command leaves the current page and will never return. |
| |
** Option 1: Jump to page “usage” if there's nothing to ask ** | ** Option 1: skip to page “usage” if there's nothing to ask ** |
<code php> | <code php> |
if (value('TF_01') == 1) { | if (value('TF_01') == 1) { |
===== The Proper ID ===== | ===== The Proper ID ===== |
| |
The example uses a selection. A simple selection will save just one value, the chosen option. This can be called with ''value()'' and the ID (e.g. TF01). | In the example, you have used a selection. A simple selection stores only a single value (namely the selected option), which value()is queried using the question identifier (eg TF01). |
| |
| However, if you use scales, text entries or multiple choice, you must use the identifier of the corresponding item (e.g. TF02_02) and not the identifier of the question. |
| |
If using scales, text entry fields or multiple choice questions, you need to use the ID of the respective item, not the question (e.g. TF01_02)! | |
| |
{{scr.filters.multiselect.png?nolink|Beispiel für eine Mehrfachauswahl TF02l}} | {{scr.filters.multiselect.png?nolink|Beispiel für eine Mehrfachauswahl TF02l}} |
{{scr.filters.varlist.checkbox.png?nolink|Variablen einer Mehrfachauswahl}} | {{scr.filters.varlist.checkbox.png?nolink|Variablen einer Mehrfachauswahl}} |
| |
You get the following display in the debug mode, if you click //next// on Page 1 (showing question TF02). In the example, the first and third item were checked. | The following display is shown in debug mode when you click Next on page 1 (where question TF02 is displayed) . In the example, the first and third items were checked. |
| |
{{scr.filters.debug.png?nolink|Debug-Information beim Testen des Fragebogens}} | {{scr.filters.debug.png?nolink|Debug-Information beim Testen des Fragebogens}} |
| |
All items of a multiple choice question will either have the value 1 (not selected) or 2 (selected). If you want to filter the questionees that use the mobile phone on page 2, you use the following PHP-code: | In a multiple choice, each item can have the value 1 (not selected) or 2 (selected). If you now want to filter on page 2 whether the respondent has a DSL connection, the PHP code looks like this: |
| |
** Filter for multiple choice selections ** | ** Filter for multiple choice selections ** |
</code> | </code> |
| |
A big drawback to multiple choice questions is the fact, that you cannot check if the questionee has answered the question as no checked items is considered a valid answer. | A major disadvantage of multiple choice is that you cannot check whether the respondent has answered it. After all, no tick can be a correct answer. |
| |
You can avoid this problem by using a 2-step-scale instead of a multiple choice selection and naming the extremes “yes” and “no”. So you will get the same values for all items (1 for no, 2 for yes) and an additional “-9”-value for items that were not answered. In the example we chose the minimum “no”, the maximum “yes” and the direction of scale as //descending//, because the “yes”-option should show on the left. | The problem can be avoided by using a 2-stage scale instead of a multiple choice. If you label the minimum with "no" and the maximum with "yes" (in the figure, the direction of the scale is descending, the orientation of the label is in the middle), you get the same value for each item as in the multiple choice (1=no, 2=yes). |
| |
{{scr.filters.example_scale.png?nolink|Variablen in einer Skala}} | {{scr.filters.example_scale.png?nolink|Variablen in einer Skala}} |
text('screenout'); // Show send-off | text('screenout'); // Show send-off |
buttonHide(); // Hide the next-button | buttonHide(); // Hide the next-button |
| setStatus('screenout'); // Note down status in the record |
pageStop(); // In case other content shows with the filter | pageStop(); // In case other content shows with the filter |
} | } |
| |
**Tip**: By repeating a filter you are able to check different variables. Using boolean operators you can check several variables in one filter ([[filter-boolean|Linking Multiple Conditions]]). | **Tip**: By repeating a filter you are able to check different variables. Using boolean operators you can check several variables in one filter ([[filter-boolean|Linking Multiple Conditions]]). |
| |
| Tip: You can also create a simple screenout without any PHP code if the screenout is triggered by a selection question. To do this, create a text in the question catalog that should be shown during the screenout. Then edit the screenout (selection) question and enter a screenout in the "Filter question" tab. There you would then have to select the text you created previously. |
| |
===== Tips about Filters / Problem Solving ===== | ===== Tips about Filters / Problem Solving ===== |
| |
Filters are very flexible tools. You can nest them if needed. You can check complex conditions. We will explain more in further chapters (see below). | Filters are an extremely flexible tool. They can even be nested if necessary or check complex conditions. More on this in further chapters (see below). |
| |
Usually filters don't work as needed on the first try. If things don't work, there are several possibilities to check for errors: | Unfortunately, filters don't always work as you would like them to. If a filter doesn't work, there are a few simple ways to track down the error: |
| |
* Check the **Variables listing** whether you have got the right variables ID. | * Check the **Variables listing** whether you have got the right variables ID. |
* [[filter-itemcount|At Least One Item Selected]] - Loops | * [[filter-itemcount|At Least One Item Selected]] - Loops |
* [[filter-items|Use Selected Items in Another Question]] - Arrays | * [[filter-items|Use Selected Items in Another Question]] - Arrays |
| |
| |