GraphQL শুরু করার জন্য যা যা জানা দরকার। GraphQL পার্ট - ২

আগের পর্ব :
GraphQL কি এবং কেন? GraphQL পার্ট - ১

GraphQL শুরু করার জন্য যা যা জানা দরকার:

  • Schema Definition
  • Resolver

১. Schema Definition (স্কিমা ডেফিনিশন)

GraphQL-এর স্কিমা হলো একটি ব্লুপ্রিন্ট যা ডেটার স্ট্রাকচার এবং সেই ডেটার সাথে কীভাবে ইন্টারঅ্যাক্ট করা যাবে তা নির্ধারণ করে। স্কিমা ডেফিনিশনে বিভিন্ন ধরনের ডেটা টাইপ এবং অপারেশন (query, mutation) ডিফাইন করা হয়।

Scalar Types

একটি মৌলিক ডাটা টাইপ যা একটি একক মানের প্রতিনিধিত্ব করে এবং সাধারণত প্রিমিটিভ ধরনের ডেটা ধারণ করে। GraphQL এ ডিফল্টভাবে ৫টি scalar টাইপ দেয়া থাকে:

  1. Int: পূর্ণসংখ্যা।
  2. Float: দশমিক সংখ্যা।
  3. String: টেক্সট।
  4. Boolean: সত্য বা মিথ্যা।
  5. ID: ইউনিক আইডেন্টিফায়ার যা সাধারণত ইউনিক হতে হবে।

এছাড়াও আমরা চাইলে প্রয়োজন মতো custom scalar তৈরি করে নিতে পারি।

Object Types

মূলত ডেটার স্ট্রাকচার তৈরিতে ব্যবহৃত হয়। একটি Object টাইপের একাধিক ফিল্ড থাকে, যেগুলো scalar দিয়ে ডিফাইন করা হয়।

উদাহরণ:

type User { 
  id: ID! 
  role: String! 
  name: String! 
  email: String! 
  phone: String 
  age: Int 
}

এখানে User হলো Object Type যা ইউজারের ইনফরমেশন ধরে রাখে। এই User টাইপে ছয়টি ফিল্ড রয়েছে: id, role, name, email, phone এবং age। আমরা scalar দিয়ে প্রত্যেক ফিল্ডের মান নির্ধারণ করেছি।

  • ID! মানে হচ্ছে এই ফিল্ডের মান অবশ্যই থাকতে হবে, যা required বা non-nullable নির্দেশ করে।
  • phone এবং age ঐচ্ছিক, মানে না থাকলেও চলবে।

Query Type

GraphQL স্কিমার এন্ট্রি পয়েন্ট যেখানে ডেটা ফেচ করার জন্য ক্লায়েন্ট কী রিকোয়েস্ট করতে পারবে তা ডিফাইন করা হয়। মূলত Query টাইপের মাধ্যমে GraphQL সার্ভারকে ক্লায়েন্ট জানায় যে কী কী ডেটা রিটার্ন করবে।

type Query {
  user(id: ID!): User
  users: [User!]!
}
  • users: [User!]!: এটি ব্যবহারকারীদের একটি তালিকা রিটার্ন করবে এবং সেই তালিকায় null মান থাকতে পারবে না। User! মানে প্রতিটি আইটেম non-nullable, এবং [User!]! মানে তালিকাটিও required
  • user(id: ID!): User: নির্দিষ্ট id দিয়ে একটি User অবজেক্ট রিটার্ন করবে। এখানে id একটি বাধ্যতামূলক আর্গুমেন্ট।

একটি সাধারণ GraphQL Query হতে পারে এরকম:

query {
  users {
    id
    name
    email
  }
}

উপরের Query এর মাধ্যমে আমরা সব ব্যবহারকারীর id, name, এবং email পেতে চাইছি।

Mutation Type

Object Type যা ডেটা পরিবর্তন বা রাইট করার জন্য ব্যবহৃত হয়। যেখানে ডেটা পরিবর্তন (create, update, delete) করার জন্য প্রয়োজনীয় অপারেশনগুলো ডিফাইন করা হয়।

type Mutation {
  createUser(role: String!, name: String!, email: String!, phone: String, age: Int): User
  updateUser(id: ID!, role: String!, name: String, email: String, phone: String, age: Int): User
  deleteUser(id: ID!): Boolean
}
  • createUser: একটি role, name, email, phone, এবং age আর্গুমেন্ট রিসিভ করে নতুন User তৈরি করবে এবং সেটি রিটার্ন করবে। এখানে role, name, email বাধ্যতামূলক, কিন্তু phone এবং age ঐচ্ছিক।
  • updateUser: id আর্গুমেন্ট বাধ্যতামূলক এবং বাকিগুলো ঐচ্ছিক।
  • deleteUser: id আর্গুমেন্ট বাধ্যতামূলক এবং এটি একটি Boolean মান রিটার্ন করবে।

Input Types

অনেক আর্গুমেন্ট একসাথে লেখার পরিবর্তে ইনপুট টাইপ ব্যবহার করা যায়, যা কোডকে সংক্ষিপ্ত ও ক্লিন রাখে।

input CreateUserInput {
  role: String!  
  name: String!
  email: String!
  phone: String
  age: Int 
}

type Mutation {
  createUser(input: CreateUserInput): User
}

এখানে CreateUserInput ইনপুট টাইপ ব্যবহার করে আমরা createUser মিউটেশনে প্রয়োজনীয় আর্গুমেন্টগুলো পাস করছি।

Enumeration/Enum Types

যেখানে একটি ফিল্ডের মান নির্দিষ্ট মানের মধ্যে সীমাবদ্ধ হতে হবে সেখানে Enum টাইপ ব্যবহার করা হয়।

enum UserRole {
  admin 
  user 
}

type User { 
  id: ID! 
  role: UserRole! 
  name: String! 
  email: String! 
  phone: String 
  age: Int 
}

এখানে UserRole এনাম ব্যবহার করে role ফিল্ডের মানকে admin অথবা user এর মধ্যে সীমাবদ্ধ করা হয়েছে।

Directive

কোন ফিল্ড বা কোয়েরি/মিউটেশন বা ফ্রেগমেন্টের উপর কন্ডিশন এপলাই করতে ডিরেক্টিভ ব্যবহার করা হয়। GraphQL এ ডিফল্টভাবে @include এবং @skip ডিরেক্টিভ দেয়া থাকে।

type User {
  id: ID!
  role: UserRole!
  name: String!
  email: String!
  phone: String
  age: Int @include(if: false) # অথবা age @skip(if: true)
}

এখানে age ফিল্ডটি বাদ পড়বে কারণ @include(if: false) নির্দেশ করা হয়েছে।

একটি custom ডিরেক্টিভ তৈরি করে আমরা ডেভেলপারদের ওয়ার্ন করতে পারি যদি একটি ফিল্ড deprecated হয়ে যায়:

directive @deprecated(reason: String) on FIELD_DEFINITION | ENUM_VALUE

type User { 
  id: ID! 
  role: UserRole! 
  name: String! 
  email: String! 
  phone: String 
  age: Int @deprecated(reason: "age will be deprecated soon, use dob instead of it") 
  dob: String 
}

এখন age ফিল্ড ব্যবহার করার সময় ডেভেলপারদের একটি ওয়ার্নিং দেখানো হবে, যেমন: "age will be deprecated soon, use dob instead of it"

২. Resolvers (রিজলভার)

Resolvers হলো ফাংশন যা GraphQL স্কিমার জন্য ডেটা ফেচ বা প্রসেস করার জন্য ব্যবহৃত হয়। রিজলভার ফাংশন ছাড়া GraphQL এর স্কিমা কেবলমাত্র ডেটার স্ট্রাকচার জানাবে, কিন্তু ডেটা ফেচ করার পদ্ধতি থাকবে না। রিজলভার ফাংশনই ঠিক করে দেয় যে কীভাবে ক্লায়েন্টের অনুরোধের ভিত্তিতে ডেটা রিটার্ন করা হবে।

প্রত্যেকটি রিজলভার ফাংশন সাধারণত তিন/চারটি প্যারামিটার গ্রহণ করে:

  1. parent (root): অবজেক্টকে নির্দেশ করে, যা বর্তমানে রিজলভ হচ্ছে।
  2. args: কোয়েরির আর্গুমেন্ট, যা ক্লায়েন্ট পাঠিয়েছে।
  3. context: এমন একটি অবজেক্ট যা সকল রিজলভারের জন্য শেয়ার করা হয় এবং অথেন্টিকেশন, ডাটাবেস কানেকশন, ইত্যাদি ধরার জন্য ব্যবহার করা হয়।
  4. info: এটি অবজেক্ট যা কোয়েরি সম্পর্কিত ইনফো এবং এক্সিকিউশন প্রসেস সম্পর্কিত মেটাডেটা ধারণ করে (অপশনাল)।

আমরা যেহেতু লারভেল ইউজ করবো তাই রিজলভারের এক্সাম্পল দেখালাম না , আপাতত মনে রাখুন রিজলভার কি, তাহলেই হবে।

ধন্যবাদ সবাইকে।
আবার দেখা হবে পরের পর্বে।

লারাভেল গ্রাফকিউলের জন্য নিচের ভিডিও ফলো করতে পারেন।
Bitfumes চ্যানেলের এই প্লেলিস্ট ফলো করতে পারেন।
Andre Madarang এই ভিডিও টা দেখতে পারেন।

8 Likes

দারুন লিখেছেন ভাই। আরো বিস্তারিত জানতে চাই।

1 Like