CodeDevelopr
CodeDevelopr

Reputation: 1265

Return json response for Ajax request in a basic PHP MVC

I am planning on building a lightweight simple MVC in PHP for simple projects.

I am trying to grasp a simple route of showing a View template or returning a JSON response if it is an AJAX request.

Below is a snippet I just came up with, it is all hypothetical so none of the methods actually exist yet, it is just the way I would expect them to work.

Looking at the code below and reading the comments in it, does this look like how you would probably return an AJAX request instead of a view template in a basic MVC?

/**
 * Example Controller
 */
class Test_Controller extends Core_Controller {


    function SomeAction($userId)
    {
        //GET ID from URI
        $this->request->get($userId['id']);

        // load a Model 'some' = Model Name
        $this->profile_model = $this->loadModel('some');

        // Get the Dataset from the Model
        $profileData = $this->profile_model->getProfile($userId);

        // Check if this is an AJAX request true/false
        if($this->request->isAjax()){
            //is AJAX is true then we return json instead of loading a View template
            return $this->response->json($profileData);
        }else{
            // load view file
            $this->view->load('userProfile', $profileData);
        }
    }

Upvotes: 2

Views: 3856

Answers (2)

FtDRbwLXw6
FtDRbwLXw6

Reputation: 28929

Your method seems pretty intuitive, and probably very close to how I would do it, but with the exception that I wouldn't respond with JSON to every AJAX request. I would only respond with JSON if:

  • JSON is requested in the URI (ex. /users/1/json or /users/1.json) or
  • JSON is requested via the Accepts HTML header

This allows you to be more flexible/future-proof. If at some point in the future you decide that you want to serve up some data for an AJAX request in XML format, rather than JSON, all you have to do is specify it for that one request (ex. /users/1.xml). If you were previously serving up JSON for every AJAX request, you would have to modify all AJAX requests to explicitly ask for JSON in order to accomodate this one XML request, and that's not very developer-friendly. :-)

Upvotes: 2

devdRew
devdRew

Reputation: 4571

I prefer this way in your method:

public function executeSomeAction($request)
{
    if ($request->isXmlHttpRequest())
    {
         $this->actAsJsonResponse(); // here you set headers and other things
         /**
          * $code - 0, if all's fine, other on error
          * $message - verbal message that describe the error, or success
          * $extra - any data to send.
          */
         return $this->prepareJsonResponse($code, $message, $extra);
    }
}

As a result in my framework I have something like:

public function executeSave(\Lighty\Request\Request $request)
{
    $this->actAsJsonResponse();
    $p      = \Lighty\Model\ParticipantSqlAdapter::getInstance()->findById($this->getUser()->getIdParticipant());
    $data   = $request->get('profile', \Lighty\Request\Request::POST, array());
    if (count($data))
    {
        $form = new \Form\Profile(array(
            'default'   => array_merge($p->getAccount()->getArray(), $p->getArray(), $data),
        ));
        if ($form->save($p))
        {
            if (isset($data['tags']))
            {
                $tags = explode(',', $data['tags']);
                array_trim($tags);
                $tags = array_unique($tags);
                $data['tags'] = implode(', ', $tags);
                unset($tags);
            }

            $this->prepareMetaResponse(0, 'Your profile saved successfully', array('updated' => $data));
        }
        else
        {
            $this->prepareMetaResponse(1, 'Passed data is invalid', array('error' => $form->getErrors()));
        }
    }
    else
    {
        $this->prepareMetaResponse(2, 'Not enough data passed');
    }
}

Then you simplify processing request on client side:

if (response.code == 0) {
    // do whatever you need to, on success
} else {
    alert(response.code + ' ' + response.message);
}

Hope that helps.

Upvotes: 2

Related Questions