Rest Api Kullanımı
03.05.2019JSON Rest API'de aşağıdaki kriterler önem arzetmektedir:
1- NULL yerine boş string gönderilmelidir.
2- Date türü için ISO-8601 formatına göre gönderilmelidir.
3- Multiline string için base64 encoding yapılabilir.
4- Success için aşağıdaki gibi bir sonuç dönülmelidir:
{ "data": { "id":1000, "first_name": "Ahmet Yılmaz" } }
Eğer birden fazla sonuç gelecekse aşağıdaki gibi döndürülmelidir:
{ "data": [{ "id":1000, "first_name": "Ahmet Yılmaz" }, { "id":1001, "first_name": "Hakkı Yılmaz" }] }
5- Naming Convention olarak, bu örneklerde görüldüğü üzere bir property birden fazla kelimeden oluşuyorsa, snake_case
dediğimiz teknik kullanılması tavsiye edilmektedir. Ancak Java ve Javascript'te ise camelCase
kullanılması tavsiye edilmektedir.
6- Error sonuç için aşağıdaki gibi bir sonuç dönülmelidir:
{ "error": { "code": 404, "message: "ID not found" } }
Aynı şekilde birden fazla dönülecekse aşağıdaki gibi dönülmesi tavsiye edilmektedir: Burada dikkat edilmesi gereken husus şudur: Parametre error
yerine errors
şeklinde kullanıldı.
{ "errors": [{ "code": 404, "message: "ID not found" }, { "code": 400 "message: "Bad request" }] }
7- Rest API de kullanılması tavsiye edilen HTTP status kodları şunlardır:
- 200 -> OK
- 201 -> Created
- 204 -> Deleted gibi işlemlerde boş içerik döndermek için kullanılmaktadır.
- 304 -> Not Modified
- 400 -> Bad Request
- 401 -> Unauthorized
- 403 -> Forbidden
- 404 -> Not found
- 500 -> Internal server error. (Bu hata kodunu kullanıcıya iletmemek en doğru yöntemdir)
Örnek PHP Uygulaması
Öncelikle Vue.js ve Axios ile yapılan client kod kısmına bakalım:
<template> <div> <div class="row"> <div class="col-sm-12"> <input type="checkbox" class="form-check-input" id="chk_other" @change="check($event)"> <label class="form-check-label" for="chk_other">Proje İçerik türü yoksa ekleyiniz</label> </div> </div> <div v-show="showProjectContentInput"> <div class="row"> <div class="form-group col-sm-8"> <input type="text" v-model="projectContent" placeholder="Proje türünü buraya yazınız" class="form-control"/> </div> <div class="form-group col-sm-4"> <input type="button" class="btn btn-primary" v-on:click="addNewType()" value="Kaydet"> </div> </div> <div class="row" v-show="showError"> <div class="col-sm-12"> <div class="alert-danger pad margin-bottom-5 border-radius"> {{ errorMessage }} </div> </div> </div> <div class="row" v-show="showSuccess"> <div class="col-sm-12"> <div class="alert-success pad margin-bottom-5 border-radius"> {{ successMessage }} </div> </div> </div> </div> </div> </template> <script> export default { props: {}, /* * The component's data. */ data() { return { showProjectContentInput: false, showError: false, errorMessage: " ", showSuccess: false, successMessage: " ", projectContent: '' }; }, /** * Prepare the component (Vue 2.x). */ mounted() { this.prepareComponent(); }, methods: { /** * Prepare the component (Vue 2.x). */ prepareComponent() { }, check() { this.showProjectContentInput = this.showProjectContentInput === false; }, addNewType() { if (this.projectContent.length < 4) { this.errorMessage = 'Minimum 3 karakter girilmelidir'; this.showError = true; } else { const data = { name: 'Client Token', scopes: [] }; axios.post('/oauth/personal-access-tokens', data) .then(response => { var config = { headers: {'Authorization': "Bearer " + response.data.accessToken} }; axios.post('/api/v1/project-contents', {'name': this.projectContent},config).then(response => { this.successMessage = response.data.data.message; this.showSuccess = true; this.showError = false; setTimeout(function(){ window.location.reload(); },2000); }).catch(error => { this.errorMessage = error.response.data.error != null ? error.response.data.error.message : error.message; this.showError = true; this.showSuccess = false; }); }) .catch(error => { this.errorMessage=error.message; this.showError = true; this.showSuccess = false; }); } } } } </script>
PHP Kodları:
use App\Repositories\ProjectContentRepository; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Log; class ProjectContentController { /** @var ProjectContentRepository */ private $projectContentRepository; public function __construct(ProjectContentRepository $projectContentRepository) { $this->projectContentRepository = $projectContentRepository; } public function store(Request $request) { if (request()->wantsJson()) { try { $userId = Auth::user()->id; $name = $request->input('name'); if (!isset($name) || strlen($name) < 4) { return response()->json(['error' => ['code' => '400', 'message' => 'Minimum 3 karakter girilmelidir']], 400); } $existingContent = $this->projectContentRepository->findByField('name', $name)->first(); if ($existingContent != null) { return response()->json(['error' => ['code' => '400', 'message' => 'Bu isimde bir proje içerik vardır']], 400); } $this->projectContentRepository->create(['name' => $name, 'user_id' => $userId]); return response()->json(['data' => ['message' => 'Başarılı bir şekilde eklendi']]); } catch (\Exception $e) { Log::error($e->getMessage()); return response()->json(['error' => ['code' => '400', 'message' => 'Beklenmeyen bir hata oluştu']], 400); } } else { return response()->json(['error' => ['code' => '415', 'message' => 'Method not supported']], 415); } } }
8- Diğer önemli bilgiler için https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/