6

I'm developing custom component and I use Ajax for calling various tasks via controller.

I've one form, where user inputs data which should get validated before database transaction. I'm using JTable for interacting with database.

There are two ways to have Server-side validation:

1) Using Model by extending JModelForm and override validate() method of that form which can return a messages to JResponseJSon object in controller.

2) Overriding JTable's check() method which will check the data (and return messages to JResponseJson Object) before it get's store in database.

Both of the above methods validate data at Server-side. My question would be, what is the best way out of above two considering I'm using JResponseJson object to deal with my application in AJAX way.

Here is my controller Code:

/**
 * Overrided Method to save a record.
 *
 * @return  boolean  True if successful, false otherwise.
 *
 * @since   12.2
 */
public function save()
{
    // Check for request forgeries.
    JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

    $app        = JFactory::getApplication();
    $model      = $this->getModel();
    $helpdesk   = $model->getTable();
    $data       = $this->input->post->get('jform', array(), 'array');
    $key        = $helpdesk->getKeyName();
    $recordId   = $this->input->getInt($key);
    // Populate the row id from the session.
    $data[$key] = $recordId;

    // Access check.
    if (!$this->allowSave($data, $key))
    {
        $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToItemAppend()), JText::_('COM_HELPDESK_SAVE_ACCESS_ERROR'), 'warning');

        return FALSE;
    }

    $response = $model->save($data);

    // Attempt to save the data.
    if ($response === false)
    {
        echo new JResponseJson($response, NULL, true);
        $app->close();
    }

    $this->postSaveHook($model, $data);

    if ($model->getState('request.new') == '1')
    {
        $recordId = (int) $model->getState('request.id');
        // Set Success Message for New Request.
        echo new JResponseJson(NULL, JText::sprintf('COM_HELPDESK_REQUEST_NEW_SAVE_SUCCESS', $recordId));
        $app->close();
    }
    else
    {
        // Set Success Message for Existing Request.
        echo new JResponseJson(NULL, JText::sprintf('COM_HELPDESK_REQUEST_EDIT_SAVE_SUCCESS', $recordId));
        $app->close();
    }
}

Here is my JTable's check method code:

    /**
     * Overloaded check function
     *
     * @return  boolean  True on success, false on failure
     *
     * @see JTable::check
     * @since 1.5
     */
    public function check()
    {
        $app  = JFactory::getApplication();
        $type = 'error';
        $flag = true;

        if (trim($this->subject) == '')
        {
            $app->enqueueMessage(JText::_('COM_HELPDESK_SUBJECT_ERROR'), $type);
            $flag = false;
        }

        if (trim($this->description) == '')
        {
            $app->enqueueMessage(JText::_('COM_HELPDESK_DESCRIPTION_ERROR'), $type);
            $flag = false;
        }

        if ($this->priority == 0)
        {
            $app->enqueueMessage(JText::_('COM_HELPDESK_PRIORITY_ERROR'), $type);
            $flag = false;
        }

        return $flag;
    }
2
  • I'm not sure what the question is exactly, but Personally I would suggest avoiding any Ajax specific logic in either the model or the table. Instead keep all the Ajax logic in an AJax controller and dispatch to the other parts of your extension via that controller. That way you can Ajaxify all the logic in your extension without duplication. Commented May 6, 2015 at 6:31
  • Ok for more clarity, I've added my code to the question. My save method first checks the data from JTable's check method if it is true then, it passes to my controller which get's displayed on front end. Do you think it is correct way? Commented May 6, 2015 at 6:39

1 Answer 1

4

As previously suggested, it is better to manage errors without introducing conditionals into business logic.

You can just throw exceptions and catch them at the highest level, where you can encode to Json (and avoid a redirection).

Tip: One nasty aspect, even though you close app, any extension can add HTML to your Json data output, namenly Jomsocial. A trick, a valid Json output can be wrapped with custom tagging to "extract" it inside $.ajax from text.

3
  • I referred to following file /administrator/components/com_contact/tables/contact.php. If you scroll to overrided check() method. You would see number of conditional statements are present. They use $this->setError('My Error'). Unfortunately JError is deprecated. I couldn't find a way to pass these messages to my json object in Controller. Hence, I used $app->enquemessage('My Message'); Commented May 6, 2015 at 10:19
  • These methods are not created for single-page applications. For example, enqueued errors cannot be rendered and removed from an ajax call. At the end, you have to define your method for your JavaScript app.
    – Anibal
    Commented May 6, 2015 at 10:28
  • Thank you. I have edited my code and thrown an error instead of enquemessage. Commented May 6, 2015 at 11:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.