การพัฒนาระบบ Multi-Site หรือ Multi-Tenancy คือการสร้างแพลตฟอร์มเดียวที่สามารถรองรับลูกค้าหรือบริษัทจำนวนมาก (Tenants) โดยที่แต่ละบริษัทจะถูกแยกข้อมูลออกจากกันอย่างสมบูรณ์ แต่ยังคงใช้โค้ดเบส (Codebase) และโครงสร้างพื้นฐานเดียวกัน
ในฐานะ Senior Architect เราแนะนำให้ใช้ PostgreSQL เป็นฐานข้อมูลหลัก เนื่องจาก PostgreSQL มีความสามารถในการจัดการ Schema และ Data Integrity ที่ยอดเยี่ยม ทำให้เหมาะอย่างยิ่งสำหรับการออกแบบระบบ Multi-Tenancy ที่ต้องการความปลอดภัยในการแยกข้อมูลสูง
หลักการ Multi-Tenancy ด้วย PostgreSQL
แทนที่จะใช้การสร้าง Schema แยกสำหรับทุกบริษัท (Schema per Tenant) ซึ่งอาจซับซ้อนในการจัดการเมื่อจำนวนบริษัทเพิ่มขึ้น เราจะใช้แนวทางที่เรียกว่า Shared Schema with Tenant ID โดยการเพิ่มคอลัมน์ tenant_id เข้าไปในทุกตารางข้อมูลหลัก เพื่อระบุว่าข้อมูลแถวนั้นๆ เป็นของบริษัทใด
ขั้นตอนที่ 1: การออกแบบ Schema ด้วย PostgreSQL
เราต้องมั่นใจว่าตารางข้อมูลหลักทุกตารางมีคอลัมน์ tenant_id เพื่อให้ Laravel สามารถกรองข้อมูลได้อย่างถูกต้องตามบริษัทที่ล็อกอินอยู่
SQL
-- สร้างตารางข้อมูลหลักที่รองรับ Multi-Tenancy<br>CREATE TABLE products ( <br> id SERIAL PRIMARY KEY, <br> tenant_id UUID NOT NULL, <br> product_name VARCHAR(255) NOT NULL, <br> sku VARCHAR(50) UNIQUE, <br> price NUMERIC(10, 2) <br> -- เพิ่ม Index เพื่อเร่งความเร็วในการค้นหาตาม Tenant ID<br> );<br>CREATE INDEX idx_tenant_id ON products (tenant_id);
ขั้นตอนที่ 2: การจัดการข้อมูลและการแยก Tenant
เมื่อ Laravel ทำงานกับ PostgreSQL เราจะต้องมั่นใจว่าทุกคำสั่ง Query จะมีการใส่เงื่อนไข WHERE tenant_id = :current_tenant_id เสมอ เพื่อป้องกันการรั่วไหลของข้อมูล (Data Leakage) ระหว่างบริษัท
ตัวอย่างการเพิ่มข้อมูล (Insert) สำหรับ Tenant A และ Tenant B:
SQL
-- สมมติว่า Tenant A มี UUID: 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'<br>INSERT INTO products (tenant_id, product_name, sku, price) <br>VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', 'apple', 'A101', 1.00);<br><br>-- ข้อมูลของ Tenant B<br>INSERT INTO products (tenant_id, product_name, sku, price) <br>VALUES ('b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22', 'banana', 'B202', 0.50);
ตัวอย่างการดึงข้อมูล (Select) สำหรับ Tenant A เท่านั้น:
SQL
SELECT * FROM products <br>WHERE tenant_id = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11' <br>AND product_name = 'apple';
การผสานรวมใน Laravel (Laravel Integration)
ในระดับ Laravel เราจะใช้ Middleware หรือ Scope เพื่อดักจับ tenant_id จากผู้ใช้ที่ล็อกอิน และทำการผูกค่านี้เข้ากับทุก Query ที่ส่งไปยัง PostgreSQL โดยอัตโนมัติ ทำให้โค้ดส่วน Business Logic ไม่ต้องกังวลเรื่องการใส่เงื่อนไข WHERE tenant_id ซ้ำๆ
บทสรุป
การใช้ PostgreSQL ร่วมกับแนวคิด Shared Schema & Tenant ID ใน Laravel เป็นวิธีที่ทรงพลังและปลอดภัยในการสร้างระบบ Multi-Site ที่ขยายตัวได้ง่าย (Scalable) และสามารถรองรับการเติบโตของลูกค้าได้ในระยะยาว สิ่งสำคัญที่สุดคือการบังคับใช้การกรองข้อมูลด้วย tenant_id ในทุกระดับของการเข้าถึงข้อมูลเพื่อรักษาความปลอดภัยของข้อมูลลูกค้าแต่ละราย