لارافيل, Api / 2024-09-08

التعامل مع Api في لارافيل - الجزء الأول - ما هو RESTful API وكيف يمكن جلب البيانات في لارافيل.

التعامل مع Api في لارافيل - الجزء الأول - ما هو RESTful API وكيف يمكن جلب البيانات في لارافيل.

2024-09-08 وقت القراءه : 9 دقائق

جدول المحتويات

ما هو API.

ما هو REST API.

التعامل مع REST API في لارافيل.

لماذا يجب وضع api في الروابط.

ما هو ApiResources؟

إستخدام العلاقات في apiResources.


الـ API  هو اختصار  .Application Programming Interface  

الـ API ببساطة هى عبارة عن وسيط  يقدم خدمة لبرنامج معين فيقوم  برنامجك  مثلا بالتواصل مع هدا الوسيط لكي يترجم له مجموعة من الامور يحتاج برنامجك اليها   حتى  يفهمها.

الـ API اليوم لايمكن الاستغناء عنها ابدا فلايكاد موقع  تدخله الا وتجده يستخدم API مثلا عندما تجد موقع ما يدعم خاصية التسجيل عبر facebook فبتسجيلك عن طريق فيسبوك يتطلب api خاصة بالفيسبوك تمر عليها وهدا الوسيط api يقوم بالرد   للسرفر ادا كانت البيانات صحيحة ام لا

 

ماهو الـ Rest API ؟

اختصاراً لـ Representational state transfer  هو نوع من أنواع الـ API حيث يقوم   هدا النوع بنقل البيانات  بين العميل والخادم  "Server و Client" عن طريق البرتكول HTTP,   فجميع العمليات تتم من خلال هذا البرتكول   وعندما نقول عمليات فنحن نقصد العمليات الشائعة بعالم البرمجة وهي CREATE  READ UPDATE DELETE   اختصارا لكلمة CRUD.

 

يملك البرتكول HTTP  مجموعة من التعليمات methods تترجم من خلالها نوع الطلب المرسل من client الى server    حيث سيفهم الـ API من خلال مسار رابط http  +نوع الـ method  سيفهم مادا تريده بالضبط ويقوم بمعالجة طلبك وتتلخص تعليمات البرتكول http في التالي

  • GET تستخدم لجلب البيانات من السيرفر ( قراءة البيانات READ ).
  • POST إضافة بيانات  ( Create ).
  • PUT لتعديل بيانات (UPDATE)
  • DELETE لحذف البيانات (DELETE)

 

فالـ API بشكله الافتراضي عندما يستقبل مثلا تعليمة عن طريق POST سيفهم انك تقصد CREATE اي انك تريد اضافة بيانات. وعندما يستقبل تعليمة بنمط GET سيفهم انك تريد جلب وقراءة بيانات READ

 

أيضا عندما يستقبل تعليمة بنمط PUT سيفهم أنك تريد التعديل على بيانات شيء ما موجود سابقا بقاعدة البيانات وعندما يستقبل بيانات.

 

التعامل مع  API  بإستخدام إطار العمل لارافيل.

في هذا المثال سوف أقوم بجلب جميع 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.


لماذا يجب وضع api بعد الدومين في الرابط؟

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

يمكن أن نتصور apiResources على أنه طبقة بين Model و JSON Response الذي يتم إرجاعه من خلال api، حيث يوفر طريقة سهله لإرجاع البيانات على شكل JSON

يتكون  apiResource من 

  • Resource Class : يستخدم لتحويل model واحد الى json مثلا لجلب الـ brand الذي لديه id=1.
  • Resource Collection : يستخدم لإرجاع جميع brands.

 

طريقة تطبيق 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


إستخدام العلاقات في apiResources

لفرض أن لدي جدول المنتجات ويحتوي على حقل 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"
    }

},


التعليقات
Anwar Kamel
منذ 3 سنوات

السلام عليكم استاذ ، لدي سؤال. ماهو اصدار لارافيل الذي تعمل عليه . وهل ممكن تظع لنا الكود كامل على Github

خالد حسن
منذ سنتين

شكرا جزيلا

وليد
منذ سنتين

الله يعطيك العافيه

بسملة إبراهيم
منذ سنة

ازاي اعمل documentation ع النت بيبقى فيه الداتا و ال methods اللي بعملها بحيث ان بتوع الفرونت إند يقدروا يستخدموا ال url و يجيبوا الداتا عادي زي ده كده 👇 https://fakestoreapi.com/docs

زائر
منذ سنة

شكراً الشرح واضح أكثر من التطبيق العملي باليوتيوب ^_^

Ahmed
منذ سنة

لقد انشات InvoicesResource وكتبت الكود return new InvoicesResource($invoices); تم ارجاع جميع الداتا null , لماذا ؟

إضافة تعليق
Loading...