亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

這樣都能直接保存,但問題中的第一個頁面就不能正常保存?

這樣都能直接保存,但問題中的第一個頁面就不能正常保存?

PHP
POPMUISE 2023-04-01 13:09:32
第一個頁面中傳了個數字3過來,session_start();$booknum=$_GET['num'];$_SESSION["$booknum"]="XXX";print_r($_SESSION);結果就是當前頁面可以打印出$_SESSION["$booknum"]Array([3] => XXX)但是新開一個頁面session_start();echo $_SESSION[3];這里就不能輸出$_SESSION[3]了,求大神解惑我想知道的是為什么第一個頁面中的SESSION不能夠保存下來,第一個頁面中直接輸出$_SESSION[3]都沒有問題,能保存下來應該就能在第二個頁面獲取了,而且并不是我SESSION方面的設置不對,新建頁面session_start();$_SESSION['user']="aaa";
查看完整描述

2 回答

?
MMMHUHU

TA貢獻1834條經驗 獲得超8個贊

$_SESSION["$string"],$string不能是純數字

查看完整回答
反對 回復 2023-04-05
?
人到中年有點甜

TA貢獻1895條經驗 獲得超7個贊

為了證明這段話,我們創建一下 2 個文件: 文件:session1.php
  <?php
  session_start();
  sleep(5);
  var_dump($_SESSION);
  ?>
  文件:session2.php
  <?php
  session_start();
  var_dump($_SESSION);
  ?>
  在同一個瀏覽器中,先訪問 http://127.0.0.1/session1.php,然后在當前瀏覽器新的標簽頁立刻訪問 http://127.0.0.1/session2.php。實驗發現,session1.php 等了 5 秒鐘才有輸出,而 session2.php 也等到了將近 5 秒才有輸出。而單獨訪問 session2.php 是秒開的。在一個瀏覽器中訪問 session1.php,然后立刻在另外一個瀏覽器中訪問 session2.php。結果是 session1.php 等待 5 秒鐘有輸出,而 session2.php 是秒開的。
  分析一下造成這個現象的原因:上面例子中,默認使用 Cookie 來傳遞 session_id,而且 Cookie 的作用域是相同。這樣,在同一個瀏覽器中訪問這 2 個地址,提交給服務器的 session_id 就是相同的(這樣才能標記訪問者,這是我們期望的效果)。當訪問 session1.php 時,PHP 根據提交的 session_id,在服務器保存 Session 文件的路徑(默認為 /tmp,通過 php.ini 中的 session.save_path 或者函數 session_save_path() 來修改)中找到了對應的 Session 文件,并對其加鎖。如果不顯式調用 session_write_close(),那么直到當前 PHP 腳本執行完畢才會釋放文件鎖。如果在腳本中有比較耗時的操作(比如例子中的 sleep(5)),那么另一個持有相同 session_id 的請求由于文件被鎖,所以只能被迫等待,于是就發生了請求阻塞的情況。
  既然如此,在使用完 Session 后,立刻顯示調用 session_write_close() 是不是就解決問題了哩?比如上面例子中,在 sleep(5) 前面調用 session_write_close()。
  確實,這樣 session2.php 就不會被 session1.php 所阻塞。但是,顯示調用了 session_write_close() 就意味著將數據寫到文件中并結束當前會話。那么,在后面代碼中要使用 Session 時,必須重新調用 session_start()。
  例如:
  <?php
  session_start();
  $_SESSION['name'] = 'Jing';
  var_dump($_SESSION);
  session_write_close();
  sleep(5);
  session_start();
  $_SESSION['name'] = 'Mr.Jing';
  var_dump($_SESSION);
  ?>
  官方給出的方案:
  對于大量使用 Ajax 或者并發請求的網站而言,這可能是一個嚴重的問題。 解決這個問題最簡單的做法是如果修改了會話中的變量, 那么應該盡快調用 session_write_close() 來保存會話數據并釋放文件鎖。 還有一種選擇就是使用支持并發操作的會話保存管理器來替代文件會話保存管理器。
  我推薦的方式是使用 Redis 作為 Session 的處理器。
  拓展閱讀:
  為什么不能用 memcached 存儲 Session
  如何使用 Redis 作為 PHP Session handler
  Session 數據是什么時候被刪除的
  這是一道經常被面試官問起的問題。
  先看看官方手冊中的說明:
  session.gc_maxlifetime 指定過了多少秒之后數據就會被視為"垃圾"并被清除。 垃圾搜集可能會在 session 啟動的時候開始( 取決于 session.gc_probability 和 session.gc_divisor)。 session.gc_probability 與 session.gc_divisor 合起來用來管理 gc(garbage collection 垃圾回收)進程啟動的概率。此概率用 gc_probability/gc_divisor 計算得來。例如 1/100 意味著在每個請求中有 1% 的概率啟動 gc 進程。session.gc_probability 默認為 1,session.gc_divisor 默認為 100。
  繼續用我上面那個不太恰當的比方吧:如果我們把物品放在超市的儲物箱中而不取走,過了很久(比如一個月),那么保安就要清理這些儲物箱中的物品了。當然并不是超過期限了保安就一定會來清理,也許他懶,又或者他壓根就沒有想起來這件事情。
  再看看兩段手冊的引用:
  如果使用默認的基于文件的會話處理器,則文件系統必須保持跟蹤訪問時間(atime)。Windows FAT 文件系統不行,因此如果必須使用 FAT 文件系統或者其他不能跟蹤 atime 的文件系統,那就不得不想別的辦法來處理會話數據的垃圾回收。自 PHP 4.2.3 起用 mtime(修改時間)來代替了 atime。因此對于不能跟蹤 atime 的文件系統也沒問題了。
  GC 的運行時機并不是精準的,帶有一定的或然性,所以這個設置項并不能確保舊的會話數據被刪除。某些會話存儲處理模塊不使用此設置項。
  對于這種刪除機制,我是存疑的。
  比如 gc_probability/gc_divisor 設置得比較大,或者網站的請求量比較大,那么 GC 進程啟動就會比較頻繁。
  還有,GC 進程啟動后都需要遍歷 Session 文件列表,對比文件的修改時間和服務端的當前時間,判斷文件是否過期而決定是否刪除文件。
  這也是我覺得不應該使用 PHP 自帶的 files 型 Session 處理器的原因。而 Redis 或 Memcached 天生就支持 key/value 過期機制的,用于作為會話處理器很合適?;蛘咦约簩崿F一個基于文件的處理器,當根據 session_id 獲取對應的單個 Session 文件時判斷文件是否過期。
  為什么重啟瀏覽器后 Session 數據就取不到了
  session.cookie_lifetime 以秒數指定了發送到瀏覽器的 cookie 的生命周期。值為 0 表示"直到關閉瀏覽器"。默認為 0。
  其實,并不是 Session 數據被刪除(也有可能是,概率比較小,參見上一節)。只是關閉瀏覽器時,保存 session_id 的 Cookie 沒有了。也就是你弄丟了打開超市儲物箱的鑰匙(session_id)。
  同理,瀏覽器 Cookie 被手動清除或者其他軟件清除也會造成這個結果。
  為什么瀏覽器開著,我很久沒有操作就被登出了
  這個是稱為“防呆”,為了保護用戶賬戶安全的。
  這個小節放進來,是因為這個功能的實現可能和 Session 的刪除機制有關(之所以說是可能,是因為這個功能不一定要借住 Session 實現,用 Cookie 也同樣可以實現)。 說簡單一點,就是長時間沒有操作,服務端的 Session 文件過期被刪除了。
  一個有意思的事情
  在我試驗的過程中,發現了小有意思的事情:我把 GC 啟動的概率設置為 100%。如果只有一個訪問者請求,該訪問者即使過了很久(超過了過期時間)后才發起第二次請求,那么 Session 數據也還是存在的('session.save_path' 目錄下面的 Session 文件存在)。是的,明明就超過了過期時間,卻沒有被 GC 刪除。這時,我用另外一個瀏覽器訪問時(相對于另一個訪問者),這次請求生成了新的 Session 文件,而上一個瀏覽器請求生成的那個 Session 文件終于沒有了(之前那個 Session 文件在 'session.save_path' 目錄下面的消失了)。
  還有,發現 Session 文件被刪除后,再次請求,還是會生成和之前文件名相同的 Session 文件(因為瀏覽器并沒有關閉,再次請求發送的 session_id 是相同的,所以重新生成的 Session 文件的文件名還是一樣的)。但是,我不理解的是:這個重新出現的文件的創建時間竟然是第一次的那個創建時間,難道它是從回收站中回來的?(確實,我做這個試驗時是在 window 下進行的)
  我猜測的原因是這樣:當啟動會話后,PHP 根據 session_id 找到并打開了對應的 Session 文件,然后才啟動 GC 進程。GC 進程就只檢查除了當前這個 Session 文件外的其他文件,發現過期的就干掉。所有,即使當前這個 Session 文件已經過期了,GC 也沒有刪除它。
  我認為這個不合理的。
  由于發生這種情況影響也不大(畢竟線上請求很多,當前請求的過期文件被其他請求喚起的 GC 干掉的可能性是比較大的) + 我沒有信心去看 PHP 源代碼 + 我并不在線上使用 PHP 自帶的 files 型 Session 處理器。所以,這個問題我就沒有深入研究了。請諒解。
  <?php
  // 過期時間設置為 30 秒
  ini_set('session.gc_maxlifetime', '30');
  // GC 啟動概率設置為 100%
  ini_set('session.gc_probability', '100');
  ini_set('session.gc_divisor', '100');
  session_start();
  $_SESSION['name'] = 'Jing';
  var_dump($_SESSION);
  ?>

 


查看完整回答
反對 回復 2023-04-05
  • 2 回答
  • 0 關注
  • 99 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號