2012-04-06 17 views
16

मैं एक पृष्ठ जहाँ मैं मैं पर उपयोग करने के लिए इस पेज के शुरू कर दिया है एक लंबे मतदान करना है इसPHP सेव सत्र;

session_start(); 
session_write_close(); 

क्योंकि:

समवर्ती लेखन केवल एक स्क्रिप्ट पर काम कर सकते हैं रोकने के लिए किसी भी समय एक सत्र

तो यदि मैं नहीं करता और लंबे मतदान चल रहा है तो उपयोगकर्ता एक और पृष्ठ लोड नहीं कर पाएगा।

तो इस मतदान पृष्ठ से सत्र में मेरे डेटा तक पहुंच संभव है लेकिन मेरी स्क्रिप्ट में किसी बिंदु पर मुझे अपने सत्र को सर्वर पर वापस सहेजना है क्योंकि मैंने इसमें कुछ बदलाव किया है।

ऐसा करने का तरीका क्या है?

कि बहुत अच्छा हो जाएगा यह

कुछ की तरह
session_write_open(); 
//do stuff 
session_write_close(); 

लेकिन session_write_open() मौजूद नहीं है करने के लिए एक तरीका हो जाएगा!

धन्यवाद

+0

देर से ही सही भविष्य पाठकों के लिए, मैं सुझाव दे रहा हूँ कि आप 'का उपयोग करें()' एक सबसे अच्छा अभ्यास के अधिक के रूप में session_set_save_handler के बाद से यह किसी भी काम arounds को शामिल नहीं करता है, लेकिन पीएचपी लेखकों के रूप में सत्र को संशोधित करता है प्रतीत होता है प्रतीत होता है। मैंने नीचे एक उदाहरण कैसे दिया है इसका एक उदाहरण पोस्ट किया है। –

उत्तर

13

इससे पहले कि आप सत्र के लिए कुछ परिवर्तन करना पड़ेगा, session_start फिर से फोन। परिवर्तन करें, और यदि आप अभी भी session_write_close पर कॉल से बाहर निकलना नहीं चाहते हैं। आप इसे जितनी बार चाहें उतनी बार कर सकते हैं।

+0

यह 'session_start' के बिना मेरे लिए क्यों काम कर रहा है? मैं बस अपनी स्क्रिप्ट की शुरुआत में session_write_close बना देता हूं, जिसमें सत्र के अपडेट सहित बहुत सारे तर्क शामिल हैं, और सब कुछ ठीक काम करता है, सत्र सही ढंग से अपडेट किया गया –

+0

@VictorBredihin वास्तविक कोड को देखे बिना मुझे नहीं पता कि क्या हो रहा है।शायद आप एक नया सवाल पोस्ट कर सकते हैं। – Jon

10

पिछले समाधान एक सत्र आईडी और कुकीज़ पैदा करेगा ... मैं इसका इस्तेमाल नहीं होता है के रूप में:

सत्र हर बार जब आप session_start फोन बनाई गई है()। यदि आप एकाधिक कुकी से बचने के लिए चाहते हैं, तो बेहतर कोड लिखें। एकाधिक session_start() विशेष रूप से एक ही स्क्रिप्ट में एक ही नाम के लिए वास्तव में खराब विचार की तरह लगता है।

यहाँ देखें: https://bugs.php.net/bug.php?id=38104

मैं भी एक समाधान के लिए देख रहा हूँ अभी और मैं एक नहीं मिल रहा। मैं उन लोगों से सहमत हूं जो कहते हैं कि यह एक "बग" है। आपको एक पीएचपी सत्र फिर से खोलने में सक्षम होना चाहिए, लेकिन जैसा कि आपने कहा है session_write_open() मौजूद नहीं है ...

मुझे उपरोक्त धागे में एक कार्यवाही मिली। इसमें अनुरोध संसाधित करने के बाद मैन्युअल रूप से सत्र आईडी की कुकी निर्दिष्ट करने वाला हेडर भेजना शामिल है। सौभाग्य से पर्याप्त मैं घर-निर्मित फ्रंट कंट्रोलर के साथ काम कर रहा हूं जो काम करता है ताकि कोई उप-नियंत्रक कभी भी डेटा भेज न सके। संक्षेप में, यह मेरे मामले में पूरी तरह से काम करता है। इसका उपयोग करने के लिए आपको केवल ob_start() और ob_get_clean() का उपयोग करना होगा। यहाँ जादू लाइन है:

if (SID) header('Set-Cookie: '.SID.'; path=/', true); 

संपादित करें: नीचे CMCDragonkai के जवाब देखते हैं, अच्छा लगता है !?

+0

ठीक है मुझे कुकीज़ के बारे में पता नहीं था, हाँ session_start() को कॉल करना; ज्यादा समझ में नहीं आता है लेकिन मेरे पास उस समस्या को ठीक करने का कोई अन्य समाधान नहीं है जिसे मैं जानता हूं;) बग के बारे में जानकारी के लिए धन्यवाद! –

+0

यह सिर्फ एक सुविधा हो सकती है जो गायब है ... –

+1

एक कामकाज मिला! संपादित उत्तर! –

3

आर्मेल लैरिसीर के आसपास के काम का परीक्षण करने के बाद।

ob_start(); 

    session_start(); 
    session_write_close(); 

    session_start(); 
    session_write_close(); 

    session_start(); 
    session_write_close(); 

    session_start(); 
    session_write_close(); 

    if(SID){ 

     $headers = array_unique(headers_list()); 

     $cookie_strings = array(); 

     foreach($headers as $header){ 
      if(preg_match('/^Set-Cookie: (.+)/', $header, $matches)){ 
       $cookie_strings[] = $matches[1]; 
      } 
     } 

     header_remove('Set-Cookie'); 

     foreach($cookie_strings as $cookie){ 
      header('Set-Cookie: ' . $cookie, false); 
     } 

    } 

    ob_flush(); 

इस सत्र के साथ काम करने से पहले बनाए गए किसी भी कुकी सुरक्षित करेगा: यहाँ इस समस्या के लिए अपने प्रस्तावित समाधान है।

बीटीडब्ल्यू, आप उपरोक्त कोड को register_shutdown_function के लिए फ़ंक्शन के रूप में पंजीकृत करना चाहते हैं। फ़ंक्शन के अंदर ob_start() फ़ंक्शन से पहले और ob_flush() को चलाने के लिए सुनिश्चित करें।

4

अन्य उत्तरों यहां बहुत अच्छे समाधान पेश करते हैं। जैसा कि @ जोन द्वारा उल्लिखित है, चाल है कि आप बदलाव करना चाहते हैं, फिर से session_start() को कॉल करना है। फिर, जब आप परिवर्तन कर लेते हैं, तो session_write_close() को दोबारा कॉल करें।

जैसा कि @ एर्मेल लैरसीर द्वारा उल्लिखित है, इस समस्या के साथ यह है कि PHP नए शीर्षकों को उत्पन्न करने का प्रयास करता है और संभवतः चेतावनियां उत्पन्न करेगा (उदाहरण के लिए यदि आपने पहले ही क्लाइंट को गैर-हेडर डेटा लिखा है)। बेशक, आप बस "_ "(@session_start()) के साथ session_start() को उपसर्ग कर सकते हैं, लेकिन एक बेहतर दृष्टिकोण है।

एक और स्टैक ओवरफ़्लो सवाल, @VolkerK द्वारा प्रदान की सर्वश्रेष्ठ उत्तर का पता चलता है:

session_start(); // first session_start 
... 
session_write_close(); 
... 

ini_set('session.use_only_cookies', false); 
ini_set('session.use_cookies', false); 
//ini_set('session.use_trans_sid', false); //May be necessary in some situations 
ini_set('session.cache_limiter', null); 
session_start(); // second session_start 

यह हेडर फिर से भेजने का प्रयास कर से पीएचपी रोकता है। तुम भी ini_set() इस में थोड़ा और अधिक सुविधाजनक बनाने के लिए काम करता है रैप करने के लिए एक सहायक समारोह लिख सकते हैं:

function session_reopen() { 
    ini_set('session.use_only_cookies', false); 
    ini_set('session.use_cookies', false); 
    //ini_set('session.use_trans_sid', false); //May be necessary in some situations 
    ini_set('session.cache_limiter', null); 
    session_start(); //Reopen the (previously closed) session for writing. 
} 

मूल अतः संबंधित प्रश्न/उत्तर: https://stackoverflow.com/a/12315542/114558

+1

यह एक अच्छा खोज है। * सबसे अच्छा * समाधान केवल भागों में सामग्री को आउटपुट नहीं करना होगा (हमेशा मेरे लिए काम करता है), इस मामले में आपको एकाधिक शीर्षलेख मिलते हैं लेकिन वे हानिरहित होते हैं। हालांकि यह संभव नहीं हो सकता है अगर उदा। आपको कुछ कोड विरासत में मिला है, इसलिए इस कार्यवाही का वैध उपयोग केस है। – Jon

+0

यह बहुत ही जटिल लगता है जब आप session_set_save_handler का उपयोग कर सकते हैं और समस्या से पूरी तरह से बच सकते हैं और यह वही कर सकते हैं जो आप चाहते हैं। –

3

जवाब यहां के सभी कह हो रहे हैं सत्र विधियों का उपयोग इस तरीके से करने के लिए किया गया था कि वे स्पष्ट रूप से उपयोग नहीं किए जाने का इरादा रखते थे ... अर्थात् session_start() को एक से अधिक बार कॉल करना।

PHP वेबसाइट एक उदाहरण प्रदान करता है सत्रहैंडलर इंटरफेस कार्यान्वयन जो मौजूदा सत्रों की तरह काम करेगा लेकिन फ़ाइल को लॉक किए बिना काम करेगा। बस अपने उदाहरण इंटरफ़ेस को कार्यान्वित करने के लिए सत्र में वर्र्स जोड़ने की मेरी क्षमता को सीमित किए बिना उसी सत्र पर समवर्ती कनेक्शन की अनुमति देने के लिए मेरे लॉकिंग समस्या को ठीक किया गया। कुछ रेस स्थितियों को रोकने के लिए, चूंकि ऐप का सत्र पूरी तरह से स्टेटलेस नहीं है, इसलिए मुझे इसे बंद किए बिना सत्र मध्य अनुरोध को सहेजने का एक तरीका बनाना पड़ा ताकि परिवर्तन के तुरंत बाद महत्वपूर्ण परिवर्तन बचा सकें और कम महत्वपूर्ण सत्र युद्ध केवल सहेज सकें अनुरोध के अंत में। उपयोग के लिए नीचे दिए गए उदाहरण देखें: आप की जगह अगर वह Session::start()session_start() साथ और Session::save()session_write_close() साथ, आप ध्यान देंगे कि अनुवर्ती अनुरोधों बाहर तीसरे चर मुद्रित कभी नहीं होगा

Session::start(); 
echo("<pre>Vars Stored in Session Were:\n");print_r($_SESSION);echo("</pre>"); 

$_SESSION['one'] = 'one'; 
$_SESSION['two'] = 'two'; 
//save won't close session and subsequent request will show 'three' 
Session::save(); 
$_SESSION['three'] = 'three'; 

... यह नष्ट हो जाएंगे। हालांकि, सत्रहैंडलर (नीचे) का उपयोग करके, कोई डेटा खो नहीं जाता है।

ओओपी कार्यान्वयन के लिए PHP 5.4+ की आवश्यकता होती है। हालांकि, आप PHP के पुराने संस्करणों में व्यक्तिगत कॉलबैक विधियां प्रदान कर सकते हैं। See docs

namespace { 
    class Session implements SessionHandlerInterface { 
     /** @var Session */ 
     private static $_instance; 
     private $savePath; 

     public static function start() { 
      if(empty(self::$_instance)) { 
       self::$_instance = new self(); 
       session_set_save_handler(self::$_instance,true); 
       session_start(); 
      } 
     } 
     public static function save() { 
      if(empty(self::$_instance)) { 
       throw new \Exception("You cannot save a session before starting the session"); 
      } 
      self::$_instance->write(session_id(),session_encode()); 
     } 
     public function open($savePath, $sessionName) { 
      $this->savePath = $savePath; 
      if (!is_dir($this->savePath)) { 
       mkdir($this->savePath, 0777); 
      } 

      return true; 
     } 
     public function close() { 
      return true; 
     } 
     public function read($id) { 
      return (string)@file_get_contents("$this->savePath/sess_$id"); 
     } 
     public function write($id, $data) { 
      return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true; 
     } 
     public function destroy($id) { 
      $file = "$this->savePath/sess_$id"; 
      if (file_exists($file)) { 
       unlink($file); 
      } 

      return true; 
     } 
     public function gc($maxlifetime) { 
      foreach (glob("$this->savePath/sess_*") as $file) { 
       if (filemtime($file) + $maxlifetime < time() && file_exists($file)) { 
        unlink($file); 
       } 
      } 

      return true; 
     } 
    } 
संबंधित मुद्दे