Skip to content

Instantly share code, notes, and snippets.

@Da-Fecto
Last active August 29, 2015 14:22
Show Gist options
  • Save Da-Fecto/53b68d309fe98f3a15df to your computer and use it in GitHub Desktop.
Save Da-Fecto/53b68d309fe98f3a15df to your computer and use it in GitHub Desktop.
Work in progress
<?php
/**
* JSON response with a “standardized” structure
*
* @author ©2015 Martijn Geerts
*
* ---------------------------------------------------------------------------------------
*
* 4 types: success, redirect, fail, error
*
* // 2xx Success
* Success (All went well, and data was returned.)
* - success (bool) true
* - message (string) 'success'
* - statusCode (integer) 200
* - data (array) optional
*
* // 3xx Redirection
* Redirect
* No data is returned, only HTTP headers
*
* // 4xx Success
* Fail (There was a problem with the submitted data or the API call wasn't satisfied)
* - success (bool) false
* - message (string) 'reason'
* - statusCode (integer)
*
* // 5xx Server Error
* Error (An error occurred in processing the request, i.e. an exception was thrown)
* - success (bool) false
* - message (string) 'reason'
* - statusCode (integer)
* - errors (array)
*/
class ajaxResponse {
/** @var int */
protected $statusCode;
/** @var bool */
protected $success;
/** @var string */
protected $message;
/** @var array */
protected $errors;
/** @var array */
protected $data;
/**
* Array key is the statusCode the value is the reason. The
*
* HTTP status codes (http://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
*
* 200 OK
* - Standard response for successful HTTP requests. The actual response will depend
* on the request method used. In a GET request, the response will contain an entity
* corresponding to the requested resource. In a POST request, the response will
* contain an entity describing or containing the result of the action.
*
* 201 Created
* The request has been fulfilled and resulted in a new resource being created.
*
* 202 Accepted
* The request has been accepted for processing, but the processing has not been
* completed. The request might or might not eventually be acted upon, as it might be
* disallowed when processing actually takes place.
*
* 204 No Content
* The server successfully processed the request, but is not returning any content.
* Usually used as a response to a successful delete request.
*
* 304 Not Modified
* Indicates that the resource has not been modified since the version specified by
* the request headers If-Modified-Since or If-None-Match. This means that there is no
* need to retransmit the resource, since the client still has a previously-downloaded
* copy.
*
* 400 Bad Request
* The server cannot or will not process the request due to something that is
* perceived to be a client error (e.g., malformed request syntax, invalid request
* message framing, or deceptive request routing).
*
* 401 Unauthorized
* Similar to 403 Forbidden, but specifically for use when authentication is required
* and has failed or has not yet been provided. The response must include a
* WWW-Authenticate header field containing a challenge applicable to the requested
* resource
*
* 403 Forbidden
* The request was a valid request, but the server is refusing to respond to it.
* Unlike a 401 Unauthorized response, authenticating will make no difference.
*
* 404 Not Found
* The requested resource could not be found but may be available again in the future.
* Subsequent requests by the client are permissible.
*
* 405 Method Not Allowed
* A request was made of a resource using a request method not supported by that
* resource; for example, using GET on a form which requires data to be presented via
* POST, or using PUT on a read-only resource.
*
*/
public function statusCodes() {
return array(
// 2xx Success
'200' => 'OK',
'201' => 'Created',
'202' => 'Accepted',
'204' => 'No Content',
// 3xx Redirection
'304' => 'Not Modified', // No need to send data back
// 4xx Client Error
'400' => 'Bad Request',
'401' => 'Unauthorized',
'403' => 'Forbidden',
'404' => 'Not Found',
'405' => 'Method Not Allowed',
// 5xx Server Error
);
}
public function render() {
header('Content-Type: application/json');
header("HTTP/1.1 " . strval($this->statusCode) . " " . $this->message);
$int = (int) $this->statusCode;
$array = array(
'message' => $this->message,
'statusCode' => $int,
'data' => $this->data,
'errors' => $this->errors,
);
// 2xx Success
if ($int >= 200 && $int < 300) {
unset($array['errors']);
// 4xx Client Error
} else if ($int >= 400 && $int < 500) {
unset($array['data']);
}
return json_encode($array, JSON_PRETTY_PRINT);
}
/**
* Setup defaults
*
* @var $array (array) Data or error. dependent on $code
* @var $code (integer) HTTP status code, 400
*/
public function __construct($array = array(), $code = 200) {
// 2xx Success
if (is_array($array) && $code < 300) {
$this->success = true;
$this->data = $array;
// 3xx Redirection ()
} else if (is_array($array) && $code >= 300 && $code < 400 ) {
// No need to reply
// 4xx Client Error
} else if (is_array($array) && $code >= 400 && $code < 500 ) {
$this->success = false;
$this->errors = $array;
// 5xx Server Error
} else if (is_array($array) && $code >= 500) {
$this->success = false;
$this->errors = $array;
// No need for data or array
} else if (is_int($array)) {
$code = (int) $array;
$this->success = $code < 300 ? true : false;
}
$statusCodes = (array) $this->statusCodes();
$codeString = (string) $code;
if (!isset($statusCodes[$codeString])) {
throw new WireException('Status code ' . $code . ' not implemented in ' . get_class($this));
}
// status code & reason
$this->statusCode = (int) $code;
$this->message = (string) $statusCodes[$codeString];
}
/**
* Setter for the properties
*
* @var $property (string) name of the property to set
* @var $value (mixed) value with the type according to the property
*/
public function set($property, $value) {
if (!property_exists($this, $property)) {
throw new WireException(get_class($this) . '::' . $property . " doesn't exist.");
}
switch ($property) {
case 'statusCode':
$expected = 'integer';
$isValid = is_int($property);
break;
case 'success':
$expected = 'boolean';
$isValid = is_bool($property);
break;
case 'message':
$expected = 'string';
$isValid = is_string($property);
break;
case 'errors':
$expected = 'array';
$isValid = is_array($property);
break;
case 'data':
$expected = 'array';
$isValid = is_array($property);
break;
default:
$isValid = false;
break;
}
if (!$isValid) {
$message = $expected . " expected for property " . $property . ', ' . gettype($property) . ' given.';
throw new WireException($message);
}
$this->$property = $value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment