======  Items in eine andere Frage übernehmen ======

Gelegentlich soll eine Frage nicht alle Items anzeigen, sondern nur solche, die in einer anderen Frage vorher ausgewählt wurden. Und eventuell soll die Anzahl der Items auch noch beschränkt werden.

Dieses Kapitel erklärt, wie man Items in eine andere Frage übernimmt. Normalerweise genügen dafür 2-3 Zeile PHP-Code. Falls Sie bisher noch keinen PHP-Code verwendet haben, lesen Sie bitte zunächst die [[php|Einführung in PHP-Code]].


===== Aufgabenstellung 1 =====

Als Beispiel für dieses Kapitel wird die folgende Frage (TF04) verwendet:

{{scr.filter-itemcount.png?nolink|Filterfrage mit mehreren Items}}

In folgender Frage (TF05) sollen nur die Medien zur Auswahl stehen, die der Befragte mindestens einmal im Monat nutzt.

**Tipp:** Es ist wichtig, dass beide Fragen dieselben Items mit derselben Kennung enthalten. Dies erzielen Sie am einfachsten, indem Sie die Frage kopieren (Funktion //Frage duplizieren// oben in der Frage) und anschließend in der Kopie den //Frage-Typ// und ggf. die Texte ändern.

{{scr.filter-items.selection.png?nolink|Auswahlfrage mit allen Items}}

Ziel ist es nun, dass die zweite Frage nur die Medien (Items) zu Auswahl zeigt, die in der ersten Frage eine Bewertung von mindestens 2 erhalten haben.


==== Die kompakte Lösung ====

Die Funktion ''[[:de:create:functions:getitems|getItems()]]'' erstellt Ihnen eine Liste ([[array|Array]]) jener Items, die mindestens (min) einmal im Monat genutzt werden (Ausprägung 2). Diese Liste übergeben Sie einfach der Funktion [[:de:create:functions:question|question()]] -- aber natürlich nur dann, wenn sie mindestens ein Element enthält.

Damit der PHP-Code funktioniert, muss die Frage TF04 auf einer vorhergehenden Seite im Fragebogen gestellt worden sein.

<code php>
$medien = getItems('TF04', 'min', 2);
if (count($medien) > 0) {
  question('TF05', $medien);
}
</code>

Die weitere Anleitung beschreibt, wie Sie mit Arrays im Detail arbeiten. Dies ist vor allem dann interessant, wenn ''getItems()'' einmal nicht weiterhilft.


==== Der Lange Weg ====

Die Funktion ''getItems()'' erstellt ein [[array|Array]] -- das kann man auch zu Fuß erledigen. Man muss ja nur ein Array erstellen, in dem alle Item-Kennungen stehen, die in der zweiten Frage auftauchen sollen. Das funktioniert wie folgt.

<code php>
$itemliste = array(); // Eine leere Liste erstellen
$anzahl_items = 6; // 6 Items überprüfen
$frage = 'TF04';

for ($i=1; $i<=$anzahl_items; $i++) { // Durchzählen von 1 bis 6
  $kennung = $frage.'_'.$i; // Ergibt z.B. TF_04_1
  // Hat das Item einen Wert von mindestens 2?
  if (value($kennung) >= 2) {
    $itemliste[] = $i;
  }
}
// Nur zur Information
html( '<p>'. count($itemliste).' relevante Items: '. implode(', ', $itemliste). '</p>' );
// Weiter zur nächsten Seite, wenn nichts genutzt
if (count($itemliste) == 0) {
  goToPage('next');
}
// Zweite Frage mit diesen Items stellen
question('TF05', $itemliste);
</code>

Bei der Programmierung solcher Filter sollte man nicht vergessen, dass vielleicht gar kein Item ausgewählt wird. Deshalb wird der Teilnehmer im obigen Beispiel direkt zur nächsten Seite weitergeleitet, wenn er kein Medium wenigstens einmal im Monat nutzt.

Für das obige Beispiel könnte man auf Seite 1 folgende Angaben machen:

{{scr.filter-items.example.png?nolink|Mögliche Antworten in der Filterfrage}}

Fernsehen, Internet und der Telegraph erfüllen also nicht die Voraussetzung, dass sie mindestens einmal im Monat genutzt werden. Dann würde Seite 2 so aussehen:

{{scr.filter-items.result1.png?nolink|Auswahl mit gefilterten Items}}

===== Aufgabenstellung 2 =====

Nun sollen Polaritätenprofile für die einzelnen Medien erfragt werden. Allerdings nur für solche Medien, die der Befragte mindestens einmal pro Monat nutzt. Außerdem sollen maximal 2 Polprofile abgefragt werden. Falls der Befragte mehr Medien nutzt, sollen zufällig zwei ausgewählt werden.

Grundlage sind 6 gleichartige Fragen (TF06 bis TF11), in denen lediglich der Fragetext variiert. In der ersten Frage steht dort "Tageszeitung", in der nächsten "Radio" u.s.w. Die Frage wird einmal erstellt, anschließend fünf mal kopiert und abschließend Beschreibung und Fragetext geändert.

{{scr.filter-items.questions.png?nolink|Basis für gleichartige Fragen}}

Wie man eine Liste der genutzten Medien erstellt, ist oben bereits ausführlich beschrieben.

<code php>
// Variante A: Bequem
$itemliste = getItems('TF04', 'min', 2); // Liste der relevanten Items
</code>

<code php>
// Variante B: Zu Fuß
$itemliste = array(); // Eine leere Liste erstellen
$anzahl_items = 6; // 6 Items überprüfen
$frage = 'TF04';

for ($i=1; $i<=$anzahl_items; $i++) {
  $kennung = $frage.'_'.$i; // Ergibt z.B. TF_04_1
  if (value($kennung) >= 2) {
    $itemliste[] = $i;
  }
}
</code>

Falls die Liste mehr als zwei Einträge hat, müssen 2 Einträge zufällig ausgewählt werden. Um das zu erreichen könnte man die Liste mischen und anschließend die beiden ersten Einträge in ein neues Array kopieren:

<code php>
// ...
// Fortsetzung Variante I
if (count($itemliste) > 2) {
  shuffle($itemliste);
  $neue_liste = array();
  $neue_liste[] = $itemliste[0]; // Kopiert Element 0
  $neue_liste[] = $itemliste[1]; // Kopiert Element 1
} else {
  $neue_liste = $itemliste; // Sonst die Liste wie gehabt verwenden
}</code>

Man kann sich das Umkopieren in eine neue Liste auch sparen, die Liste einfach nur mischen und nachher nur die ersten beiden Einträge verwenden.

<code php>
// ...
// Fortsetzung Variante II
shuffle($itemliste);
</code>

Jetzt müssen nur noch die entsprechenden Fragen gestellt werden. Auch das funktioniert wieder am schnellsten mit Hilfe eines Arrays. Man hat die Möglichkeit, in einem Array anzugeben, welcher Eintrag welchen Index erhält. Dazu wird ein Array wie folgt erstellt: Es wird jeweils der Index angegeben, dann ein Gleichheitszeichen und ein größer-als-Zeichen (''%%=>%%'') und dann erst der eigentliche Eintrag. Das Ergebnis wird dann als assoziatives Array bezeichnet, während die "normalen" Arrays indiziert sind.

<code php>
// ...
// Fortsetzung
$fragen = array(
  1 => 'TF06',
  2 => 'TF07',
  3 => 'TF08',
  4 => 'TF09',
  5 => 'TF10',
  6 => 'TF11'
);
</code>

In diesem Array beginnen die Indizes nun nicht mit 0, sondern mit 1. Das Array sieht aus wie folgt:

^Index| 1 | 2 | 3 | 4 | 5 | 6 |
^Wert|TF_06|TF_07|TF_08|TF_09|TF_10|TF_11|

Mit ''$fragen[2]'' erhält man jetzt die Kennung der Frage, die zu Item 2 ("Radio") gehört, nämlich 'TF07'. So kann man nun ganz einfach die Fragen zu den genutzten Medien stellen:

<code php>
// ...
// Fortsetzung
$anzahl = count($itemliste); // So viele Elemente können erfragt werden
if ($anzahl == 0) {
  goToPage('next'); // Nichts genutzt? Dann gleich weiter!
}
if ($anzahl > 2)  {
  $anzahl = 2; // Maximal zwei Polprofile abfragen
}
for ($i=0; $i<$anzahl; $i++) {
  $item_kenn = $itemliste[$i]; // Einer der genutzten Dienste (1 bis 6)
  $frage_kenn = $fragen[$item_kenn];
  question($frage_kenn);  // Frage stellen
}
</code>

Die Schleife stellt nur maximal ''$anzahl'' Fragen. Vorher wird begrenzt, dass ''$anzahl'' immer maximal 2 sein kann. Gleichzeitig kann die Anzahl nie größer sein als die Anzahl der genutzten Medien (also der Listenlänge).

Der vollständige Code für dieses Beispiel sieht so aus:

<code php>
$itemliste = getItems('TF04', 'min', 2);  // Relevante Items ermitteln
shuffle($itemliste); // Liste mischen
// Fragen zu den Items definieren
$fragen = array(
  1 => 'TF06',
  2 => 'TF07',
  3 => 'TF08',
  4 => 'TF09',
  5 => 'TF10',
  6 => 'TF11'
);
$anzahl = count($itemliste); // So viele Elemente können erfragt werden
if ($anzahl == 0) {
  goToPage('next'); // Nichts genutzt? Dann gleich weiter!
}
if ($anzahl > 2) {
  $anzahl = 2; // Maximal zwei Polprofile abfragen
}
for ($i=0; $i<$anzahl; $i++) {
  $item_kenn = $itemliste[$i]; // Einer der genutzten Dienste (1 bis 6)
  $frage_kenn = $fragen[$item_kenn];  // Die entspr. Frage
  question($frage_kenn);  // Frage stellen
}
</code>

Im Fragebogen könnte das dann so aussehen:

{{scr.filter-items.example.png?nolink|Mögliche Antworten in der Filterfrage}}

Seite 2 zeigt zufällig die Fragen für Tageszeitung, Radio oder Videokonferenz. Beachten Sie, dass die Reihenfolge der Fragen eine andere sein kann als die der Items (oben).

{{scr.filter-items.result2.png?nolink|Nur relevante Fragen anzeigen}}

===== Aufgabenstellung 3 =====

Manchmal wird die Nutzung in unterschiedlichen Fragen erhoben. Zum Beispiel fragt (Auswahl-)Frage NU01 nach der Nutzung von Weblogs, NU02 nach der Nutzung von Podcasts und NU03 nach Wikis.

Nun sollen in der Frage TF13 immer die Items 1 bis 3 gefragt werden. Die Items 4, 5 und 6 sollen nur gefragt werden, wenn der entsprechende Dienst genutzt wird. Das ist nach dieser Anleitung freilich überhaupt kein Problem mehr:

<code php>
// Auf Seite 1 werden zunächst die drei Fragen gestellt
question('NU01'); // Nutzen Sie Weblogs? (1=nein, 2=ja)
question('NU02'); // Nutzen Sie Podcasts? (1=nein, 2=ja)
question('NU03'); // Verwendung von Wikis - Item 2 ist Nutzung // Werte: 1=nie 2=selten 3=häufig
</code>

<code php>
// Auf Seite 2 wird eine Item-Liste erzeugt und abgefragt
$items = array(1,2,3); // Items 1-3 werden immer gefragt
if (value('NU01') == 2) {
  $items[] = 4; // Weblogs genutzt => Item 4
}
if (value('NU02') == 2) {
  $items[] = 5; // Podcasts genutzt => Item 5
}
if (value('NU03_02') >= 2) {
  $items[] = 6; // Wikis min. selten => Item 6
}
// Zu guter Letzt die Frage stellen
question('TF13', $items);
</code>

===== Aufgabenstellung 4 =====

Fast schon trivial mutet der Fall an, dass die ausgewählten Items aus einer anderen Frage übernommen werden sollen -- und zusätzlich soll noch eine Option "Sonstiges" angezeigt werden.

Dazu legt man in der zweiten Fragen (z.B. TF05) nach den Items aus der Filterfrage (TF04) noch ein weiteres Item "Sonstiges" an. Das folgende Beispiel geht davon aus, dass dieses Item die Kennung 13 hat. Nun ermittelt man die ausgewählten Items und hängt an die Liste noch die Nummer 13 an. Dafür wird einfach eine leere eckige Klammern (''[]'') verwendet -- alternativ könnte man auch den PHP-Befehl ''[[http://php.net/manual/de/function.array-push.php|array_push()]]'' dazu verwenden.

<code php>
$auswahl = getItems('TF04'); // Ausgewählte Items ermitteln
$auswahl[] = 13; // Die Zahl 13 an die Liste anhängen
question('AF05', $auswahl); // Die Folgefrage inkl. Item 13 anzeigen
</code>

Damit dieser Filter funktioniert, muss man die Kennung des zusätzlichen Items angeben. Natürlich könnte man auch zunächst ermitteln, welche Items in der zweiten, nicht aber in der ersten Frage vorhanden sind. Die Funktion ''[[http://de.php.net/manual/de/function.array-diff.php|array_diff()]]'' liefert eine Liste genau solcher Listenelemente und mit der Funktion ''[[http://de.php.net/manual/de/function.array-merge.php|array_merge()]]'' lassen sich die Listen anschließend kombinieren.

<code php>
// Zusätzliche Items ermitteln
$items1 = getItems('TF04', 'all'); // Alle Items der Frage 1 auflisten
$items2 = getItems('TF05', 'all'); // Alle Items der Frage 2 auflisten
$added = array_diff($items2, $items1); // Items, die in Frage 2 vorkommen, nicht aber in Frage 1

$auswahl = getItems('TF04'); // Ausgewählte Items ermitteln
$auswahl = array_merge($auswahl, $added); // Zusätzliche Items an die Liste anhängen
question('AF05', $auswahl); // Die Folgefrage inkl. zusätzlicher Items anzeigen
</code>