PHP: Menyimpan 'objek' di dalam $ _SESSION

188

Saya baru tahu bahwa saya benar-benar dapat menyimpan objek di $ _SESSION dan saya merasa cukup keren karena ketika saya melompat ke halaman lain saya masih memiliki objek saya. Sekarang sebelum saya mulai menggunakan pendekatan ini, saya ingin mencari tahu apakah itu benar-benar ide yang bagus atau apakah ada potensi jebakan yang terlibat.

Saya tahu bahwa jika saya memiliki satu titik masuk saya tidak perlu melakukan itu tetapi saya belum sampai di sana sehingga saya tidak memiliki satu titik masuk dan saya benar-benar ingin menyimpan objek saya karena saya tidak punya Aku tidak kehilangan kondisiku seperti itu. (Sekarang saya juga membaca bahwa saya harus memprogram situs stateless tapi saya belum mengerti konsep itu.)

Jadi singkatnya : Apakah boleh menyimpan objek dalam sesi, apakah ada masalah dengannya?


Edit:

Ringkasan sementara : Sekarang saya mengerti bahwa mungkin lebih baik untuk membuat ulang objek walaupun itu melibatkan pencarian kembali database.

Jawaban lebih lanjut mungkin bisa menguraikan aspek itu sedikit lebih banyak!

markus
sumber
13
Betapa 'bodohnya' saya pada 2008 :-)
markus
49
tapi pertanyaan yang berguna untuk 'orang bodoh seperti kita pada tahun 2014: D
Momin Al Aziz
3
Pertanyaan yang sangat bagus Anda telah meminta markus .. :) Saya membacanya hari ini;)
gkd
1
Kamu tidak bodoh! Anda bertanya apa yang akan saya tanyakan dan membuat saya solid, 10 tahun kemudian!
toddmo
well, saya kira Anda baru saja menyelamatkan saya dari mengajukan pertanyaan bodoh pada 2019
Maxwell

Jawaban:

133

Saya tahu topik ini sudah lama, tetapi masalah ini terus muncul dan belum ditujukan untuk kepuasan saya:

Apakah Anda menyimpan objek dalam $ _SESSION, atau merekonstruksi seluruh kain berdasarkan data yang disimpan di bidang formulir tersembunyi, atau meminta kembali objek tersebut dari DB setiap kali, Anda menggunakan status. HTTP tidak memiliki kewarganegaraan (lebih atau kurang; tetapi lihat MENDAPATKAN vs. PUT) tetapi hampir semua orang yang peduli dengan aplikasi web memerlukan status untuk dipertahankan di suatu tempat. Bertingkah seolah-olah mendorong negara ke sudut dan celah sama dengan semacam kemenangan teoretis adalah salah. Negara adalah negara. Jika Anda menggunakan status, Anda kehilangan berbagai keuntungan teknis yang diperoleh dengan menjadi tanpa kewarganegaraan. Ini bukan sesuatu untuk kurang tidur kecuali jika Anda tahu sebelumnya bahwa Anda harus kehilangan tidur di atasnya.

Saya terutama bingung oleh berkat yang diterima oleh argumen "whammy ganda" yang diajukan oleh Hank Gay. Apakah OP membangun sistem e-commerce terdistribusi dan seimbang? Dugaan saya adalah tidak; dan saya lebih lanjut akan berpendapat bahwa membuat serial $ User class-nya, atau apa pun, tidak akan melumpuhkan servernya yang tidak dapat diperbaiki. Saran saya: gunakan teknik yang masuk akal untuk aplikasi Anda. Objek dalam $ _SESSION baik-baik saja, tunduk pada tindakan pencegahan akal sehat. Jika aplikasi Anda tiba-tiba berubah menjadi sesuatu yang menyaingi Amazon dalam lalu lintas yang dilayani, Anda perlu beradaptasi ulang. Itulah hidup.

shanusmagnus
sumber
16
Jawaban yang bagus menggabungkan banyak pikiran saya sendiri ketika saya sudah membaca ini. Internet modern membutuhkan keadaan. Sementara beberapa aplikasi tidak memerlukan status dan masuk akal untuk dibuat tanpa kewarganegaraan, internet modern bergantung pada terlalu banyak sistem yang didasarkan pada keadaan (AKA: Login!) Untuk menyerah begitu saja! Para Dewa Besar internet bahkan telah memasukkan konsep dasar itu selama bertahun-tahun dalam bentuk cookie, dan pada tingkat dasar mereka menambahkannya dalam bentuk penyimpanan lokal dalam HTML. Mungkin masuk akal untuk menghindari penggunaan negara berlebihan di beberapa aplikasi, tetapi beberapa! = Semua!
RonLugge
Nah, ketika saya mengajukan pertanyaan itu tak lama setelah manusia menemukan api, saya tidak tahu banyak hal yang saya tahu hari ini ... yang juga bagus. Sementara itu saya akan mengatakan mungkin ada beberapa kasus penggunaan yang baik tetapi umumnya saya akan mencari solusi lain terlebih dahulu. Masih menandainya sebagai jawaban yang baru diterima karena jawaban yang lain adalah kategoris.
markus
Sangat sedikit jawaban yang membuatku tertawa terbahak-bahak. Yang ini. Bravo +1
toddmo
114

tidak apa-apa asalkan pada saat panggilan session_start () dibuat, deklarasi / definisi kelas telah ditemukan oleh PHP atau dapat ditemukan oleh autoloader yang sudah diinstal. jika tidak, ia tidak akan dapat membatalkan deserialisasi objek dari sesi store.

kejam
sumber
12
Terima kasih! Itu memperbaiki bug untuk saya: D
Matt Ellen
Saya berasumsi bahwa masalah ini dapat dihindari jika Anda memiliki __autoload()fungsi yang tepat .
Langel
Dalam membatalkan pengunaan objek serial apakah kita harus menambahkan definisi kelas ??? Pada saat membuat serialisasi objek, ia membutuhkan definisi kelas, yang saya setujui, tetapi apakah saya harus menambahkan definisi kelas juga dalam file di mana saya harus menghapus serial objek?
Rajesh Paul
35

HTTP adalah protokol tanpa kewarganegaraan karena suatu alasan. Sesi mengelas status ke HTTP. Sebagai aturan praktis, hindari menggunakan status sesi.

UPDATE: Tidak ada konsep sesi di tingkat HTTP; server memberikan ini dengan memberikan ID unik kepada klien dan memberi tahu klien untuk mengirim ulang pada setiap permintaan. Kemudian server menggunakan ID itu sebagai kunci ke hashtable besar dari objek Sesi. Setiap kali server mendapat permintaan, ia mencari info Sesi dari hashtable objek sesi berdasarkan ID yang dikirimkan klien dengan permintaan. Semua pekerjaan ekstra ini adalah whammy ganda pada skalabilitas (alasan utama HTTP tidak memiliki kewarganegaraan).

  • Whammy One: Ini mengurangi pekerjaan yang bisa dilakukan oleh satu server.
  • Whammy Two: Membuat skala lebih sulit karena sekarang Anda tidak bisa hanya merutekan permintaan ke server lama - mereka tidak semua memiliki sesi yang sama. Anda dapat menyematkan semua permintaan dengan ID sesi yang diberikan ke server yang sama. Itu tidak mudah, dan itu adalah satu titik kegagalan (bukan untuk sistem secara keseluruhan, tetapi untuk sebagian besar pengguna Anda). Atau, Anda bisa berbagi penyimpanan sesi di semua server di cluster, tetapi sekarang Anda memiliki lebih banyak kerumitan: memori yang terpasang jaringan, server sesi yang berdiri sendiri, dll.

Mengingat semua itu, semakin banyak info yang Anda masukkan dalam sesi, semakin besar dampaknya pada kinerja (seperti yang ditunjukkan Vinko). Juga seperti yang ditunjukkan Vinko, jika objek Anda tidak dapat diubah serial, sesi akan bertingkah buruk. Jadi, sebagai aturan praktis, hindari menempatkan lebih dari yang benar-benar diperlukan dalam sesi.

@ Vinko Anda biasanya dapat mengatasi keadaan toko server dengan menyematkan data yang Anda lacak dalam respons yang Anda kirim kembali dan meminta klien mengirim ulang, misalnya, mengirimkan data ke dalam input tersembunyi. Jika Anda benar - benar membutuhkan pelacakan sisi-server, itu mungkin harus di datastore dukungan Anda.

(Vinko menambahkan: PHP dapat menggunakan database untuk menyimpan informasi sesi, dan meminta klien mengirimkan kembali data setiap kali dapat memecahkan masalah skalabilitas potensial, tetapi membuka kaleng besar masalah keamanan Anda harus memperhatikan sekarang bahwa klien mengendalikan semua negara Anda)

Hank Gay
sumber
1
Tidak ada konsep sesi di tingkat HTTP; server memberikan ini dengan memberikan ID unik kepada klien dan memberi tahu klien untuk mengirim ulang setiap permintaan. Kemudian server menggunakan ID itu sebagai kunci ke hashtable besar dari objek Sesi. Bersambung ...
Hank Gay
1
Setiap kali server mendapat permintaan, ia mencari info Sesi dari hashtable objek sesi berdasarkan ID yang dikirimkan klien dengan permintaan. Semua pekerjaan ekstra ini adalah whammy ganda pada skalabilitas (alasan utama HTTP tidak memiliki kewarganegaraan). Bersambung ...
Hank Gay
1
Saya ingin tahu bagaimana Anda menerapkan aplikasi kompleks melalui HTTP tanpa status pengelasan entah bagaimana
Vinko Vrsalovic
3
harap edit jawaban Anda untuk memasukkan semua komentar ini. lebih mudah dibaca dan lebih baik untuk wiki dan lagipula saya tidak bisa memilih jawaban Anda sebagai yang diterima, jika semua yang penting ada di komentar. Terima kasih!
markus
6
"whammy one" Aku berharap aku bisa lebih memilih ini. Ketahui waktu Anda. Referensi memori berharga 100 nano detik, atau 0,0001 ms. Jadi melakukan pencarian pada hashtable yang disimpan di memori utama benar-benar tidak memakan waktu. Apakah O(1)memberitahumu sesuatu? @whammy dua: tapi jangan secara acak merutekan semua permintaan ke server acak? lakukan round robin, dan terus merutekan ke server yang sama dari pengguna yang sama. Ini wow, sangat jelas. Anda harus melihat kembali buku-buku Anda, bersama dengan semua 30+ upvotes
Toskan
19
  • Objek yang tidak dapat diserialisasi (atau yang berisi anggota yang tidak dapat diubah) tidak akan keluar dari $ _SESSION seperti yang Anda harapkan
  • Sesi besar membebani server (serialisasi dan deserializing megs negara setiap kali mahal)

Selain itu saya tidak melihat masalah.

Vinko Vrsalovic
sumber
9

Dalam pengalaman saya, umumnya tidak sepadan untuk hal yang lebih rumit daripada StdClass dengan beberapa properti. Biaya unserializing selalu lebih dari menciptakan kembali dari database diberi Pengidentifikasi sesi disimpan. Tampaknya keren, tetapi (seperti biasa), membuat profil adalah kuncinya.

Greg
sumber
Adakah komentar tentang kinerja antara meminta tabel 5x2 data pada setiap permintaan vs. menyimpan hasil dalam sesi dan menggunakannya?
musicliftsme
6

Saya sarankan jangan menggunakan status kecuali Anda benar-benar membutuhkannya. Jika Anda dapat membangun kembali objek tanpa menggunakan sesi, lakukanlah. Memiliki status dalam aplikasi web Anda membuat aplikasi lebih kompleks untuk dibangun, untuk setiap permintaan Anda harus melihat keadaan pengguna. Tentu ada saat-saat di mana Anda tidak dapat menghindari menggunakan sesi (contoh: pengguna harus tetap login selama sesi pada aplikasi web). Terakhir saya akan menyarankan menjaga objek sesi Anda sekecil mungkin karena ini berdampak pada kinerja untuk membuat serial dan membatalkan serial objek besar.

Johnny
sumber
Jadi, apakah lebih baik untuk membangun kembali objek termasuk melakukan semua query database lagi? Karena salah satu pemikiran saya untuk melakukan ini adalah bahwa saya tidak perlu menanyakan db untuk hal yang sama lagi.
markus
3
Jika penting bagi Anda bahwa itu tidak akan meminta database lagi menggunakan caching daripada menyimpannya di sesi. Tapi tolong sebelum melakukan sesuatu seperti membangun caching, periksa apakah itu benar-benar hit kinerja.
Johnny
Terima kasih, saya pikir sebenarnya tidak. Saya harus bertanya lagi.
markus
4

Anda harus ingat bahwa jenis sumber daya (seperti koneksi db atau file pointer) tidak akan bertahan di antara pemuatan halaman, dan Anda harus membuat ulang ini tanpa terlihat.

Juga pertimbangkan ukuran sesi, tergantung bagaimana sesi itu disimpan, Anda mungkin memiliki batasan ukuran, atau masalah latensi.

Marc Gear
sumber
0

Saya juga akan memunculkan ketika memutakhirkan pustaka perangkat lunak - kami meningkatkan perangkat lunak kami dan versi lama memiliki objek dalam sesi dengan nama kelas perangkat lunak V1, perangkat lunak baru mogok ketika mencoba untuk membangun objek yang ada di sesi - seperti V2 perangkat lunak tidak menggunakan kelas yang sama lagi, tidak dapat menemukannya. Kami harus memasukkan beberapa kode perbaikan untuk mendeteksi objek sesi, menghapus sesi jika ditemukan, memuat ulang halaman. Rasa sakit terbesar pada awalnya adalah Anda menciptakan bug ini ketika pertama kali dilaporkan (semuanya terlalu familiar, "well, itu berfungsi untuk saya" :) karena hanya memengaruhi orang-orang yang masuk dan keluar sistem lama dan baru baru-baru ini - namun, bagus pekerjaan yang kami temukan sebelum diluncurkan karena semua pengguna kami pasti memiliki variabel sesi lama di sesi mereka dan berpotensi mengalami crash untuk semua,

Bagaimanapun, seperti yang Anda sarankan dalam amandemen Anda, saya juga berpikir lebih baik untuk membuat kembali objek. Jadi mungkin hanya menyimpan id dan kemudian pada setiap permintaan menarik objek dari database, lebih baik / lebih aman.

Martyn
sumber