Search code examples
joomla

Do a server side validation using multiple form fields


Overriding the JFormRule function "test", I need to implement a server side validation of a value of the form field against the value of another form field in the same form. I am struggling with a probably very easy thing: How can I get the value of this other form field?

Here's an extract of my form definition easyfpu.xml:

<?xml version="1.0" encoding="utf-8"?>
<form addrulepath="/administrator/components/com_easyfpu/models/rules">
    <fieldset
        name="details"
        label="COM_EASYFPU_EASYFPU_DETAILS"
    >
        <field
            name="id"
            type="hidden"
        />
        <field
            name="calories"
            type="text"
            label="COM_EASYFPU_EASYFPU_CALORIES_LABEL"
            description="COM_EASYFPU_EASYFPU_CALORIES_DESC"
            size="40"
            class="inputbox validate-numfracpos"
            validate="numfracpos"
            required="true"
            hint="COM_EASYFPU_EASYFPU_CALORIES_HINT"
            message="COM_EASYFPU_EASYFPU_ERRMSG_NUMBER_FRAC"
        />
        <field
            name="carbs"
            type="text"
            label="COM_EASYFPU_EASYFPU_CARBS_LABEL"
            description="COM_EASYFPU_EASYFPU_CARBS_DESC"
            size="40"
            class="inputbox validate-numfracpos"
            validate="carbs"
            required="true"
            hint="COM_EASYFPU_EASYFPU_CARBS_HINT"
            message="COM_EASYFPU_EASYFPU_ERRMSG_NUMBER_FRAC"
        />
    </fieldset>
</form>

The value of the "carbs" field needs to be assessed against the value of the "calories" field. Here's my test routine "carbs.php":

class JFormRuleCarbs extends JFormRule
{
    public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
    {
        // Check if value is numeric
        if (!is_numeric($value)) {
            $element->attributes()->message = JText::_('COM_EASYFPU_EASYFPU_ERRMSG_NUMBER_FRAC');
            return false;
        }

        // Check if calories from carbs do not exceed total calories (1g carbs has 4 kcal)
        $caloriesFromCarbs = $value * 4;
        $totalCalories = $form->getValue('calories');

        if ($caloriesFromCarbs > $totalCalories) {
            $element->attributes()->message = JText::_('COM_EASYFPU_EASYFPU_ERRMSG_TOOMUCHCARBS');
            return false;
        }

        return true;
    }
}

Unfortunately the code $totalCalories = $form->getValue('calories'); won't return anything, probably because it's part of a fieldset. How can I get the value of this field within this test routine?


Solution

  • Solved!

    The $form variable of the test function is not yet filled with the data from the form to be stored when the test function is called. Makes sense, as otherwise the potential errors you want to exclude by performing the test would already be stored.

    Retrieve the required form value from the $input variable instead, and all is set! Here's the correct code:

    ​class JFormRuleCarbs extends JFormRule
    {
        public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
        {
            // Check if value is numeric
            if (!is_numeric($value)) {
                $element->attributes()->message = JText::_('COM_EASYFPU_EASYFPU_ERRMSG_NUMBER_FRAC');
                return false;
            }
            // Check if calories from carbs do not exceed total calories (1g carbs has 4 kcal)
            $caloriesFromCarbs = $value * 4;
            $totalCalories = $input->get('calories', 0); // <-- THIS IS HOW IT WORKS!
            if ($caloriesFromCarbs > $totalCalories) {
                $element->attributes()->message = JText::_('COM_EASYFPU_EASYFPU_ERRMSG_TOOMUCHCARBS');
                return false;
            }
            return true;
        }
    }