Build your own step

The Generic PHP Steptype is the most flexible in SoPHIE. Whenever one of the other Steptypes is not sufficient for the experimenters demand, this Steptype can be used. There are almost no limitations on what can be done.

The flipside of using the Generic PHP is that you have to take care of the most things on your own. Therefore, predefined steptypes should be used for standard tasks, as design, validation and much more are already done.

Forms

To create a valid form on our online experiment platform, a few requirements need to be considered. At first a context checksum is required to guarantee the location of a participant. In addition the action parameter of the form is set through the context API, to specify where the form-data is submitted. On the example below you can see the minimum requirements described here.

Requirements

To have an idea of what you can do in a Generic PHP step, see the example hereafter. This is a form including eleven input fields. These fields are representing one football player each and the participant is asked to rate the players performance during the match.

Form Example

To get to this result you can see the code below. From the vast amount of code you can already tell that this is not the best way to generate such a form. Preferably you should use a for loop in combination with some if-conditions to adjust for the different cases.

<form action="<?= $context->getFrontUrl(); ?>" method="post">

  <?php if (!empty($message)): ?>
    <div class="alert alert-danger">
      <?= $message; ?>
    </div>
  <?php endif; ?>
  
<div class="container">
  <div class="row">
    <div class="footballPerformanceHeadline">Football - Player Performance Evaluation</div>
    <div>
      Please select a value between 1 (very bad) and 10 (very good) for the individual player performance.
    </div>
  </div>
  <div class="row">
    <div class="col-xs-3 col-xs-offset-3">
      <div>
        Nr. 11
      </div>
      <div>
        <input class="form-control" size="3" name="nr11">
      </div>
    </div>
    <div class="col-xs-3">
      <div>
        Nr. 10
      </div>
      <div>
        <input class="form-control" size="3" name="nr10">
      </div>
    </div>
  </div>
  
  <div class="row">
    <div class="col-xs-3">
      <div>
        Nr. 9
      </div>
      <div>
        <input class="form-control" size="3" name="nr9">
      </div>
    </div>
    <div class="col-xs-3">
      <div>
        Nr. 8
      </div>
      <div>
        <input class="form-control" size="3" name="nr8">
      </div>
    </div>
    <div class="col-xs-3">
      <div>
        Nr. 7
      </div>
      <div>
        <input class="form-control" size="3" name="nr7">
      </div>
    </div>
    <div class="col-xs-3">
      <div>
        Nr. 6
      </div>
      <div>
        <input class="form-control" size="3" name="nr6">
      </div>
    </div>
  </div>
  
    <div class="row">
      <div class="col-xs-3">
        <div>
          Nr. 5
        </div>
        <div>
          <input class="form-control" size="3" name="nr5">
        </div>
      </div>
      <div class="col-xs-3">
        <div>
          Nr. 4
        </div>
        <div>
          <input class="form-control" size="3" name="nr4">
        </div>
      </div>
      <div class="col-xs-3">
        <div>
          Nr. 3
        </div>
        <div>
          <input class="form-control" size="3" name="nr3">
        </div>
      </div>
      <div class="col-xs-3">
        <div>
          Nr. 2
        </div>
        <div>
          <input class="form-control" size="3" name="nr2">
        </div>
      </div>
    </div>
  
    <div class="row">
      <div class="col-xs-4 col-xs-offset-4">
        <div>
          Nr. 1
        </div>
        <div>
          <input class="form-control" size="3" name="nr1">
        </div>
      </div>
    </div>  
  </div>


  <input type="submit" value="Submit" class="btn btn-default">
  <input type="hidden" name="contextChecksum" value="<?= $context->getChecksum(); ?>">
</form>

Validation

Validating for correct inputs is a crucial part of setting up an experiment. This is necessary for automated data analysis or to conduct sessions without problems. How to validate given data depends on the requirements for the inputs and this is why there is no general solution for data validation in forms.

To stick with the example given in the section above the requirements for a correct input are valid integers between 1 and 10, including the boundaries. The validation is processed in the process tab of the step. By using the request API the submitted parameters are accessed and saved into an array. Afterwards each input is validated individually by checking, whether the input is not empty and still including anything else but numbers. In addition we check, if the input is smaller than 0 or larger than 10 and we make sure that the input is not empty

$inputArray = array();
$view = $api->get('view');

for ($i = 1; $i <= 11; $i++)
{
  $inputArray[] = $requestApi->getParam('nr' .  $i, '');
}

$variableApi->setPSL('array', $inputArray);

foreach ($inputArray as $input)
{
  if((!empty($input) && !ctype_digit($input)) || $input < 0 || $input > 10 || empty($input))
  {
    $view->set('message', 'At least one of your ratings has not been correct.');
    return false;
  }
}

return true;

Furthermore, the information of a wrong input is displayed to a participant, whenever a validation fails. To accomplish that the view API is used, to set the 'message' variable to the required error message. The return value false as a result guarantees that the participant is not able to proceed without valid inputs.

<?php if (!empty($message)): ?>
    <div class="alert alert-danger">
      <?= $message; ?>
    </div>
<?php endif; ?>

Wrong Input

Escaping

In many experiments participant inputs are displayed to their partners. Although the data should have been validated before, an information output should always be escaped. This means that every input will be shown as plain text, instead of potentially interpreted code. The reason for this approach is code that might eventually be harmful. Participants could enter code instead of number inputs and try to access your database or utilize the server performance to full capacity.

Below you see an example, where escaping is used. The php function htmlentities escapes every potentially harmful code and converts it to HTML entities.

Escaping Code

The output of the code is displayed here. It shows the entered input and ignores any functionality of the script tags. In case you are not sure, whether to use escaping or not, you should use it.

Escaping Output

To give you an example of how the same code looks without escaping have a look at the next screenshot.

No Escaping Code

The exact same code without the htmlentities function leads to a totally different result. The JavaScript code is executed and for this example the border of the step content is changed. More harmful than minor changes to your CSS might be ajax requests, that utilize 100% of your server performance, as this prevents the other participants from proceeding.

No Escaping Output