Friday, February 19, 2016

$_POST[] จำกัดการรับค่าใน PHP

มีปัญหาไม้เบื่อไม้เมาระหว่าง โปรแกรมเมอร์ กับ คนทำระบบ มานานหลายเดือน สาเหตุที่แก้ไขล่าช้าก็เพราะมีงานอื่นที่สำคัญกว่า และแก้ไขกันอีกทีในภายหลัง

ปัญหาเริ่มจาก ตารางรับค่าของโปรแกรมหนึ่ง มี input 200 ร้อยกว่ารายการ รวมที่ซ่อนไว้แล้ว เมื่อกดปุ่ม Submit แล้ว จะมีข้อความเตือนออกทางหน้าจอว่าค้นหา index ที่ชื่อ data ไม่พบ


Notice: Undefined index: data in /var/sentora/hostdata/xxx/ public_html/yyy_xxx_com/controllers/price.php on line 124

ตัวอักษรสีแดงคือ ตัวแปร ซึ่งก็ทำให้งงนิดหน่อยเมื่ออ่านครั้งแรก เพราะอ่านแล้วเข้าใจว่า หาข้อมูลไม่ได้ แต่จริงๆ แล้วในข้อความเตือนนั้นแจ้งว่า ไม่มีข้อมูลในอะเรย์ที่ชื่อ data เพราะเขาตั้งชื่อเป็น data นั่นแหละ

พลอยทำให้คิดถึงการเขียนโปรแกรมในสมัยก่อน การตั้งชื่อตัวแปรต้องกำหนดให้ดี ไม่ให้คนที่ดูภายหลังสับสน แต่เดี๋ยวนี้คงไม่มีใครเคร่งครัดแล้วกระมัง

ตามที่โปรแกรมเมอร์เขาระบุมาว่า ต้องกำหนด max_input_vars จากเดิม 1500 เป็น 3000 ก็ดำเนินการให้แล้วก็ยังใช้ไม่ได้ ก็ลองให้เขาหาดูว่าโปรแกรมติดขัดตรงไหน แต่สุดท้ายก็ไม่สำเร็จเพราะเขายืนยันว่า ลองในเครื่อง (Windows) แล้วก็ใช้ได้ และลองในเซิร์ฟเวอร์ของบริษัทที่ตนเองอยู่ก็ไม่มีปัญหา จึงขอไฟล์คอนฟิก php.ini มาดู นานเหมือนกันกว่าจะได้ไฟล์มา คงเพราะยุ่งกับเรื่องอื่น

สุดท้ายมีโอกาสและได้รับไฟล์จากเซิร์ฟเวอร์ที่บอกว่าใช้ได้มาเปรียบเทียบ

ตอนแรกกะจะเอาง่ายแบบลวกมาม่า แต่เกรงจะดราม่า เพราะคิดไว้แล้วว่า environment ต้องแตกต่างกัน ถึงแม้จะเป็นเซิร์ฟเวอร์แบบเดียวกันแต่ไม่น่าจะมีคอนฟิกเหมือนกัน ก็เปิดไฟล์มานั่งไล่ดูก่อน

บิงโก!!! เซิร์ฟเวอร์ที่เอามาเทียบนั้นเป็น Windows แต่เซิร์ฟเวอร์ที่มีปัญหาเป็น Linux แน่นอนปัญหาเรื่องความปลอดภัย ความเคร่งครัดทางการเขียนโปรแกรมย่อมแตกต่างกัน

คราวนี้ถือวิสาสะแอบเข้าไปเปิดซอร์สโค้ดเขาดูเสียเลยว่า ข้อมูลที่รับจากฟอร์มมาแบบไหน ขนาดไหนก็เริ่มบรรทัดที่ 124 ที่เกิดข้อความเตือนซึ่งมีการเรียกตัวแปรอะเรย์ชื่อ data มาใช้งาน (จากเดิมเคยขอดูแล้วครั้งหนึ่ง ก็ไม่ได้รับข้อมูลที่กระจ่าง เพราะถามไปก็ได้รับคำตอบงงๆ กลับมา จึงดูด้วยตัวเองดีกว่า)
จากซอร์สโค้ดก็เห็นมีความพยายาม debug และกำหนดค่า max_input_vars ไว้แล้ว










จากรูปจะเห็นว่ามีความพยายาม debug และกำหนดค่าใน cookie แล้วแต่ก็ยังไม่สำเร็จ สุดท้ายผู้เขียนก็ลองเปิดเข้าไปดู var_dump($_POST); เพื่อดูว่าข้อมูลที่ได้กลับมาเป็นอย่างไร โดย Submit ตารางที่มีน้อยและตารางที่มีปัญหา

ผลลัพธ์ที่ได้
ตารางที่ไม่มีปัญหามีอะเรย์ประมาณ

ประมาณ 3 ร้อยกว่ารายการ 755 หาร 2 
ตารางที่มีปัญหามีอะไรเกิน 1000 รายการ
ตารางที่มีปัญหาส่งข้อมูลมาเกิน 1,000 รายการ 2015 หาร 2



ถึงตรงนี้ก็ทำให้สามารถพรุ่งเป้าไปที่จำนวน Array ของ Input หรือ $_POST ว่าทำไมยังจำกัดไว้ที่ 1,000 ทั้งๆ ที่กำหนด max_input_vars = 3000 แล้วก็ตาม

เมื่อดูจากไฟล์ php.ini ที่ได้จากเซิร์ฟเวอร์ของโปรแกรมเมอร์ (Windows) ก็ไม่แตกต่างมากนัก นอกจาก environment อื่นๆ แต่ไม่เกี่ยวกับ input หรือการรับค่า ตัวแปร Array

ลองหาอ่านในเว็บส่วนใหญ่ก็แก้ไขที่ max_input_vars จาก 1000 เป็น 3000, 4000 หรือ 5000 กันทั้งนั้น แต่ไปเจอใน stackoverflow.com ซึ่งมีคนหนึ่งมาคอมเม้นท์เกี่ยวกับ suhosin ซึ่งเป็น patch ของ Linux ที่ใช้ทำเป็น VPS ทำให้มองเห็นแสงสว่างนิดๆ

คอมเม้นท์ที่แนะนำให้ดูค่าของ suhosin
และเมื่อเข้าไปอ่านการตั้งค่าของ suhosin ก็ถึงบางอ้อว่า ข้อจำกัด 1,000 รายการมาจากไหน

suhosin กำหนดค่า pos.max_vars ไว้ที่ 1000


จากนั้นก็เข้าไปแก้ไขที่ php.ini แรกเริ่มเข้าไปปิดการโหลด suhosin.so ก่อน แล้วทดสอบข้อความเตือนนั้นหายเป็นปลิดทิ้ง แต่ก็ไม่เป็นผลดีต่อ VPS แน่ๆ จึงกลับเข้าไปแก้ไขโดยเพิ่มการตั้งค่าเข้าไป


เพิ่มข้อความในกรอบสี่เหลี่ยมสีแดงเข้าไป


[suhosin]suhosin.request.max_vars = 1500suhosin.post.max_vars = 1500

หลังจากเปลี่ยนแปลงใน php.ini ก็ต้องรีสตาร์ท apache กันสักหน่อยผู้เขียนใช้ Ubuntu ก็ใช้คำสั่ง

/etc/init.d/apache2 restart
เป็นอันเรียบร้อยข้อมูลที่ป้อนมาได้รับครบถ้วนข้อความเตือนหายไปเรียบร้อย

การแก้ไขปัญหาก็จบลุล่วงด้วยดีจากข้อมูลใน stackoverflow.com ซึ่งเป็นสถานที่ผู้เขียนคิดถึงก่อนเป็นอันดับแรกเมื่อเจอปัญหา ซึ่งเกือบทุกครั้งจะได้คำตอบจากที่นี่เช่นกัน ดังนั้นหากเจอปัญหาอย่าเพิ่งท้อ และอย่าเพิ่งโยนให้คนอื่น เพราะหากเราเข้าใจ เราค้นหาปัญหาเจอมันจะทำให้เราเก่งมากขึ้น

บางคนคิดว่าไม่ใช่หน้าที่ ไม่ใช่ภาระของตนเอง จริงๆ แล้วโปรแกรมเมอร์ควรจะรู้เรื่องเน็ตเวิร์คหรือหลักการของเซิร์ฟเวอร์บ้างย่อมทำให้ได้เปรียบในการพัฒนาระบบ

แต่เดี๋ยวนี้ผู้เขียนมักเจอโปรแกรมเมอร์รุ่นใหม่ที่ชอบผลักภาระให้คนอื่นโดยคิดว่าไม่ใช่หน้าที่ ไม่ใช่สิ่งที่ตัวเองต้องรับผิดชอบ ก็ไม่เป็นไรถือว่าเป็นสิทธิ์ แต่อยากฝากไว้นิดหนึ่งว่า ถ้าคิดเช่นนั้นก็เป็นได้แค่โปรแกรมเมอร์เขียนเว็บเพจตลอดชีวิต ไม่สามารถพัฒนาข้ามไปพัฒนาโปรแกรมแบบอื่นๆ ที่ซับซ้อนได้อย่างแน่นอน เพราะโลกการเขียนโปรแกรมมันกว้างกว่า php+mysql+javascript  มาก

และประสิทธิภาพของโปรแกรมจะดีหรือไม่อยู่ที่การเขียนโปรแกรมให้สอดคล้องกับระบบสภาพแวดล้อม ซึ่งไม่มีใครสามารถกำหนดสภาพแวดล้อมให้พอดีกับโปรแกรมของเราได้หากเราไม่ได้แจ้งให้เขาปรับปรุงตามที่เราต้องการ... ยกเว้นอย่างเดียว... ไม่รู้จะปรับปรุงอย่างไร เขาสร้างบ้านอะไรให้ก็อยู่อย่างนั้นแหละ... แล้วแต่จะเลือกครับ

No comments:

Post a Comment