- 1. สถาปัตยกรรมที่แนะนำ
- 2. สิ่งที่ต้องเตรียม
- 3. ติดตั้งแพ็กเกจ Laravel Firebase
- 4. ตั้งค่า Service Account
- 5. เรียกใช้ Firebase Service
- 6. Firebase Authentication กับ Laravel API
- 7. Cloud Firestore
- 8. Realtime Database
- 9. Cloud Storage
- 10. Firebase Cloud Messaging จาก Laravel
- 11. Security Checklist
- 12. Testing Strategy
- 13. ปัญหาที่พบบ่อย
- 14. สรุปแนวทางเลือกบริการ
- แหล่งอ้างอิง
Firebase เป็นแพลตฟอร์ม Backend-as-a-Service ที่มีบริการ Authentication, Cloud Firestore, Realtime Database, Cloud Storage, Cloud Messaging และบริการอื่น ๆ ส่วน Laravel เหมาะกับการสร้าง Web Application, REST API, ระบบหลังบ้าน และงานประมวลผลฝั่งเซิร์ฟเวอร์
การใช้ทั้งสองระบบร่วมกันทำให้ Laravel รับผิดชอบ business logic และ API ขณะที่ Firebase ช่วยจัดการ identity, NoSQL database, ไฟล์ และการแจ้งเตือนแบบ realtime
บทความนี้ใช้ PHP package kreait/laravel-firebase ซึ่งเป็น Laravel integration สำหรับ Firebase Admin PHP SDK
#1. สถาปัตยกรรมที่แนะนำ
flowchart LR
C[Web / Mobile Client] -->|Firebase ID Token| L[Laravel API]
L -->|Verify Token| A[Firebase Authentication]
L -->|Admin SDK| F[Firestore / Realtime Database]
L -->|Admin SDK| S[Cloud Storage]
L --> D[(Laravel Database)]
แนวทางสำคัญคือ Client ขอ Firebase ID Token หลังจากผู้ใช้เข้าสู่ระบบ แล้วส่ง token ไปยัง Laravel ผ่าน Authorization: Bearer ... จากนั้น Laravel ตรวจสอบ token ด้วย Admin SDK ก่อนให้สิทธิ์เข้าถึงข้อมูล
| ส่วนประกอบ | หน้าที่หลัก |
|---|---|
| Firebase Client SDK | Login, รับ ID Token และสื่อสารกับ Firebase จากฝั่งผู้ใช้ |
| Laravel | API, business rules, validation, authorization และการเชื่อมต่อระบบอื่น |
| Firebase Admin SDK | ตรวจสอบ token และจัดการ Firebase จาก trusted server |
| Firestore | ฐานข้อมูลเอกสารแบบ NoSQL ที่รองรับการ query และการขยายระบบ |
| Realtime Database | ฐานข้อมูล JSON ที่เหมาะกับข้อมูลซึ่งต้องอัปเดตแบบ realtime |
| Cloud Storage | จัดเก็บรูปภาพ เอกสาร และไฟล์สื่อ |
ไม่ควรนำ Service Account JSON ไปไว้ใน frontend หรือ commit เข้า Git repository เพราะไฟล์ดังกล่าวมีสิทธิ์ระดับ server
#2. สิ่งที่ต้องเตรียม
- Firebase Project
- Laravel application ที่ทำงานได้
- PHP และ Composer
- Firebase Authentication ที่เปิด provider ตามต้องการ
- Firestore หรือ Realtime Database หากต้องการเก็บข้อมูลใน Firebase
- Cloud Storage หากต้องการอัปโหลดไฟล์
- Service Account สำหรับการทำงานจาก Laravel
Firebase ระบุว่า Admin SDK ใช้สำหรับสภาพแวดล้อมที่มีสิทธิ์ เช่น server หรือ cloud environment และสามารถตรวจสอบ authentication token รวมถึงเข้าถึง Firestore, Realtime Database และ Cloud Storage ได้
#3. ติดตั้งแพ็กเกจ Laravel Firebase
ติดตั้งแพ็กเกจด้วย Composer:
composer require kreait/laravel-firebase
แพ็กเกจจะลงทะเบียน service provider ให้กับ Laravel และสามารถเรียกใช้งานผ่าน dependency injection, app() helper หรือ Facade ได้
เผยแพร่ไฟล์ configuration หากต้องการปรับแต่ง:
php artisan vendor:publish \
--provider="Kreait\\Laravel\\Firebase\\ServiceProvider" \
--tag=config
#4. ตั้งค่า Service Account
ไปที่ Firebase Console → Project settings → Service accounts แล้วสร้าง private key จากนั้นเก็บไฟล์ไว้ในตำแหน่งที่ไม่ถูกเผยแพร่ เช่น storage/app/firebase/ และเพิ่มลงใน .gitignore
ตัวอย่าง .env:
FIREBASE_CREDENTIALS=storage/app/firebase/firebase-service-account.json
FIREBASE_DATABASE_URL=https://your-project-default-rtdb.firebaseio.com
หรือใช้ Application Default Credentials:
GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/firebase-service-account.json
ตัวอย่าง .gitignore:
storage/app/firebase/*.json
.env
หลังแก้ .env ให้ล้าง configuration cache:
php artisan config:clear
php artisan cache:clear
ใน production ที่ทำงานบน Google Cloud ควรพิจารณาใช้ Application Default Credentials หรือ workload identity ตามสภาพแวดล้อม แทนการฝัง private key ไว้ใน source code
#5. เรียกใช้ Firebase Service
ตัวอย่าง Controller ที่เรียก Firebase Facade:
<?php
namespace App\\Http\\Controllers;
use Illuminate\\Http\\JsonResponse;
use Kreait\\Laravel\\Firebase\\Facades\\Firebase;
class FirebaseHealthController extends Controller
{
public function __invoke(): JsonResponse
{
$auth = Firebase::auth();
return response()->json([
'firebase' => 'connected',
'auth_service' => $auth::class,
]);
}
}
เพิ่ม route:
use App\\Http\\Controllers\\FirebaseHealthController;
Route::get('/firebase/health', FirebaseHealthController::class);
สำหรับโค้ดที่ต้องทดสอบง่าย แนะนำ dependency injection ผ่าน service class แทนการเรียก Facade ทุกจุด
#6. Firebase Authentication กับ Laravel API
#6.1 ตรวจสอบ Firebase ID Token
สร้าง middleware:
php artisan make:middleware VerifyFirebaseToken
ตัวอย่าง middleware:
<?php
namespace App\\Http\\Middleware;
use Closure;
use Illuminate\\Http\\Request;
use Kreait\\Firebase\\Exception\\Auth\\FailedToVerifyToken;
use Kreait\\Laravel\\Firebase\\Facades\\Firebase;
class VerifyFirebaseToken
{
public function handle(Request $request, Closure $next)
{
$token = $request->bearerToken();
if (!$token) {
return response()->json([
'message' => 'Missing Firebase ID token',
], 401);
}
try {
$verifiedIdToken = Firebase::auth()->verifyIdToken($token);
$request->attributes->set('firebase_token', $verifiedIdToken);
$request->attributes->set('firebase_uid', $verifiedIdToken->claims()->get('sub'));
} catch (FailedToVerifyToken $exception) {
return response()->json([
'message' => 'Invalid Firebase ID token',
], 401);
}
return $next($request);
}
}
ผูก middleware กับ route:
Route::middleware('firebase.auth')->group(function () {
Route::get('/me', function (Request $request) {
return response()->json([
'uid' => $request->attributes->get('firebase_uid'),
]);
});
});
ชื่อ middleware ต้องลงทะเบียนให้ตรงกับ Laravel version ที่ใช้งาน เช่นใน bootstrap/app.php หรือ app/Http/Kernel.php
#6.2 เชื่อม Firebase user กับตาราง users ของ Laravel
ระบบจริงมักเก็บข้อมูลผู้ใช้ที่เกี่ยวกับ business ไว้ในฐานข้อมูล Laravel และใช้ Firebase เป็น identity provider:
$uid = $request->attributes->get('firebase_uid');
$user = User::updateOrCreate(
['firebase_uid' => $uid],
[
'email' => $verifiedIdToken->claims()->get('email'),
'name' => $verifiedIdToken->claims()->get('name', 'ผู้ใช้ Firebase'),
]
);
ควรเพิ่ม unique index ให้ firebase_uid:
$table->string('firebase_uid')->unique();
ข้อดีของแนวทางนี้คือ Firebase จัดการ identity ส่วน Laravel ยังคงใช้ Eloquent, Policy, Role และ business transaction ได้เต็มที่
#7. Cloud Firestore
#7.1 เขียนเอกสาร
use Illuminate\\Http\\Request;
use Kreait\\Laravel\\Firebase\\Facades\\Firebase;
public function store(Request $request)
{
$data = $request->validate([
'title' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
]);
$firestore = Firebase::firestore();
$database = $firestore->database();
$document = $database->collection('posts')->add([
'title' => $data['title'],
'content' => $data['content'],
'created_at' => now()->toIso8601String(),
]);
return response()->json([
'id' => $document->id(),
], 201);
}
#7.2 อ่านเอกสาร
public function show(string $id)
{
$document = Firebase::firestore()
->database()
->collection('posts')
->document($id)
->snapshot();
if (!$document->exists()) {
return response()->json(['message' => 'Post not found'], 404);
}
return response()->json([
'id' => $document->id(),
...$document->data(),
]);
}
#7.3 Query เอกสาร
$documents = Firebase::firestore()
->database()
->collection('posts')
->where('status', '=', 'published')
->orderBy('created_at', 'DESC')
->limit(20)
->documents();
$posts = [];
foreach ($documents as $document) {
if ($document->exists()) {
$posts[] = [
'id' => $document->id(),
...$document->data(),
];
}
}
ควรวางแผน index ของ Firestore ตั้งแต่ต้น โดยเฉพาะ query ที่ใช้ filter และ order หลาย field
#8. Realtime Database
Realtime Database เหมาะกับโครงสร้างข้อมูล JSON และ use case ที่ต้องอ่านค่าปัจจุบันอย่างรวดเร็ว เช่น presence, สถานะอุปกรณ์ หรือ dashboard แบบ realtime
เขียนข้อมูล:
$database = Firebase::database();
$database
->getReference('rooms/room-001/messages/msg-001')
->set([
'text' => 'สวัสดีจาก Laravel',
'sender_id' => $request->user()->id,
'created_at' => now()->timestamp,
]);
อ่านข้อมูล:
$value = Firebase::database()
->getReference('rooms/room-001/messages')
->getValue();
return response()->json($value ?? []);
ควรกำหนดโครงสร้าง path ให้สัมพันธ์กับ tenant หรือ user และหลีกเลี่ยงการเก็บข้อมูลทั้งหมดไว้ที่ root เดียว
#9. Cloud Storage
ตัวอย่างอัปโหลดไฟล์จาก Laravel ไปยัง Firebase Storage:
use Illuminate\\Http\\Request;
use Kreait\\Laravel\\Firebase\\Facades\\Firebase;
public function upload(Request $request)
{
$request->validate([
'file' => ['required', 'file', 'max:5120', 'mimes:jpg,jpeg,png,pdf'],
]);
$file = $request->file('file');
$path = 'uploads/' . date('Y/m') . '/' . uniqid() . '-' . $file->getClientOriginalName();
$bucket = Firebase::storage()->getBucket();
$bucket->upload(
fopen($file->getRealPath(), 'r'),
['name' => $path]
);
return response()->json([
'path' => $path,
'message' => 'Upload successful',
], 201);
}
ใน production ควรจัดการชื่อไฟล์เอง ไม่ใช้ชื่อไฟล์จากผู้ใช้โดยตรง และควรกำหนด MIME type, ขนาดไฟล์, antivirus scanning และอายุของ signed URL ตามความเหมาะสม
#10. Firebase Cloud Messaging จาก Laravel
สำหรับการแจ้งเตือนแบบ push ให้เก็บ FCM registration token ของอุปกรณ์ แล้วส่งข้อความผ่าน Firebase Messaging:
use Kreait\\Firebase\\Messaging\\CloudMessage;
use Kreait\\Firebase\\Messaging\\Notification;
use Kreait\\Laravel\\Firebase\\Facades\\Firebase;
$message = CloudMessage::withTarget('token', $deviceToken)
->withNotification(Notification::create(
'มีข้อความใหม่',
'คุณได้รับการแจ้งเตือนจากระบบ'
));
Firebase::messaging()->send($message);
งานส่ง notification จำนวนมากควรทำผ่าน Laravel Queue เพื่อไม่ให้ request หลักรอการส่งข้อความ
#11. Security Checklist
#Service Account
- ห้าม commit JSON private key เข้า Git
- ห้ามใส่ private key ใน JavaScript หรือ mobile application
- ใช้ secret manager หรือ environment secret ใน production
- จำกัดสิทธิ์ของ service account ตามหลัก least privilege
- หมุนเวียน key และ revoke key ที่ไม่ใช้งาน
#Authentication
- ตรวจสอบ ID Token ทุกครั้งที่รับ request ที่ต้องยืนยันตัวตน
- ตรวจสอบ
iss,aud, expiration และ project ที่ถูกต้องผ่าน SDK - ไม่รับ
uidจาก request body มาใช้แทน uid จาก token - ใช้ Laravel Policy/Gate ตรวจสอบสิทธิ์ระดับ resource
- แยก authentication ออกจาก authorization
#Database
- กำหนด Firebase Security Rules สำหรับการเข้าถึงจาก client
- สำหรับ Admin SDK ให้ถือว่าเป็น privileged access และตรวจสอบสิทธิ์ใน Laravel เอง
- Validate input ก่อนเขียน Firestore หรือ Realtime Database
- หลีกเลี่ยงการใช้ document ID ที่คาดเดาได้เมื่อข้อมูลมีความอ่อนไหว
- ออกแบบ index และ pagination เพื่อควบคุมค่าใช้จ่ายและ latency
#File Storage
- ตรวจสอบนามสกุล MIME และขนาดไฟล์
- สร้าง path จาก server ไม่ใช้ path ที่ผู้ใช้ส่งมาโดยตรง
- ใช้ signed URL ที่มีอายุจำกัดกับไฟล์ส่วนตัว
- แยกพื้นที่เก็บไฟล์ public และ private
#12. Testing Strategy
ทดสอบอย่างน้อย 4 ระดับ:
- Unit test สำหรับ service ที่แปลงข้อมูลและสร้างคำสั่ง Firebase
- Feature test สำหรับ middleware ตรวจสอบ token และ HTTP status code
- Integration test กับ Firebase project แยกสำหรับทดสอบ
- Security test สำหรับ token หมดอายุ, token ผิด project, user ไม่มีสิทธิ์ และ path ที่ไม่ควรเข้าถึง
ไม่ควรใช้ production Firebase project เป็นฐานข้อมูลสำหรับ automated test ควรแยก project หรือใช้ emulator ตามความเหมาะสม
#13. ปัญหาที่พบบ่อย
#Unable to determine the Google's Application Credentials
ตรวจสอบว่า FIREBASE_CREDENTIALS หรือ GOOGLE_APPLICATION_CREDENTIALS ชี้ไปยังไฟล์จริง และรัน php artisan config:clear
#Permission denied
ตรวจสอบ service account role, project ID, database URL และรูปแบบ path ของ Firestore/Realtime Database รวมถึงสิทธิ์ที่ตรวจสอบใน Laravel
#Token ใช้งานไม่ได้
ตรวจสอบว่า Client ส่ง Firebase ID Token ไม่ใช่ refresh token หรือ access token ของ provider อื่น และส่งผ่าน header รูปแบบนี้:
Authorization: Bearer <FIREBASE_ID_TOKEN>
#ข้อมูลใน Firestore ไม่ตรงชนิด
Firestore มีชนิดข้อมูลเฉพาะ เช่น timestamp, reference และ array ควรกำหนด data contract ให้ชัดเจน และแปลงข้อมูลก่อนส่งออกเป็น JSON
#14. สรุปแนวทางเลือกบริการ
| ความต้องการ | บริการที่เหมาะสม |
|---|---|
| Login ด้วย Google, Apple, Email หรือ Phone | Firebase Authentication |
| ข้อมูลเอกสารและ query แบบ NoSQL | Cloud Firestore |
| ข้อมูลสถานะที่ต้องอัปเดตเร็วและโครงสร้าง JSON | Realtime Database |
| รูปภาพ เอกสาร และวิดีโอ | Cloud Storage |
| Push notification | Firebase Cloud Messaging |
| Business transaction, report, relational data | Laravel Database เช่น MySQL/PostgreSQL |
สถาปัตยกรรมที่ใช้งานได้ดีในหลายโครงการคือให้ Firebase ดูแล identity และความสามารถ realtime ส่วน Laravel เป็นศูนย์กลางของ domain logic, authorization, validation, queue และการเชื่อมต่อระบบภายนอก
#แหล่งอ้างอิง
- Firebase Admin SDK setup
- Verify Firebase ID tokens
- Add data to Cloud Firestore
- Firebase for Laravel
- Firebase Admin SDK for PHP
- Laravel Documentation
บทความนี้เป็นแนวทางเริ่มต้น ควรตรวจสอบ compatibility ของ PHP, Laravel, kreait/laravel-firebase และ kreait/firebase-php ให้ตรงกับเวอร์ชันในโครงการก่อนติดตั้งจริง