Laravel Mass Assignment Protection

$fillable vs $guarded

Laravel Model-এ Mass Assignment থেকে সুরক্ষার দুটি পদ্ধতি — সম্পূর্ণ গাইড বাংলায়

Mass Assignment কী?
👤 User InputPOST /users
name, email, password
+ is_admin: true
⚡ Mass AssignmentModel::create($request→all())
সব field একসাথে insert
💾 Databasename ✓
email ✓
is_admin = true ✗ (বিপদ!)
⚠️

সমস্যা: User যদি request-এ extra field পাঠায় (যেমন is_admin=true), আর আমরা create($request→all()) করি — তাহলে সেই field-ও database-এ চলে যাবে। এটাকেই Mass Assignment Vulnerability বলে।

$fillable Whitelist

শুধু যেগুলো দেব, সেগুলোই allow — বাকি সব block

protected $fillable = [
  'name',
  'email',
  'password',
];

// is_admin → automatically blocked
Array-এ listed fields শুধু mass assignment-এ যাবে
যেগুলো list-এ নেই, automatically protected
Explicit permission model — Safe by default
🛡️

$guarded Blacklist

যেগুলো দেব না, শুধু সেগুলো block — বাকি সব allow

protected $guarded = [
  'id',
  'is_admin',
];

// name, email → automatically allowed
Array-এ listed fields শুধু block হবে
বাকি সব field allow থাকে
নতুন column যোগ হলে risk বাড়ে
তুলনামূলক বিশ্লেষণ
বিষয়$fillable ✅$guarded 🛡️
কাজের ধরনWhitelist — অনুমতি দাওBlacklist — বাধা দাও
নিরাপত্তা স্তরবেশি নিরাপদকম নিরাপদ
নতুন Column যোগেManually add → controlledAuto allow → risky
Code পরিমাণবেশি field = বেশি লিখতে হয়কম field block = কম লেখা
Laravel best practice✅ Recommended⚠️ সতর্কতার সাথে
একসাথে ব্যবহার❌ একসাথে ব্যবহার করবেন না — conflict হয়
কখন কোনটা ব্যবহার করব?
🔐

$fillable — User-facing Model

User, Post, Comment — যেখানে public input আসে এবং specific field control দরকার

🏗️

$fillable — Sensitive Data

Payment, Role, Permission model — যেখানে একটি extra field বিপদজনক হতে পারে

⚙️

$guarded — Internal/Admin Tool

Admin panel বা internal seeder যেখানে controlled trusted input আসে

🌱

$guarded = [] — Database Seeder

Seeder বা migration-এ সব field fill করার দরকার হলে, কিন্তু production-এ নয়

🚫

$guarded = [] — Production এ নয়

Production app-এ guard পুরো খালি রাখা বিপজ্জনক — সব field exposed থাকে

দুটো একসাথে নয়

একই model-এ fillable ও guarded একসাথে দেবেন না — Laravel conflict handle করে কিন্তু confusing

Corner Cases — বিশেষ পরিস্থিতি

✅ Timestamps স্বয়ংক্রিয়

created_at ও updated_at fillable-এ না রাখলেও চলবে — Laravel নিজেই manage করে।

// fillable-এ দরকার নেই
'created_at', 'updated_at'

❌ $guarded = [] মানে শূন্য protection

Empty array মানে কোনো field block হবে না — সব field mass-assignable।

protected $guarded = [];
// ⚠️ সব field exposed!

⚠️ fill() vs forceFill()

forceFill() fillable/guarded দুটোই bypass করে। Trusted internal code-এ ব্যবহার করুন।

$user->forceFill([
'is_admin' => true
])->save();

🔮 unguard() — temporary bypass

Model::unguard() দিয়ে সাময়িক protection বন্ধ করা যায়। Seeder-এ উপকারী।

Model::unguard();
// ... seeding ...
Model::reguard();

✅ Validation + fillable = Perfect

FormRequest দিয়ে validate করার পর validated() দিয়ে create করলে double protection।

User::create(
$request->validated()
);

❌ create($request→all()) — বিপজ্জনক

all() দিলে user-এর পাঠানো সব field যায় — extra data আসে।

// ⚠️ বিপজ্জনক
User::create($request->all());
// ✅ নিরাপদ
User::create($request->validated());
Real World Example — User Model
class User extends Model {

  // ✅ Recommended approach
  protected $fillable = [
    'name',      // ✅ user দিতে পারবে
    'email',     // ✅ user দিতে পারবে
    'password',  // ✅ user দিতে পারবে
  ];

  // ❌ এগুলো fillable-এ নেই = protected
  // 'is_admin', 'role', 'email_verified_at'

  protected $hidden = ['password', 'remember_token'];
}

// Controller-এ সঠিক ব্যবহার
User::create($request->validated()); // ✅
💡

Best Practice: সবসময় $fillable + $request→validated() একসাথে ব্যবহার করুন। FormRequest validation নিশ্চিত করে শুধু valid data আসছে, আর fillable নিশ্চিত করে শুধু allowed field database-এ যাচ্ছে। দুটো মিলে double protection।

Interactive Simulation
$fillable vs $guarded — Live Demo
Form submit করুন এবং দেখুন Laravel কীভাবে প্রতিটি field প্রসেস করে
$fillable mode চালু — শুধু name, email, password allow। বাকি সব auto-blocked।
HTTP REQUEST (Browser Form)
USER MODEL CONFIG
protected $fillable = [
  'name', 'email', 'password'
];
name allow
email allow
password allow
LARAVEL PROCESSING PIPELINE
1
REQUEST RECEIVED
Controller-এ $request পৌঁছেছে...
2
MODEL FILTER CHECK
Model config চেক করছে...
3
FIELD FILTERING
Fields ফিল্টার হচ্ছে...
4
DATABASE INSERT
Database-এ write হচ্ছে...
DATABASE ROW (users table)
↓ SQL QUERY LOG ↓
GENERATED SQL
-- submit করুন, SQL দেখা যাবে এখানে
Quick Decision Guide

কোনটা ব্যবহার করব?

পরিস্থিতি বুঝে সঠিক পদ্ধতি বেছে নিন

✅ $fillable ব্যবহার করুন যদি...

  • Public-facing form থেকে data আসছে
  • Security critical model (User, Payment)
  • Team-এ junior developer আছে
  • Production application
  • Audit trail দরকার কোন field allowed
  • নতুন column ভবিষ্যতে যোগ হবে

⚠️ $guarded ব্যবহার করুন যদি...

  • Internal admin tool বা script
  • Database seeder / migration
  • Trusted source থেকে data আসছে
  • Prototype বা rapid development
  • অনেক বেশি field আছে model-এ
  • সব field allowed, শুধু কয়টা block
Scenario অনুযায়ী সিদ্ধান্ত
Scenarioপরামর্শকারণ
User registration form$fillablePublic input — attacker field inject করতে পারে
Admin থেকে user update$guardedTrusted admin panel, controlled input
Database seeder$guarded = []একবারের কাজ, trusted data
Payment model$fillableExtra field = বড় বিপদ
Blog post create$fillablePublic form থেকে আসছে
Internal API (trusted service)$guardedSource verified, attack risk কম
Permission/Role model$fillableExtra field = privilege escalation risk
Advanced — forceFill ও unguard

forceFill() — সব protection bypass

fillable/guarded দুটোই উপেক্ষা করে। শুধু trusted internal code-এ ব্যবহার করুন।

$user->forceFill(['is_admin' => true])->save();
// fillable-এ না থাকলেও কাজ করবে

unguard() / reguard() — সাময়িক bypass

পুরো Model-এর protection সাময়িক বন্ধ করা যায়। Seeder-এ কাজে লাগে।

Model::unguard(); // protection off
// bulk seeding এখানে
Model::reguard(); // protection back on

isFillable() / isGuarded() — check করুন

কোনো field allowed কিনা programmatically check করতে পারেন।

$user->isFillable('name'); // true
$user->isFillable('is_admin'); // false
$user->isGuarded('id'); // true

Double Protection Pattern

সবচেয়ে নিরাপদ — validation + fillable একসাথে।

// FormRequest-এ validate করুন
// তারপর validated() দিয়ে create
User::create($request->validated());
// fillable = 2nd safety net
🏆

চূড়ান্ত পরামর্শ: নতুন Laravel project-এ সবসময় $fillable দিয়ে শুরু করুন। এটা আপনাকে explicit হতে বাধ্য করে — কোন field allow তা clearly দেখা যায়। ভবিষ্যতে নতুন column যোগ হলেও automatically exposed হয় না। $guarded শুধু সেখানে ব্যবহার করুন যেখানে আপনি data source-কে ১০০% trust করেন।