الـ API ببساطة هى عبارة عن وسيط يقدم خدمة لبرنامج معين فيقوم برنامجك مثلا بالتواصل مع هدا الوسيط لكي يترجم له مجموعة من الامور يحتاج برنامجك اليها حتى يفهمها.
الـ API اليوم لايمكن الاستغناء عنها ابدا فلايكاد موقع تدخله الا وتجده يستخدم API مثلا عندما تجد موقع ما يدعم خاصية التسجيل عبر facebook فبتسجيلك عن طريق فيسبوك يتطلب api خاصة بالفيسبوك تمر عليها وهدا الوسيط api يقوم بالرد للسرفر ادا كانت البيانات صحيحة ام لا
اختصاراً لـ Representational state transfer هو نوع من أنواع الـ API حيث يقوم هدا النوع بنقل البيانات بين العميل والخادم "Server و Client" عن طريق البرتكول HTTP, فجميع العمليات تتم من خلال هذا البرتكول وعندما نقول عمليات فنحن نقصد العمليات الشائعة بعالم البرمجة وهي CREATE READ UPDATE DELETE اختصارا لكلمة CRUD.
يملك البرتكول HTTP مجموعة من التعليمات methods تترجم من خلالها نوع الطلب المرسل من client الى server حيث سيفهم الـ API من خلال مسار رابط http +نوع الـ method سيفهم مادا تريده بالضبط ويقوم بمعالجة طلبك وتتلخص تعليمات البرتكول http في التالي
فالـ API بشكله الافتراضي عندما يستقبل مثلا تعليمة عن طريق POST سيفهم انك تقصد CREATE اي انك تريد اضافة بيانات. وعندما يستقبل تعليمة بنمط GET سيفهم انك تريد جلب وقراءة بيانات READ
أيضا عندما يستقبل تعليمة بنمط PUT سيفهم أنك تريد التعديل على بيانات شيء ما موجود سابقا بقاعدة البيانات وعندما يستقبل بيانات.
في هذا المثال سوف أقوم بجلب جميع brands كما في الجدول التالي
إنشاء Route
بداية فإننا نحتاج لإنشاء route، حيث وفرت لارافيل ملف api.php في المسار routes/api.php.
Route::get('brands',[BrandController::class,'index']);
وبداخل الكونترولر BrandController لجلب البيانات
public function index() { return Brand::get(); }
عرض البيانات
ولعرض البيانات فإننا بحاجة لإضافة api للرابط
فإذا كنا نريد مثلا عرض الطلاب
http://www.test.test/api/students
وهكذا
ولعرض brands
http://www.test.test/api/brands
فنحصل على النتيجة التالية
[ { "id": 11, "name": "possimus", "created_at": "2021-05-09T04:25:19.000000Z", "updated_at": "2021-05-09T04:25:19.000000Z" }, { "id": 12, "name": "dolores", "created_at": "2021-05-09T04:25:19.000000Z", "updated_at": "2021-05-09T04:25:19.000000Z" },
عرض تفاصيل brand معين
Route::get('brands/{brand}',[BrandController::class,'show']);
public function show(Brand $brand) { return $brand; }
http://www.test.test/api/brands/11
{ "id": 11, "name": "possimus", "created_at": "2021-05-09T04:25:19.000000Z", "updated_at": "2021-05-09T04:25:19.000000Z" }
كما نرى إنه تم إرجاع جميع بيانات brand وبما إننا نستخدم Route Model Binding فإنه ليس من السهل إستخدام select ولحل هذه المشكله نستخدم apiResources.
http://www.test.test/api/brands
الكلاس الذي يتحكم بالروابط هو roueServiceProvider حيث يحتوي على الدالة bootوبداخلها يتم تحديد api prefix بحيث يتعامل مع الملف routes/api
$this->routes(function () {
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
كما يحتوي على rules أخرى مثل middleware باسم api.
يمكن أن نتصور apiResources على أنه طبقة بين Model و JSON Response الذي يتم إرجاعه من خلال api، حيث يوفر طريقة سهله لإرجاع البيانات على شكل JSON.
يتكون apiResource من
طريقة تطبيق apiResource
لإنشاء apiResource نستخدم الأمر php artisan make:resource ResourceName.
لإنشاء Resource للـ brands
Php artisan make:resource BrandResource
هنا بعد تنفيذ الأمر يتم إنشاء كلاس باسم BrandResource بداخل المسار app/http/resources/BrandResource.php
class BrandResource extends JsonResource { public function toArray($request) { return parent::toArray($request); } }
وبداخل الدالة toArray نحدد البيانات التي نريد إرجاعها، هنا أريد إرجاع فقط id, name,created_at
public function toArray($request) { return [ 'id'=>$this->id, 'name'=>$this->name, 'created_at'=>$this->created_at, ]; }
بعد ذلك يجب إخبار دوال الكونترولر BrandController بإرجاع Resource عوضا عن إرجاع object
public function show(Brand $brand) { return new BrandResource($brand); }
الأن عند زيارة الرابط سوف نحصل على النتائج التالية
http://www.test.test/api/brands/11
{ "data": { "id": 11, "name": "possimus", "created_at": "2021-05-09T04:25:19.000000Z" } }
كما نلاحظ أنه حصلنا فقط على البيانات التي نريدها، وكذلك نلاحظ أنه تم إضافة طبقة جديده باسم data.
ولتحويل دالة index كي تستخدم resource عوضا عن إرجاع object.
public function index() { $brands=Brand::get(); return BrandResource::collection($brands); }
http://www.test.test/api/brands
{ "data": [ { "id": 11, "name": "possimus", "created_at": "2021-05-09T04:25:19.000000Z" }, { "id": 12, "name": "dolores", "created_at": "2021-05-09T04:25:19.000000Z" }, ] }
ماذا لو كنا نريد جلب بيانات brand معين وهذا الـ brand غير موجود في قاعدة البيانات
http://www.test.test/api/brands/2222
إذا كنا نستخدم المتصفح فإنه سوف يتم إرجاع خطأ
404 NOT FOUND
أما إذا كنا نستخدم postman فإنه سيتم إرجاع صفحة html لذلك وفي التطبيقات الرسمية يجب تحديد headers بـ application/json.
ولتحديد ذلك في postman نذهب إلى التبويب Haders ونضيف القيم
Key=Accept Value = application/json
لفرض أن لدي جدول المنتجات ويحتوي على حقل brand_id وأريد جلب المنتجات مع إسم brand التابع له بإستخدام apiResource
تحديد العلاقة بين جدول product و brand حيث أن كل product له brand واحد
public function brand() { return $this->belongsTo(Brand::class); }
إنشاء Resource لـ product Model
class ProductResource extends JsonResource { public function toArray($request) { return [ 'id'=>$this->id, 'name'=>$this->name, 'price'=>$this->price, 'qty'=>$this->qty, 'brand'=>new BrandResource($this->brand), ]; } }
كما نلاحظ في ProductResource أننا قمنا بإستخدام BrandResource ونقوم بتمرير العلاقه له.
دالة index في ProductController لعرض المنتجات
public function index() { $products=Product::with('brand')->get(); return ProductResource::collection($products); }
{ "data": [ { "id": 1, "name": "tenetur", "price": 260, "qty": 301, "brand": { "id": 14, "name": "omnis", "created_at": "2021-05-09T04:25:19.000000Z" } }, { "id": 2, "name": "error", "price": 432, "qty": 270, "brand": { "id": 19, "name": "ab", "created_at": "2021-05-09T04:25:19.000000Z" }
},
شكرا جزيلا
الله يعطيك العافيه
ازاي اعمل documentation ع النت بيبقى فيه الداتا و ال methods اللي بعملها بحيث ان بتوع الفرونت إند يقدروا يستخدموا ال url و يجيبوا الداتا عادي زي ده كده 👇 https://fakestoreapi.com/docs
شكراً الشرح واضح أكثر من التطبيق العملي باليوتيوب ^_^
لقد انشات InvoicesResource وكتبت الكود return new InvoicesResource($invoices); تم ارجاع جميع الداتا null , لماذا ؟
Anwar Kamel
السلام عليكم استاذ ، لدي سؤال. ماهو اصدار لارافيل الذي تعمل عليه . وهل ممكن تظع لنا الكود كامل على Github