We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

AJax call to controller getting HTTP response from model->afterSave() rather than \Phalcon\Http\Response();

Hello,

I am making an Ajax call to a controller/action on form submission. The controller action does basic validation and saves the content to the database.

    public function indexAction()
    {
        $form = new ContactsForm();
        $this->view->disable();
        $message = "Oops! Something went wrong. Please try again later.";

        $response = new \Phalcon\Http\Response();
        $response->setStatusCode(400, "Bad Request");

        if ($this->request->isPost() && $this->request->isAjax()) {

            $params = array(
                'name' => 'emailFooter',
                'email' => $this->request->getPost('email'),
                'businessSize' => 'N/A'
            );

            if ($form->isValid($params) != false) {

                $user = new Contacts();

                $user->assign($params);

                if ($user->save()) { // Here is where a network call is made in model->afterSave()
                    $message = "Thanks - We'll let you know when the product is available!";
                    $response->setStatusCode(200);
                }

            } else {
                $message = $form->getMessages()[0]->getMessage();
            }
        }

        $response->setJsonContent($message);
        $response->send();
        exit;
    }

The issues comes when I call $user->save() because that model has an afterSave() method that will send an email to the user via a API request to AWS SES. This means that instead of me returning the explicit message/status I want the javascsript always gets the response from email API network call instead.

    /**
     * Send a confirmation e-mail to the user
     */
    public function afterSave()
    {
        // Get first name if possible
        $nameParts = explode(" ", $this->name);
        $this->getDI()
            ->getMail()
            ->send(array(
            $this->email => $this->name
        ), "Welcome", 'general-submission', array("name" => $nameParts[0]));
    }

Is there anyway to have Phalcon/Ajax ignore the HTTP response of the AWS mail API call so I can explicitely return what I want?

edited Jul '16

You're not clear whenever you want to explicitly return response data OR you'd prefer to return the actual response of the API remote call happening in your model afterSave() method?

I want the javascsript always gets the response from email API network call instead.

So, AJAX calls your indexAction and that action should return response from remote endpoint / API? In that case, you need to put into session response which is now executing in your afterSave() method. That way, after mail is sent, and you have response from remote endpoint, you put it in either in a regular session or temporary in persistent session storage, and then read that data from your controller and return it in Response object as regular to the AJAX client/browser.

Also, some comments for your code:

$response = new \Phalcon\Http\Response(); //here you don't need new instance as response is already instantiated by services container and you can access it via $this->response...
$response->setStatusCode(400, "Bad Request"); //first numeric argument is enough, you don't need to specify string message

$response->setJsonContent($message);
$this->response->setContentType('application/json');  // prior to 2.1.x PhalconPHP you need to set content type HTTP header to application/json
$response->send();
exit; //do not kill stack here, it can cause you issues and unexpected behaviour

Sorry I wasn't more clear. I don't want my ajax call to get the response from the API endpoint. I want to be able to specify exactly what it gets back in the controller itself by setting the response body/code. But as soon as the API response comes back from the afterSave() method that appears to be what is returned to the calling javascript even though I haven't sent the response from the controller yet or sent it.

I'm not sure how to not have that response sent back from the afterSave() method.

edited Jul '16

Well, in that case your response object gets returned before your logic. That's odd since your afterSave() method does not return value (void). Does that happen only via AJAX/JS calls, have you tried to hit indexAction via plain GET w/o XMLHttpRequest?

I believe your validation fails i.e. your response is empty here:

$response->setJsonContent($message); // do var_dump of $message here and exit it to see raw result
$response->send();