Skip to navigation

How To Send JSON Responses with Concrete5.7

Written by and published on

The traditional way to send JSON with Concrete5 seems to be echoing it out in the controller and then exiting the script, like so:

<?php
public function view() {
  // Error handling and validation ignored here
  // to keep the example simple. Also, assuming that
  // we don't want to handle GET requests.
  if ( $this->isPost() ) {
    $data = $this->getResult( $this->post( 'query' ) );
    $json = json_encode( $data );
    header( 'Content-Type: application/json' );
    echo $json;
    exit;
  }
}

This works, but it’s not very elegant. In Concrete5.7 you have two other options.

Option 1: Ajax Service

The first one is to use the Ajax Service:

<?php
public function view() {
  if ( $this->isPost() ) {
    $data = $this->getData( $this->post( 'query' ) );
    if ( count( $data ) > 0 ) {
      $this->sendJson( $data );
    }
    // Errors must be plain text
    $error = 'Something went wrong!';
    $this->sendJson( $error, 'error' );
    // The Ajax Service kills the script, so no need to exit here
  }
}

public function sendJson( $data, $error = null )
{
  // This creates a new \Concrete\Core\Http\Service\Ajax
  $ajax = Core::make( 'helper/ajax' );
  // Simplistic assumption for this example
  if ( !$error ) {
    $ajax->sendResult($data);
  }
  $ajax->sendError($data);

}

The Ajax service takes care of encoding the data and sending the proper HTTP header for JSON. In case of an error, you can give it \Concrete\Core\Error\Errorobject and it will call its outputJSON() method to get the proper output, although in that case it doesn’t set the correct mime type header (as of Concrete5 7.5.6).

Option 2: Custom Response

The drawback with the Ajax Service is that it will always use HTTP status code 200 for success and code 400 for errors. Also, unless you use the Error object it sends errors as plain text. If that doesn’t bother you, it’s a good solution.

If, however, you want more control over the HTTP headers or want your errors to be descriptive JSON, you need to craft your own response, which is almost as easy as using the Ajax Service.

<?php
use Response;

// ....

public function view() {
  if ( $this->isPost() ) {
    $data = $this->getData( $this->post( 'query' ) );
    if ( count( $data ) > 0 ) {
      // We need to return the Response object or this
      // doesn't work
      return $this->sendJson( $data );
    }
    $error = ['message' => 'Something went wrong!']
    return $this->sendJson( $error, 418 );
  }
}

public function sendJson( $data, $statusCode = 200 ) {
  return new Response(
    json_encode( $data ),
    $statusCode,
    ['Content-Type' => 'application/json']
  );
}

The way controllers work in Concrete5, is that if their  action methods (such as view() or action_) return an instanceof Response, then

And that’s how you send JSON in Concrete5.7.

Comments

Commenting has been disabled until I get a proper spam protection working. =(

External Links

Back to beginning