Saat ini saya sedang merancang dan mengimplementasikan API RESTful di PHP. Namun, saya tidak berhasil menerapkan desain awal saya.
GET /users # list of users
GET /user/1 # get user with id 1
POST /user # create new user
PUT /user/1 # modify user with id 1
DELETE /user/1 # delete user with id 1
Sejauh ini cukup standar, bukan?
Masalah saya dengan yang pertama GET /users
. Saya sedang mempertimbangkan mengirim parameter di badan permintaan untuk memfilter daftar. Ini karena saya ingin dapat menentukan filter kompleks tanpa mendapatkan url yang sangat panjang, seperti:
GET /users?parameter1=value1¶meter2=value2¶meter3=value3¶meter4=value4
Sebaliknya saya ingin memiliki sesuatu seperti:
GET /users
# Request body:
{
"parameter1": "value1",
"parameter2": "value2",
"parameter3": "value3",
"parameter4": "value4"
}
yang jauh lebih mudah dibaca dan memberi Anda kemungkinan besar untuk mengatur filter yang kompleks.
Bagaimanapun, file_get_contents('php://input')
tidak mengembalikan badan GET
permintaan untuk permintaan. Saya juga mencoba http_get_request_body()
, tetapi shared hosting yang saya gunakan tidak ada pecl_http
. Tidak yakin itu akan membantu.
Saya menemukan pertanyaan ini dan menyadari bahwa GET mungkin tidak seharusnya memiliki badan permintaan. Itu agak tidak meyakinkan, tetapi mereka menyarankan untuk tidak melakukannya.
Jadi sekarang saya tidak yakin apa yang harus saya lakukan. Bagaimana Anda merancang fungsi pencarian / penyaringan RESTful?
Saya kira saya bisa menggunakannya POST
, tapi itu sepertinya tidak begitu tenang.
Jawaban:
Cara terbaik untuk mengimplementasikan pencarian RESTful adalah dengan menganggap pencarian itu sendiri sebagai sumber daya. Kemudian Anda dapat menggunakan kata kerja POST karena Anda membuat pencarian. Anda tidak harus benar-benar membuat sesuatu dalam database untuk menggunakan POST.
Sebagai contoh:
Anda membuat pencarian dari sudut pandang pengguna. Detail implementasi ini tidak relevan. Beberapa API yang tenang bahkan mungkin tidak membutuhkan kegigihan. Itu adalah detail implementasi.
sumber
Jika Anda menggunakan badan permintaan dalam permintaan GET, Anda melanggar prinsip REST, karena permintaan GET Anda tidak akan dapat di-cache, karena sistem cache hanya menggunakan URL.
Dan yang lebih buruk, URL Anda tidak dapat di-bookmark, karena URL tidak berisi semua informasi yang diperlukan untuk mengarahkan pengguna ke halaman ini
Gunakan parameter URL atau Pertanyaan alih-alih parameter isi permintaan.
misalnya:
Bahkan, HTTP RFC 7231 mengatakan bahwa:
Muatan dalam pesan permintaan GET tidak memiliki semantik yang ditentukan; mengirim badan muatan pada permintaan GET dapat menyebabkan beberapa implementasi yang ada menolak permintaan tersebut.
Untuk informasi lebih lanjut lihat di sini
sumber
Tampaknya penyaringan / pencarian sumber daya dapat diimplementasikan dengan tenang. Idenya adalah untuk memperkenalkan titik akhir baru yang disebut
/filters/
atau/api/filters/
.Menggunakan filter titik akhir ini dapat dianggap sebagai sumber daya dan karenanya dibuat melalui
POST
metode. Cara ini - tentu saja - badan dapat digunakan untuk membawa semua parameter serta struktur pencarian / filter yang kompleks dapat dibuat.Setelah membuat filter seperti itu, ada dua kemungkinan untuk mendapatkan hasil pencarian / filter.
Sumber daya baru dengan ID unik akan dikembalikan bersama dengan
201 Created
kode status. Kemudian menggunakan ID iniGET
permintaan dapat dibuat untuk/api/users/
menyukai:Setelah filter baru dibuat melalui
POST
itu tidak akan membalas dengan201 Created
tetapi sekaligus303 SeeOther
denganLocation
header yang menunjuk ke/api/users/?filterId=1234-abcd
. Redirect ini akan ditangani secara otomatis melalui pustaka yang mendasarinya.Dalam kedua skenario, dua permintaan perlu dibuat untuk mendapatkan hasil yang difilter - ini dapat dianggap sebagai kelemahan, terutama untuk aplikasi seluler. Untuk aplikasi seluler saya akan menggunakan
POST
panggilan tunggal untuk/api/users/filter/
.Bagaimana cara menjaga filter yang dibuat?
Mereka dapat disimpan dalam DB dan digunakan nanti. Mereka juga dapat disimpan di beberapa penyimpanan sementara misalnya redis dan memiliki beberapa TTL setelah itu mereka akan kedaluwarsa dan akan dihapus.
Apa kelebihan dari ide ini?
Filter, hasil yang difilter dapat di-cache dan bahkan dapat di-bookmark.
sumber
Saya pikir Anda harus pergi dengan parameter permintaan tetapi hanya selama tidak ada header HTTP yang sesuai untuk mencapai apa yang ingin Anda lakukan. The spesifikasi HTTP tidak secara eksplisit mengatakan, bahwa GET tidak bisa memiliki tubuh. Namun makalah ini menyatakan:
sumber
Karena saya menggunakan backend laravel / php saya cenderung menggunakan sesuatu seperti ini:
PHP secara otomatis mengubah
[]
params menjadi array, jadi dalam contoh ini saya akan berakhir dengan$filter
variabel yang menampung array / objek filter, bersama dengan halaman dan sumber daya terkait yang ingin saya muat.Jika Anda menggunakan bahasa lain, ini mungkin masih merupakan konvensi yang bagus dan Anda bisa membuat parser untuk dikonversi
[]
ke array.sumber
[
dan]
. Menggunakan representasi yang dikodekan dari karakter-karakter ini untuk mengelompokkan parameter permintaan adalah praktik yang sudah dikenal luas. Ini bahkan digunakan di JSON: spesifikasi API .Jangan terlalu khawatir jika API awal Anda sepenuhnya tenang atau tidak (khususnya ketika Anda baru saja dalam tahap alpha). Dapatkan pipa back-end bekerja terlebih dahulu. Anda selalu dapat melakukan semacam transformasi URL / penulisan ulang untuk memetakan berbagai hal, menyempurnakannya sampai Anda mendapatkan sesuatu yang cukup stabil untuk pengujian luas ("beta").
Anda dapat menentukan URI yang parameternya dikodekan oleh posisi dan konvensi pada URI sendiri, diawali oleh jalur yang Anda tahu akan selalu dipetakan ke sesuatu. Saya tidak tahu PHP, tapi saya berasumsi bahwa fasilitas seperti itu ada (seperti yang ada dalam bahasa lain dengan kerangka kerja web):
.yaitu. Lakukan jenis pencarian "pengguna" dengan param [i] = nilai [i] untuk i = 1..4 di toko # 1 (dengan value1, value2, value3, ... sebagai singkatan untuk parameter kueri URI):
atau
atau sebagai berikut (meskipun saya tidak akan merekomendasikannya, lebih lanjut tentang itu nanti)
Dengan opsi 1, Anda memetakan semua URI yang diawali dengan
/store1/search/user
penangan pencarian (atau apa pun penandaan PHP) default untuk melakukan pencarian sumber daya di bawah store1 (setara dengan/search?location=store1&type=user
.Dengan konvensi yang didokumentasikan dan ditegakkan oleh API, nilai parameter 1 hingga 4 dipisahkan dengan koma dan disajikan dalam urutan itu.
Opsi 2 menambahkan tipe pencarian (dalam hal ini
user
) sebagai parameter posisi # 1. Pilihan mana pun hanyalah pilihan kosmetik.Opsi 3 juga dimungkinkan, tetapi saya rasa saya tidak menyukainya. Saya pikir kemampuan pencarian dalam sumber daya tertentu harus disajikan dalam URI itu sendiri sebelum pencarian itu sendiri (seolah-olah menunjukkan dengan jelas dalam URI bahwa pencarian itu spesifik dalam sumber daya itu.)
Keuntungan dari melewati parameter pada URI adalah bahwa pencarian adalah bagian dari URI (sehingga memperlakukan pencarian sebagai sumber daya, sumber daya yang isinya dapat - dan akan - berubah dari waktu ke waktu.) Kerugiannya adalah bahwa urutan parameter adalah wajib .
Setelah Anda melakukan sesuatu seperti ini, Anda dapat menggunakan GET, dan itu akan menjadi sumber daya baca-saja (karena Anda tidak dapat POST atau PUT untuk itu - itu akan diperbarui ketika GET'ed). Ini juga akan menjadi sumber daya yang hanya ada saat dijalankan.
Anda juga bisa menambahkan lebih banyak semantik dengan menyimpan hasil untuk periode waktu tertentu atau dengan DELETE yang menyebabkan cache dihapus. Namun, ini mungkin bertentangan dengan apa yang biasanya digunakan DELETE untuk orang (dan karena orang biasanya mengontrol caching dengan header caching.)
Bagaimana Anda melakukannya akan menjadi keputusan desain, tetapi ini akan menjadi cara saya akan pergi tentang. Itu tidak sempurna, dan saya yakin akan ada kasus di mana melakukan ini bukanlah hal terbaik untuk dilakukan (khusus untuk kriteria pencarian yang sangat kompleks).
sumber
FYI: Saya tahu ini agak terlambat tetapi bagi siapa saja yang tertarik. Tergantung pada seberapa tenang Anda ingin menjadi, Anda harus menerapkan strategi penyaringan Anda sendiri karena spesifikasi HTTP tidak begitu jelas tentang hal ini. Saya ingin menyarankan pengkodean url semua parameter filter misalnya
Saya tahu itu jelek tapi saya pikir itu cara yang paling tenang untuk melakukannya dan harus mudah diurai di sisi server :)
sumber