Dalam situasi ini, saya selalu memikirkan antarmuka terlebih dahulu, kemudian menulis kode PHP untuk mendukungnya.
- Ini adalah REST API, jadi kode status HTTP yang berarti adalah suatu keharusan.
- Anda ingin struktur data yang fleksibel dan konsisten dikirim ke dan dari klien.
Mari kita pikirkan semua hal yang bisa salah dan kode status HTTP mereka:
- Server melempar kesalahan (500)
- Kegagalan otentikasi (401)
- Sumber daya yang diminta tidak ditemukan (404)
- Data yang Anda modifikasi telah diubah sejak Anda memuatnya (409)
- Kesalahan validasi saat menyimpan data (422)
- Klien telah melampaui tingkat permintaan mereka (429)
- Jenis file tidak didukung (415)
Perhatikan, ada orang lain yang bisa Anda teliti nanti.
Untuk sebagian besar kondisi kegagalan, hanya ada satu pesan kesalahan yang akan dikembalikan. Itu422 Unprocessable Entity
respon, yang saya digunakan untuk "kesalahan validasi" bisa kembali lebih dari satu kesalahan --- Satu atau lebih kesalahan per formulir isian.
Kami membutuhkan struktur data yang fleksibel untuk respons kesalahan.
Ambil sebagai contoh, 500 Internal Server Error
:
HTTP/1.1 500 Internal Server Error
Content-Type: text/json
Date: Fri, 16 Jan 2015 17:44:25 GMT
... other headers omitted ...
{
"errors": {
"general": [
"Something went catastrophically wrong on the server! BWOOP! BWOOP! BWOOP!"
]
}
}
Bandingkan dengan kesalahan validasi sederhana ketika mencoba POST sesuatu ke server:
HTTP/1.1 422 Unprocessable Entity
Content-Type: text/json
Date: Fri, 16 Jan 2015 17:44:25 GMT
... other headers omitted ...
{
"errors": {
"first_name": [
"is required"
],
"telephone": [
"should not exceed 12 characters",
"is not in the correct format"
]
}
}
Kunci mereka di sini adalah tipe konten text/json
. Ini memberi tahu aplikasi klien bahwa mereka dapat men-decode isi respons dengan dekoder JSON. Jika, katakanlah, kesalahan server internal tidak terdeteksi dan halaman web "Sesuatu yang salah" generik Anda dikirimkan sebagai gantinya, jenis konten harusnya text/html; charset=utf-8
sehingga aplikasi klien tidak akan mencoba untuk memecahkan kode badan respons sebagai JSON.
Ini terlihat semua menemukan dan keren, sampai Anda perlu mendukung tanggapan JSONP . Anda harus mengembalikan 200 OK
respons, bahkan untuk kegagalan. Dalam hal ini Anda harus mendeteksi bahwa klien meminta respons JSONP (biasanya dengan mendeteksi parameter permintaan URL yang disebutcallback
) dan mengubah sedikit struktur data:
(DAPATKAN / posting / 123? Callback = displayBlogPost)
<script type="text/javascript" src="/posts/123?callback=displayBlogPost"></script>
HTTP/1.1 200 OK
Content-Type: text/javascript
Date: Fri, 16 Jan 2015 17:44:25 GMT
... other headers omitted ...
displayBlogPost({
"status": 500,
"data": {
"errors": {
"general": [
"Something went catastrophically wrong on the server! BWOOP! BWOOP! BWOOP!"
]
}
}
});
Maka penangan respons pada klien (dalam browser web) harus memiliki fungsi JavaScript global displayBlogPost
yang disebut yang menerima argumen tunggal. Fungsi ini harus menentukan apakah respons berhasil:
function displayBlogPost(response) {
if (response.status == 500) {
alert(response.data.errors.general[0]);
}
}
Jadi kami sudah merawat klien. Sekarang, mari kita jaga servernya.
<?php
class ResponseError
{
const STATUS_INTERNAL_SERVER_ERROR = 500;
const STATUS_UNPROCESSABLE_ENTITY = 422;
private $status;
private $messages;
public function ResponseError($status, $message = null)
{
$this->status = $status;
if (isset($message)) {
$this->messages = array(
'general' => array($message)
);
} else {
$this->messages = array();
}
}
public function addMessage($key, $message)
{
if (!isset($message)) {
$message = $key;
$key = 'general';
}
if (!isset($this->messages[$key])) {
$this->messages[$key] = array();
}
$this->messages[$key][] = $message;
}
public function getMessages()
{
return $this->messages;
}
public function getStatus()
{
return $this->status;
}
}
Dan untuk menggunakan ini jika terjadi kesalahan server:
try {
// some code that throws an exception
}
catch (Exception $ex) {
return new ResponseError(ResponseError::STATUS_INTERNAL_SERVER_ERROR, $ex->message);
}
Atau saat memvalidasi input pengguna:
// Validate some input from the user, and it is invalid:
$response = new ResponseError(ResponseError::STATUS_UNPROCESSABLE_ENTITY);
$response->addMessage('first_name', 'is required');
$response->addMessage('telephone', 'should not exceed 12 characters');
$response->addMessage('telephone', 'is not in the correct format');
return $response;
Setelah itu, Anda hanya perlu sesuatu yang mengambil objek respons yang dikembalikan dan mengubahnya menjadi JSON dan mengirimkan respons dengan cara riang.