PHP
PHP Session คืออะไร และทำงานอย่างไร
PHP Session คือกลไกที่ช่วยให้เว็บแอปพลิเคชันจดจำข้อมูลของผู้ใช้ระหว่างการโหลดหน้าเว็บแต่ละครั้ง เนื่องจาก HTTP เป็น Stateless Protocol หมายความว่าเซิร์ฟเวอร์ไม่สามารถจดจำผู้ใช้ได้โดยอัตโนมัติ Session จึงเข้ามาแก้ปัญหานี้ด้วยการสร้างไฟล์ชั่วคราวบนเซิร์ฟเวอร์และส่ง Session ID กลับมาในรูปแบบ Cookie ให้กับเบราว์เซอร์ของผู้ใช้
บน Shared Hosting โดยทั่วไป PHP จะเก็บไฟล์ Session ไว้ในโฟลเดอร์ /tmp หรือโฟลเดอร์ที่กำหนดใน php.ini การจัดการ Session บน Shared Hosting มีข้อควรระวังหลายอย่าง โดยเฉพาะเรื่องความปลอดภัย เพราะผู้ใช้หลายรายอาจแชร์เซิร์ฟเวอร์เดียวกัน
ความแตกต่างระหว่าง Session และ Cookies
ก่อนเริ่มตั้งค่า ควรเข้าใจความแตกต่างระหว่าง Session และ Cookies เสียก่อน:
- Session: เก็บข้อมูลบนเซิร์ฟเวอร์ ข้อมูลไม่ถูกส่งผ่านเครือข่าย มีความปลอดภัยสูงกว่า หมดอายุเมื่อปิดเบราว์เซอร์หรือหมดเวลา
- Cookies: เก็บข้อมูลในเบราว์เซอร์ของผู้ใช้ ส่งผ่าน HTTP Header ทุกครั้งที่ request เหมาะสำหรับข้อมูลที่ไม่ละเอียดอ่อน เช่น ภาษา หรือธีมที่เลือก
สำหรับข้อมูลสำคัญเช่น สถานะการล็อกอิน ตะกร้าสินค้า หรือสิทธิ์การเข้าถึง ควรใช้ Session เสมอ ไม่ใช่ Cookies
การเริ่มต้นใช้งาน PHP Session
การใช้งาน Session ใน PHP ทำได้ง่ายมาก เพียงเรียก session_start() ที่บรรทัดแรกของไฟล์ PHP ก่อนที่จะมีการ output ใดๆ รวมถึงช่องว่างหรือ HTML ด้วย
<?php
// เริ่มต้น Session - ต้องอยู่บรรทัดแรกสุดก่อน output ใดๆ
session_start();
// กำหนดค่าใน Session
$_SESSION['user_id'] = 123;
$_SESSION['username'] = 'somchai';
$_SESSION['role'] = 'admin';
// อ่านค่าจาก Session
if (isset($_SESSION['username'])) {
echo "ยินดีต้อนรับ " . htmlspecialchars($_SESSION['username']);
}
// ลบค่าเฉพาะตัวแปรใน Session
unset($_SESSION['role']);
// ลบ Session ทั้งหมด (ใช้ตอน logout)
session_destroy();
?>
การตั้งค่า Session บน Shared Hosting ผ่าน cPanel
บน Shared Hosting สามารถปรับแต่งการตั้งค่า Session ได้หลายวิธี วิธีที่ง่ายที่สุดคือการแก้ไขผ่านไฟล์ .htaccess หรือ php.ini ซึ่งสามารถอัปโหลดได้ผ่าน File Manager ใน cPanel
ตั้งค่าผ่านไฟล์ .htaccess
สร้างหรือแก้ไขไฟล์ .htaccess ในโฟลเดอร์ public_html และเพิ่มการตั้งค่าต่อไปนี้:
# ตั้งค่า Session บน Shared Hosting ผ่าน .htaccess
# กำหนดเวลา Session หมดอายุ (วินาที) - 1800 = 30 นาที
php_value session.gc_maxlifetime 1800
# เปลี่ยนโฟลเดอร์เก็บ Session ให้ปลอดภัยกว่า /tmp
php_value session.save_path "/home/username/session_data"
# ป้องกัน Session Fixation
php_value session.use_strict_mode 1
# ป้องกัน XSS ผ่าน Session Cookie
php_value session.cookie_httponly 1
# บังคับใช้ HTTPS เท่านั้น (ถ้ามี SSL)
php_value session.cookie_secure 1
# ปิดการส่ง Session ID ผ่าน URL (ปลอดภัยกว่า)
php_value session.use_only_cookies 1
# ตั้งค่า SameSite Cookie เพื่อป้องกัน CSRF
php_value session.cookie_samesite "Strict"
session.save_path ให้ชี้ไปยังโฟลเดอร์ที่กำหนดเอง ต้องสร้างโฟลเดอร์นั้นก่อนผ่าน File Manager ใน cPanel และตรวจสอบว่า PHP มีสิทธิ์เขียนไฟล์ในโฟลเดอร์นั้นตั้งค่า Cookies อย่างปลอดภัยใน PHP
สำหรับ Cookies ที่สร้างเองด้วย PHP ควรใช้ฟังก์ชัน setcookie() พร้อมตั้งค่า Security Options ให้ครบถ้วน ตัวอย่างการสร้าง Cookie ที่ปลอดภัย:
<?php
// วิธีสร้าง Cookie ที่ปลอดภัย (PHP 7.3+)
$cookie_options = [
'expires' => time() + (86400 * 30), // 30 วัน
'path' => '/',
'domain' => 'yoursite.com',
'secure' => true, // ส่งผ่าน HTTPS เท่านั้น
'httponly' => true, // ป้องกัน JavaScript อ่าน Cookie
'samesite' => 'Strict' // ป้องกัน CSRF
];
setcookie('user_pref', 'theme_dark', $cookie_options);
// อ่านค่า Cookie
if (isset($_COOKIE['user_pref'])) {
$pref = htmlspecialchars($_COOKIE['user_pref']);
echo "ธีมที่เลือก: " . $pref;
}
// ลบ Cookie โดยตั้ง expires ให้เป็นอดีต
setcookie('user_pref', '', [
'expires' => time() - 3600,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
?>
การเพิ่มความปลอดภัยให้ Session บน Shared Hosting
บน Shared Hosting ความเสี่ยงหลักคือการที่ผู้ใช้รายอื่นอาจเข้าถึงไฟล์ Session ของเราได้หาก Session ถูกเก็บใน /tmp ร่วมกัน วิธีป้องกันที่ดีที่สุดคือ:
- เปลี่ยน Session Save Path ให้ชี้ไปยังโฟลเดอร์ภายใต้ home directory ของตัวเอง เช่น
/home/username/session_data - Regenerate Session ID ทุกครั้งที่มีการ login เพื่อป้องกัน Session Fixation Attack
- ตรวจสอบ User Agent เพื่อตรวจจับการขโมย Session
- กำหนดเวลาหมดอายุ ของ Session ให้สั้นเหมาะสม
ตัวอย่างโค้ดสำหรับการเริ่ม Session อย่างปลอดภัย ที่ควรใช้ทดแทน session_start() ธรรมดา:
<?php
function secure_session_start() {
// กำหนดค่าก่อน session_start()
ini_set('session.use_strict_mode', 1);
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);
ini_set('session.use_only_cookies', 1);
ini_set('session.cookie_samesite', 'Strict');
ini_set('session.gc_maxlifetime', 1800); // 30 นาที
session_start();
// Regenerate Session ID เพื่อป้องกัน Session Fixation
if (!isset($_SESSION['_initiated'])) {
session_regenerate_id(true);
$_SESSION['_initiated'] = true;
}
// ตรวจสอบ User Agent เพื่อป้องกันการขโมย Session
if (isset($_SESSION['_ua'])) {
if ($_SESSION['_ua'] !== md5($_SERVER['HTTP_USER_AGENT'])) {
// User Agent เปลี่ยน - อาจถูกขโมย Session
session_destroy();
session_start();
session_regenerate_id(true);
}
} else {
$_SESSION['_ua'] = md5($_SERVER['HTTP_USER_AGENT']);
}
// ตรวจสอบเวลา Session ไม่ได้ใช้งาน
if (isset($_SESSION['_last_activity'])) {
if (time() - $_SESSION['_last_activity'] > 1800) {
session_destroy();
session_start();
}
}
$_SESSION['_last_activity'] = time();
}
// ใช้งานแทน session_start()
secure_session_start();
?>
การตรวจสอบการตั้งค่า PHP Session ปัจจุบัน
ก่อนปรับแต่งใดๆ ควรตรวจสอบว่า PHP ของ Hosting ตั้งค่า Session ไว้อย่างไร สามารถทำได้โดยสร้างไฟล์ phpinfo.php ชั่วคราว แล้วค้นหาหัวข้อ session ใน cPanel หรือดูจากไฟล์ทดสอบง่ายๆ
phpinfo.php ออกจาก Hosting หลังจากตรวจสอบเสร็จแล้ว เพราะไฟล์นี้แสดงข้อมูลสำคัญของเซิร์ฟเวอร์ตรวจสอบว่า PHP Session ทำงานถูกต้อง
สร้างไฟล์ทดสอบชื่อ session_test.php แล้วอัปโหลดไปยัง Hosting เพื่อตรวจสอบการทำงาน:
<?php
// ไฟล์: session_test.php - ลบทิ้งหลังใช้งาน!
session_start();
// 1. ตรวจสอบว่า session_start() ทำงานได้
echo "<h3>1. Session Status</h3>";
echo "Session ID: " . session_id() . "<br>";
echo "Session Status: " . session_status() . " (2=active)<br>";
// 2. ทดสอบเขียนและอ่าน Session
$_SESSION['test_value'] = 'hello_' . time();
echo "<h3>2. Write/Read Test</h3>";
echo "Written: " . $_SESSION['test_value'] . "<br>";
// 3. ตรวจสอบ Session Save Path
echo "<h3>3. Session Configuration</h3>";
echo "Save Path: " . ini_get('session.save_path') . "<br>";
echo "GC Maxlifetime: " . ini_get('session.gc_maxlifetime') . " seconds<br>";
echo "Cookie HTTPOnly: " . ini_get('session.cookie_httponly') . "<br>";
echo "Cookie Secure: " . ini_get('session.cookie_secure') . "<br>";
echo "Use Only Cookies: " . ini_get('session.use_only_cookies') . "<br>";
echo "Use Strict Mode: " . ini_get('session.use_strict_mode') . "<br>";
// 4. ตรวจสอบ Cookie ที่ถูกส่ง
echo "<h3>4. Session Cookie</h3>";
echo "Cookie Name: " . session_name() . "<br>";
print_r(session_get_cookie_params());
// 5. ตรวจสอบว่าโฟลเดอร์ Session เขียนได้
echo "<h3>5. Save Path Writable</h3>";
$save_path = ini_get('session.save_path');
echo is_writable($save_path) ? "Writable: YES" : "Writable: NO (อาจทำให้ Session ไม่ทำงาน)";
?>
.htaccess ตามที่แนะนำข้างต้น และรีเฟรชหน้าเพื่อตรวจสอบอีกครั้ง อย่าลืมลบไฟล์ทดสอบออกหลังใช้งานแก้ปัญหาที่พบบ่อย
Error: "Warning: session_start(): Cannot send session cookie - headers already sent"
ข้อผิดพลาดนี้เกิดจากการมี output ก่อนเรียก session_start() ซึ่งอาจเป็นช่องว่าง บรรทัดว่าง หรือแม้แต่ BOM (Byte Order Mark) ที่ตัวแก้ไขโค้ดบางตัวเพิ่มโดยอัตโนมัติ
วิธีแก้: ตรวจสอบว่าบรรทัดแรกสุดของไฟล์คือ <?php โดยไม่มีช่องว่างหรืออักขระใดๆ ก่อนหน้า และ session_start() ต้องเป็นบรรทัดแรกที่ทำงาน ก่อน echo หรือ HTML ใดๆ หากยังพบปัญหา ลองเปิดใช้ Output Buffering:
<?php
ob_start(); // เปิด Output Buffer ก่อน
session_start();
// โค้ดที่เหลือ...
?>
Error: Session หายทุกครั้งที่เปิดหน้าใหม่
ปัญหานี้มักเกิดจาก Session Save Path ไม่มีสิทธิ์เขียน หรือ Cookie ถูกบล็อกโดยเบราว์เซอร์ ให้ตรวจสอบดังนี้:
- ตรวจสอบว่า
session.save_pathชี้ไปยังโฟลเดอร์ที่มีอยู่จริงและเขียนได้ - ตรวจสอบว่า
session.use_only_cookiesเปิดอยู่ - หากเว็บใช้ HTTPS ตรวจสอบว่า
session.cookie_secureตั้งค่าถูกต้อง - ลองเปลี่ยน Session Save Path ผ่าน .htaccess ไปยังโฟลเดอร์ภายใต้ home ของตัวเอง
Error: "Warning: session_start(): open(…) failed: No such file or directory"
ข้อผิดพลาดนี้เกิดเมื่อตั้งค่า session.save_path ชี้ไปยังโฟลเดอร์ที่ไม่มีอยู่ ให้สร้างโฟลเดอร์ผ่าน File Manager ใน cPanel ก่อน จากนั้นตั้งค่า Permission ของโฟลเดอร์นั้นเป็น 700 (เจ้าของอ่าน/เขียน/execute ได้เท่านั้น) เพื่อความปลอดภัย
Error: Session ไม่ทำงานเมื่อ Domain มี www และ non-www
หากเว็บเข้าได้ทั้ง www.yoursite.com และ yoursite.com Session Cookie อาจไม่ถูกแชร์ระหว่างสอง Domain นี้ วิธีแก้คือตั้งค่า session.cookie_domain หรือบังคับ redirect ไปยัง Domain เดียวผ่าน .htaccess และเพิ่มการตั้งค่าใน PHP:
<?php
// กำหนด Cookie Domain ให้รองรับทั้ง www และ non-www
ini_set('session.cookie_domain', '.yoursite.com'); // นำหน้าด้วย dot
session_start();
?>
Error: Session หมดอายุเร็วเกินไปบน Shared Hosting
บน Shared Hosting บางราย PHP มีการรัน Garbage Collection บ่อยมาก ทำให้ Session หมดอายุก่อนกำหนด วิธีแก้ที่ดีที่สุดคือเปลี่ยน Session Handler ให้เก็บข้อมูลในฐานข้อมูล MySQL แทน ซึ่งไม่ขึ้นกับ GC ของ PHP และจัดการได้ยืดหยุ่นกว่า
คำถามที่พบบ่อย
Q: Session และ Cookies มีขนาดข้อมูลที่เก็บได้ต่างกันไหม?
A: ใช่ Cookies มีขนาดจำกัดที่ประมาณ 4KB ต่อ Cookie และเบราว์เซอร์แต่ละตัวรับ Cookie ต่อ Domain ได้ไม่เกิน 20-50 รายการ ในขณะที่ Session เก็บข้อมูลบนเซิร์ฟเวอร์ ขนาดจึงขึ้นอยู่กับ Disk Space ของ Hosting เท่านั้น แต่ควรหลีกเลี่ยงการเก็บข้อมูลขนาดใหญ่ใน Session เพราะจะใช้หน่วยความจำมาก แนะนำให้เก็บเฉพาะ ID หรือ Key แล้วดึงข้อมูลจริงจากฐานข้อมูลแทน
Q: ต้องตั้งค่า session.cookie_secure = 1 ไหม ถ้าเว็บยังไม่มี SSL?
A: ไม่ควรตั้งค่า session.cookie_secure = 1 หากเว็บยังใช้ HTTP เพราะจะทำให้ Session ไม่ทำงานเลย เบราว์เซอร์จะปฏิเสธการตั้งค่า Cookie ที่มี Secure flag บน HTTP connection อย่างไรก็ตาม ทุกวันนี้ SSL ฟรีจาก Let's Encrypt ผ่าน cPanel ทำได้ง่ายมาก แนะนำให้เปิดใช้ SSL ก่อนแล้วค่อยเปิด cookie_secure
Q: ควรเก็บข้อมูลอะไรใน Session และอะไรใน Cookies?
A: ใน Session ควรเก็บข้อมูลที่ละเอียดอ่อน เช่น User ID, สิทธิ์การเข้าถึง, ตะกร้าสินค้า, Token ต่างๆ ส่วน Cookies เหมาะสำหรับข้อมูลที่ไม่ละเอียดอ่อนและต้องการให้คงอยู่หลังปิดเบราว์เซอร์ เช่น ภาษาที่ต้องการ, ธีม, การตั้งค่า UI ที่ไม่ส่งผลต่อความปลอดภัย หลักการง่ายๆ คือ ถ้าข้อมูลนั้นถูกขโมยแล้วเกิดความเสียหาย ให้เก็บใน Session เสมอ