PHP: การจัดเก็บ 'วัตถุ' ภายใน $ _SESSION


188

ฉันเพิ่งค้นพบว่าจริง ๆ แล้วฉันสามารถเก็บวัตถุใน $ _SESSIONและฉันคิดว่ามันค่อนข้างเท่เพราะเมื่อฉันข้ามไปยังหน้าอื่นฉันยังมีวัตถุของฉัน ตอนนี้ก่อนที่ผมจะเริ่มใช้วิธีการนี้ผมอยากจะดูว่ามันเป็นจริงเช่นความคิดที่ดีหรือหากมีข้อผิดพลาดที่อาจเกิดขึ้นที่เกี่ยวข้อง

ฉันรู้ว่าถ้าฉันมีจุดเข้าเดียวฉันไม่จำเป็นต้องทำอย่างนั้น แต่ฉันไม่ได้อยู่ที่นั่นดังนั้นฉันไม่มีจุดเข้าเดียวและฉันอยากเก็บวัตถุของฉันเพราะฉันไม่ ' จะไม่สูญเสียสถานะของฉันเช่นนั้น (ตอนนี้ฉันได้อ่านแล้วว่าฉันควรเขียนโปรแกรมเว็บไซต์ไร้สัญชาติ แต่ฉันยังไม่เข้าใจแนวคิดดังกล่าว)

ดังนั้นในระยะสั้น : การเก็บวัตถุในเซสชันมีปัญหาหรือไม่?


แก้ไข:

สรุปชั่วคราว : ตอนนี้ฉันเข้าใจแล้วว่ามันน่าจะดีกว่าที่จะสร้างวัตถุใหม่แม้ว่ามันจะเกี่ยวข้องกับการสืบค้นฐานข้อมูลอีกครั้ง

คำตอบเพิ่มเติมอาจอธิบายเพิ่มเติมในแง่มุมนั้นอีกเล็กน้อย!


13
ฉันโง่แค่ไหนในปี 2551 :-)
markus

49
แต่คำถามที่มีประโยชน์สำหรับ 'โง่เหมือนเราในปี 2014: D
Momin Al Aziz

3
คำถามที่ดีมากที่คุณถาม markus .. :) ฉันอ่านมันวันนี้;)
gkd

1
คุณไม่ได้โง่! คุณถามสิ่งที่ฉันกำลังจะถามและทำให้ฉันแข็ง 10 ปีต่อมา!
toddmo

ดีฉันเดาคุณเพิ่งช่วยฉันจากการถามคำถามโง่ ๆ ในปี 2019
Maxwell

คำตอบ:


133

ฉันรู้ว่าหัวข้อนี้เก่า แต่ปัญหานี้ยังคงเกิดขึ้นและยังไม่ได้รับการแก้ไขเพื่อความพึงพอใจของฉัน:

ไม่ว่าคุณจะบันทึกวัตถุใน $ _SESSION หรือสร้างใหม่ผ้าทั้งหมดขึ้นอยู่กับข้อมูลที่ซ่อนอยู่ในเขตข้อมูลในแบบฟอร์มที่ซ่อนอยู่หรือสอบถามซ้ำวัตถุเหล่านั้นจากฐานข้อมูลในแต่ละครั้งคุณกำลังใช้สถานะ HTTP นั้นไร้สัญชาติ (มากกว่าหรือน้อยกว่า แต่เห็น GET vs. PUT) แต่เกือบทุกสิ่งที่ทุกคนสนใจกับแอพพลิเคชั่นบนเว็บนั้นจำเป็นต้องมีการดูแลรักษาที่ไหนสักแห่ง การทำราวกับว่าการผลักดันรัฐให้กลายเป็นซอกและซอกเล็กซอกน้อยไปสู่การชนะทางทฤษฎีบางอย่างนั้นผิด รัฐคือรัฐ หากคุณใช้สถานะคุณจะสูญเสียความได้เปรียบด้านเทคนิคต่างๆที่ได้รับจากการไร้สัญชาติ นี่ไม่ใช่สิ่งที่จะทำให้คุณนอนไม่หลับเว้นแต่คุณจะรู้ล่วงหน้าว่าคุณควรจะนอนไม่หลับ

โดยเฉพาะอย่างยิ่งฉัน flummoxed โดยพรที่ได้รับจากการโต้เถียง "คำสาปแช่งคู่" นำออกมาโดยแฮงค์เกย์ OP สร้างระบบอีคอมเมิร์ซแบบกระจายและแบบกระจายสมดุลหรือไม่? ฉันเดาไม่ และฉันจะวางตัวต่อไปว่าการทำอันดับผู้ใช้ $ ของเขาเป็นประจำหรืออะไรก็ตามจะไม่ทำลายเซิร์ฟเวอร์ของเขาเกินกว่าจะซ่อม คำแนะนำของฉัน: ใช้เทคนิคที่เหมาะสมกับใบสมัครของคุณ วัตถุใน $ _SESSION นั้นใช้ได้ภายใต้ข้อควรระวังสามัญสำนึก หากแอปของคุณกลายเป็นสิ่งที่แข่งขันกับ Amazon ในการรับส่งข้อมูลคุณจะต้องปรับตัวอีกครั้ง นั่นคือชีวิต.


16
คำตอบที่ดีได้รวมเอาความคิดของตัวเองเป็นจำนวนมากเนื่องจากฉันได้อ่านสิ่งนี้ อินเทอร์เน็ตที่ทันสมัยต้องการสถานะ ในขณะที่บางแอปพลิเคชั่นไม่ต้องการสถานะและเหมาะสมในการไร้สัญชาติ แต่อินเทอร์เน็ตสมัยใหม่อาศัยระบบที่มากเกินไปที่ยึดตามสถานะ (AKA: การเข้าสู่ระบบ!) ที่จะยอมแพ้! เทพเจ้าที่ยิ่งใหญ่ของอินเทอร์เน็ตได้รวมแนวคิดพื้นฐานไว้เป็นเวลาหลายปีในรูปแบบของคุกกี้และในระดับพื้นฐานพวกเขาได้เพิ่มมันในรูปแบบของการจัดเก็บในท้องถิ่นใน HTML อาจเหมาะสมที่จะหลีกเลี่ยงการใช้สถานะมากเกินไปในบางแอปพลิเคชัน แต่บางรายการ! = ทั้งหมด!
RonLugge

เมื่อฉันถามคำถามนั้นหลังจากมนุษย์คิดค้นไฟฉันไม่รู้อะไรมากมายที่ฉันรู้วันนี้ ... ซึ่งก็เช่นกัน ในระหว่างนี้ฉันจะบอกว่าอาจมีกรณีการใช้งานที่ดีอยู่บ้าง แต่โดยทั่วไปฉันจะหาวิธีแก้ปัญหาอื่นก่อน ยังคงทำเครื่องหมายว่านี่เป็นคำตอบที่ได้รับการยอมรับใหม่เนื่องจากคำตอบอื่น ๆ นั้นเป็นหมวดหมู่
markus

คำตอบน้อยมากที่ทำให้ฉันหัวเราะออกมาดัง ๆ สิ่งนี้ทำ Bravo +1
toddmo

114

ไม่เป็นไรตราบใดที่มีการเรียก session_start () การประกาศ / คำจำกัดความของคลาสได้ถูกพบโดย PHP หรือสามารถพบได้โดย autoloader ที่ติดตั้งไว้แล้ว ไม่เช่นนั้นจะไม่สามารถทำการซีเรียลไลซ์วัตถุออกจากที่จัดเก็บเซสชันได้


12
ขอบคุณ! นั่นแก้ไขข้อผิดพลาดสำหรับฉัน: D
Matt Ellen

ฉันสมมติว่าปัญหานี้สามารถหลีกเลี่ยงได้หากคุณมี__autoload()ฟังก์ชั่นที่เหมาะสม
Langel

ในการ unserializing วัตถุต่อเนื่องเราจะต้องเพิ่มคำจำกัดความของชั้นเรียน ??? ในช่วงเวลาของการทำให้เป็นอันดับวัตถุมันต้องการคำจำกัดความของชั้นเรียนที่ฉันเห็นด้วย แต่ฉันต้องเพิ่มคำจำกัดความของชั้นยังอยู่ในไฟล์ที่ฉันต้อง unserialize วัตถุที่เป็นอนุกรม?
Rajesh Paul

35

HTTP เป็นโปรโตคอลไร้สัญชาติด้วยเหตุผล เซสชันเชื่อมสถานะลงบน HTTP ในฐานะที่เป็นกฎง่ายๆให้หลีกเลี่ยงการใช้สถานะเซสชัน

UPDATE: ไม่มีแนวคิดของเซสชันที่ระดับ HTTP; เซิร์ฟเวอร์จัดเตรียมสิ่งนี้โดยให้ ID เฉพาะแก่ลูกค้าและแจ้งให้ลูกค้าส่งอีกครั้งในทุกคำขอ จากนั้นเซิร์ฟเวอร์จะใช้ ID นั้นเป็นกุญแจลงใน hashtable ขนาดใหญ่ของวัตถุเซสชัน เมื่อใดก็ตามที่เซิร์ฟเวอร์ได้รับคำขอมันจะค้นหาข้อมูลเซสชันจากแฮชเท็กซ์ของวัตถุเซสชันตาม ID ที่ไคลเอนต์ส่งมาพร้อมกับคำขอ งานพิเศษทั้งหมดนี้เป็นสองเท่าของความสามารถในการปรับขยายได้ (เหตุผลใหญ่ HTTP คือไร้สัญชาติ)

  • Whammy One: มันลดงานที่เซิร์ฟเวอร์เดียวทำได้
  • Whammy Two: มันยากที่จะขยายออกเพราะตอนนี้คุณไม่สามารถส่งคำขอไปยังเซิร์ฟเวอร์เก่า ๆ - พวกเขาไม่ได้มีเซสชันเดียวกัน คุณสามารถปักหมุดคำขอทั้งหมดด้วย ID เซสชันที่กำหนดไปยังเซิร์ฟเวอร์เดียวกัน นั่นไม่ใช่เรื่องง่ายและเป็นเพียงจุดเดียวของความล้มเหลว (ไม่ใช่สำหรับระบบโดยรวม แต่สำหรับกลุ่มผู้ใช้ของคุณ) หรือคุณสามารถแบ่งปันที่เก็บเซสชันกับเซิร์ฟเวอร์ทั้งหมดในคลัสเตอร์ แต่ตอนนี้คุณมีความซับซ้อนมากขึ้น: หน่วยความจำที่เชื่อมต่อกับเครือข่าย, เซิร์ฟเวอร์เซสชันแบบสแตนด์อะโลนเป็นต้น

จากข้อมูลทั้งหมดที่คุณให้ไว้ในเซสชันยิ่งส่งผลกระทบต่อประสิทธิภาพการทำงานมากขึ้นเท่านั้น (เมื่อ Vinko ชี้ให้เห็น) เช่นเดียวกับที่ Vinko ชี้ให้เห็นถ้าวัตถุของคุณไม่ได้ต่อเนื่องเซสชันจะทำงานผิดปกติ ดังนั้นตามกฎง่ายๆหลีกเลี่ยงการวางมากกว่าที่จำเป็นอย่างยิ่งในเซสชั่น

@Vinko คุณสามารถแก้ไขสถานะการจัดเก็บเซิร์ฟเวอร์ได้โดยการฝังข้อมูลที่คุณกำลังติดตามในการตอบกลับที่คุณส่งกลับมาและให้ลูกค้าส่งอีกครั้งเช่นการส่งข้อมูลลงในอินพุตที่ซ่อนอยู่ หากคุณต้องการการติดตามสถานะเซิร์ฟเวอร์จริง ๆควรเป็นข้อมูลสำรองของคุณ

(Vinko เพิ่ม: PHP สามารถใช้ฐานข้อมูลสำหรับการจัดเก็บข้อมูลเซสชันและการที่ลูกค้าส่งข้อมูลใหม่ทุกครั้งอาจแก้ปัญหาความสามารถในการปรับขนาดได้ แต่เปิดประเด็นความปลอดภัยขนาดใหญ่ที่คุณต้องใส่ใจในตอนนี้ว่าลูกค้ากำลังควบคุมทั้งหมด รัฐของคุณ)


1
ไม่มีแนวคิดของเซสชันที่ระดับ HTTP; เซิร์ฟเวอร์จัดเตรียมสิ่งนี้โดยให้ ID เฉพาะแก่ลูกค้าและแจ้งให้ลูกค้าส่งอีกครั้งในทุกคำขอ จากนั้นเซิร์ฟเวอร์จะใช้ ID นั้นเป็นกุญแจลงใน hashtable ขนาดใหญ่ของวัตถุเซสชัน จะยังคง ...
แฮงค์เกย์

1
เมื่อใดก็ตามที่เซิร์ฟเวอร์ได้รับคำขอมันจะค้นหาข้อมูลเซสชันจากแฮชเท็กซ์ของวัตถุเซสชันตาม ID ที่ไคลเอนต์ส่งมาพร้อมกับคำขอ งานพิเศษทั้งหมดนี้เป็นสองเท่าของความสามารถในการขยายขีดความสามารถ จะยังคง ...
แฮงค์เกย์

1
ฉันสงสัยว่าคุณจะใช้งานที่ซับซ้อนผ่าน HTTP โดยไม่ต้องเชื่อมรัฐอย่างใด
Vinko Vrsalovic

3
โปรดแก้ไขคำตอบของคุณเพื่อรวมความคิดเห็นทั้งหมดเหล่านี้ มันง่ายต่อการอ่านและดีกว่าสำหรับ wiki และ anyways ฉันไม่สามารถเลือกคำตอบของคุณเป็นคำตอบที่ยอมรับได้ถ้าทุกสิ่งที่สำคัญอยู่ในความคิดเห็น ขอบคุณ!
markus

6
"หนึ่ง whammy" ฉันหวังว่าฉันจะลงคะแนนได้มากกว่านี้ รู้จังหวะของคุณ การอ้างอิงหน่วยความจำมีค่าใช้จ่าย 100 นาโนวินาทีหรือ 0.0001 มิลลิวินาที ดังนั้นการค้นหาบน hashtable ที่เก็บไว้ในหน่วยความจำหลักอย่างแท้จริงจึงไม่มีค่าใช้จ่าย ไม่O(1)บอกคุณว่าอะไร? @whammy สอง: อย่าสุ่มเส้นทางไปยังเซิร์ฟเวอร์สุ่มทั้งหมดหรือไม่ ทำ round robin และคอยกำหนดเส้นทางไปยังเซิร์ฟเวอร์เดียวกันจากผู้ใช้รายเดียวกัน นี่มันว้าวชัดสุด ๆ คุณต้องกลับไปอ่านหนังสือของคุณพร้อมกับ upvotes ทั้งหมด 30+
Toskan

19
  • วัตถุที่ไม่สามารถต่อเนื่องกัน (หรือมีสมาชิกที่ไม่สามารถระบุตัวตนได้) จะไม่ออกมาจาก $ _SESSION ตามที่คุณคาดหวัง
  • เซสชันขนาดใหญ่ทำให้เกิดภาระบนเซิร์ฟเวอร์ (ซีเรียลไลซ์เซชั่นและดีซีเรียลไลซ์เมกะไบต์ของรัฐในแต่ละครั้งมีราคาแพง)

นอกเหนือจากที่ฉันเคยเห็นไม่มีปัญหา


9

จากประสบการณ์ของฉันโดยทั่วไปแล้วมันไม่คุ้มกับอะไรที่ซับซ้อนกว่า StdClass ที่มีคุณสมบัติบางอย่าง ค่าใช้จ่ายในการยกเลิกการบันทึกเป็นมากกว่าการสร้างขึ้นใหม่จากฐานข้อมูลโดยใช้ตัวระบุที่เก็บเซสชัน มันดูเท่ห์ แต่ (เช่นเคย) การทำโปรไฟล์เป็นกุญแจสำคัญ


ความคิดเห็นใด ๆ เกี่ยวกับการแสดงระหว่างการสืบค้นตารางข้อมูล 5x2 ทุกคำขอเทียบกับการแคชผลลัพธ์ในเซสชันและการใช้งานนั้น?
musicliftsme

6

ฉันขอแนะนำว่าอย่าใช้สถานะจนกว่าคุณจะต้องการมันอย่างแน่นอน หากคุณสามารถสร้างวัตถุใหม่โดยไม่ต้องใช้เซสชันให้ทำ การมีสถานะต่างๆในเว็บแอปพลิเคชันของคุณทำให้แอปพลิเคชันมีความซับซ้อนมากขึ้นสำหรับคำขอทุกครั้งที่คุณต้องดูสถานะของผู้ใช้สิ่งที่พบบ่อยครั้งที่คุณไม่สามารถหลีกเลี่ยงการใช้เซสชันได้ (ตัวอย่าง: ผู้ใช้ การใช้งานเว็บ) สุดท้ายฉันขอแนะนำให้รักษาวัตถุเซสชันของคุณให้มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้เนื่องจากส่งผลกระทบต่อประสิทธิภาพในการทำให้เป็นอันดับและยกเลิกการเรียงวัตถุขนาดใหญ่


ดังนั้นจะเป็นการดีกว่าถ้าจะสร้างวัตถุใหม่รวมถึงการทำแบบสอบถามฐานข้อมูลทั้งหมดอีกครั้งหรือไม่ เพราะหนึ่งในความคิดของฉันในการทำเช่นนี้คือฉันไม่ต้องค้นหา db สำหรับสิ่งเดียวกันอีก
markus

3
หากเป็นสิ่งสำคัญสำหรับคุณที่จะไม่สืบค้นฐานข้อมูลอีกครั้งจะใช้แคชแทนการเก็บไว้ในเซสชัน แต่ได้โปรดก่อนที่จะทำอะไรบางอย่างเช่นการสร้างแคชตรวจสอบว่าเป็นผลงานที่ยอดเยี่ยมจริงๆหรือไม่
จอห์นนี่

ขอบคุณฉันคิดว่ามันไม่จริง ฉันควรสอบถามอีกครั้ง
markus

4

คุณจะต้องจำไว้ว่าประเภททรัพยากร (เช่นการเชื่อมต่อฐานข้อมูลหรือตัวชี้ไฟล์) จะไม่คงอยู่ระหว่างการโหลดหน้าและคุณจะต้องสร้างสิ่งเหล่านี้ขึ้นมาใหม่

พิจารณาขนาดของเซสชันขึ้นอยู่กับวิธีจัดเก็บคุณอาจมีข้อ จำกัด ด้านขนาดหรือปัญหาเวลาในการตอบสนอง


0

ฉันจะนำขึ้นเมื่ออัพเกรดห้องสมุดซอฟต์แวร์ - เราอัพเกรดซอฟต์แวร์ของเราและรุ่นเก่ามีออบเจ็กต์ในเซสชันด้วยชื่อคลาสของซอฟต์แวร์ V1 ซอฟต์แวร์ใหม่หยุดทำงานเมื่อพยายามสร้างวัตถุที่อยู่ในเซสชั่น - เป็น V2 ซอฟต์แวร์ไม่ได้ใช้คลาสเดียวกันนั้นอีกต่อไปมันหาไม่พบ เราต้องใส่รหัสแก้ไขเพื่อตรวจจับวัตถุเซสชั่นลบเซสชั่นหากพบโหลดหน้าใหม่ ความเจ็บปวดที่ยิ่งใหญ่ที่สุดในตอนแรกก็คือคุณกำลังสร้างบั๊กนี้ขึ้นมาใหม่เมื่อมันถูกรายงานครั้งแรก (ทุกคนคุ้นเคยกันดีว่า "ใช้ได้กับฉันด้วย" :) เพราะมันส่งผลกระทบต่อคนที่เข้าและออกระบบเก่าและใหม่เท่านั้น งานที่เราค้นพบก่อนเปิดตัวเนื่องจากผู้ใช้ของเราทุกคนจะมีตัวแปรเซสชันเก่าในเซสชันของพวกเขาและอาจเกิดความผิดพลาดได้ทั้งหมด

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.