真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

php將數(shù)據(jù)保存在客戶端 php將數(shù)據(jù)庫(kù)內(nèi)容顯示到網(wǎng)頁(yè)

PHP中SESSION的問(wèn)題

Session 和 Cookie 有什么關(guān)系

十余年的潞城網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都全網(wǎng)營(yíng)銷推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整潞城建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)公司從事“潞城網(wǎng)站設(shè)計(jì)”,“潞城網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

Cookie 也是由于 HTTP 無(wú)狀態(tài)的特點(diǎn)而產(chǎn)生的技術(shù)。也被用于保存訪問(wèn)者的身份標(biāo)示和一些數(shù)據(jù)。每次客戶端發(fā)起 HTTP 請(qǐng)求時(shí),會(huì)將 Cookie 數(shù)據(jù)加到 HTTP header 中,提交給服務(wù)端。這樣服務(wù)端就可以根據(jù) Cookie 的內(nèi)容知道訪問(wèn)者的信息了。 可以說(shuō),Session 和 Cookie 做著相似的事情,只是 Session 是將數(shù)據(jù)保存在服務(wù)端,通過(guò)客戶端提交來(lái)的 session_id 來(lái)獲取對(duì)應(yīng)的數(shù)據(jù);而 Cookie 是將數(shù)據(jù)保存在客戶端,每次發(fā)起請(qǐng)求時(shí)將數(shù)據(jù)提交給服務(wù)端的。

上面提到,session_id 可以通過(guò) URL 或 cookie 來(lái)傳遞,由于 URL 的方式比 cookie 的方式更加不安全且使用不方便,所以一般是采用 cookie 來(lái)傳遞 session_id。

服務(wù)端生成 session_id,通過(guò) HTTP 報(bào)文發(fā)送給客戶端(比如瀏覽器),客戶端收到后按指示創(chuàng)建保存著 session_id 的 cookie。cookie 是以 key/value 形式保存的,看上去大概就這個(gè)樣子的:PHPSESSID=e4tqo2ajfbqqia9prm8t83b1f2。在 PHP 中,保存 session_id 的 cookie 名稱默認(rèn)叫作 PHPSESSID,這個(gè)名稱可以通過(guò) php.ini 中 session.name 來(lái)修改,也可以通過(guò)函數(shù) session_name() 來(lái)修改。

為什么不推薦使用 PHP 自帶的 files 型 Session 處理器

在 PHP 中,默認(rèn)的 Session 處理器是 files,處理器可以用戶自己實(shí)現(xiàn)(參見(jiàn):自定義會(huì)話管理器)。我知道的成熟的 Session 處理器還有很多:Redis、Memcached、MongoDB……

為什么不推薦使用 PHP 自帶的 files 類型處理器,PHP 官方手冊(cè)中給出過(guò)這樣一段 Note:

無(wú)論是通過(guò)調(diào)用函數(shù) session_start() 手動(dòng)開啟會(huì)話, 還是使用配置項(xiàng) session.auto_start 自動(dòng)開啟會(huì)話, 對(duì)于基于文件的會(huì)話數(shù)據(jù)保存(PHP 的默認(rèn)行為)而言, 在會(huì)話開始的時(shí)候都會(huì)給會(huì)話數(shù)據(jù)文件加鎖, 直到 PHP 腳本執(zhí)行完畢或者顯式調(diào)用 session_write_close() 來(lái)保存會(huì)話數(shù)據(jù)。 在此期間,其他腳本不可以訪問(wèn)同一個(gè)會(huì)話數(shù)據(jù)文件。

上述引用參見(jiàn):Session 的基本用法

為了證明這段話,我們創(chuàng)建一下 2 個(gè)文件: 文件:session1.php

?php

session_start();

sleep(5);

var_dump($_SESSION);

?

文件:session2.php

?php

session_start();

var_dump($_SESSION);

?

在同一個(gè)瀏覽器中,先訪問(wèn) ,然后在當(dāng)前瀏覽器新的標(biāo)簽頁(yè)立刻訪問(wèn) 。實(shí)驗(yàn)發(fā)現(xiàn),session1.php 等了 5 秒鐘才有輸出,而 session2.php 也等到了將近 5 秒才有輸出。而單獨(dú)訪問(wèn) session2.php 是秒開的。在一個(gè)瀏覽器中訪問(wèn) session1.php,然后立刻在另外一個(gè)瀏覽器中訪問(wèn) session2.php。結(jié)果是 session1.php 等待 5 秒鐘有輸出,而 session2.php 是秒開的。

分析一下造成這個(gè)現(xiàn)象的原因:上面例子中,默認(rèn)使用 Cookie 來(lái)傳遞 session_id,而且 Cookie 的作用域是相同。這樣,在同一個(gè)瀏覽器中訪問(wèn)這 2 個(gè)地址,提交給服務(wù)器的 session_id 就是相同的(這樣才能標(biāo)記訪問(wèn)者,這是我們期望的效果)。當(dāng)訪問(wèn) session1.php 時(shí),PHP 根據(jù)提交的 session_id,在服務(wù)器保存 Session 文件的路徑(默認(rèn)為 /tmp,通過(guò) php.ini 中的 session.save_path 或者函數(shù) session_save_path() 來(lái)修改)中找到了對(duì)應(yīng)的 Session 文件,并對(duì)其加鎖。如果不顯式調(diào)用 session_write_close(),那么直到當(dāng)前 PHP 腳本執(zhí)行完畢才會(huì)釋放文件鎖。如果在腳本中有比較耗時(shí)的操作(比如例子中的 sleep(5)),那么另一個(gè)持有相同 session_id 的請(qǐng)求由于文件被鎖,所以只能被迫等待,于是就發(fā)生了請(qǐng)求阻塞的情況。

既然如此,在使用完 Session 后,立刻顯示調(diào)用 session_write_close() 是不是就解決問(wèn)題了哩?比如上面例子中,在 sleep(5) 前面調(diào)用 session_write_close()。

確實(shí),這樣 session2.php 就不會(huì)被 session1.php 所阻塞。但是,顯示調(diào)用了 session_write_close() 就意味著將數(shù)據(jù)寫到文件中并結(jié)束當(dāng)前會(huì)話。那么,在后面代碼中要使用 Session 時(shí),必須重新調(diào)用 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);

?

官方給出的方案:

對(duì)于大量使用 Ajax 或者并發(fā)請(qǐng)求的網(wǎng)站而言,這可能是一個(gè)嚴(yán)重的問(wèn)題。 解決這個(gè)問(wèn)題最簡(jiǎn)單的做法是如果修改了會(huì)話中的變量, 那么應(yīng)該盡快調(diào)用 session_write_close() 來(lái)保存會(huì)話數(shù)據(jù)并釋放文件鎖。 還有一種選擇就是使用支持并發(fā)操作的會(huì)話保存管理器來(lái)替代文件會(huì)話保存管理器。

我推薦的方式是使用 Redis 作為 Session 的處理器。

拓展閱讀:

為什么不能用 memcached 存儲(chǔ) Session

如何使用 Redis 作為 PHP Session handler

Session 數(shù)據(jù)是什么時(shí)候被刪除的

這是一道經(jīng)常被面試官問(wèn)起的問(wèn)題。

先看看官方手冊(cè)中的說(shuō)明:

session.gc_maxlifetime 指定過(guò)了多少秒之后數(shù)據(jù)就會(huì)被視為"垃圾"并被清除。 垃圾搜集可能會(huì)在 session 啟動(dòng)的時(shí)候開始( 取決于 session.gc_probability 和 session.gc_divisor)。 session.gc_probability 與 session.gc_divisor 合起來(lái)用來(lái)管理 gc(garbage collection 垃圾回收)進(jìn)程啟動(dòng)的概率。此概率用 gc_probability/gc_divisor 計(jì)算得來(lái)。例如 1/100 意味著在每個(gè)請(qǐng)求中有 1% 的概率啟動(dòng) gc 進(jìn)程。session.gc_probability 默認(rèn)為 1,session.gc_divisor 默認(rèn)為 100。

繼續(xù)用我上面那個(gè)不太恰當(dāng)?shù)谋确桨桑喝绻覀儼盐锲贩旁诔械膬?chǔ)物箱中而不取走,過(guò)了很久(比如一個(gè)月),那么保安就要清理這些儲(chǔ)物箱中的物品了。當(dāng)然并不是超過(guò)期限了保安就一定會(huì)來(lái)清理,也許他懶,又或者他壓根就沒(méi)有想起來(lái)這件事情。

再看看兩段手冊(cè)的引用:

如果使用默認(rèn)的基于文件的會(huì)話處理器,則文件系統(tǒng)必須保持跟蹤訪問(wèn)時(shí)間(atime)。Windows FAT 文件系統(tǒng)不行,因此如果必須使用 FAT 文件系統(tǒng)或者其他不能跟蹤 atime 的文件系統(tǒng),那就不得不想別的辦法來(lái)處理會(huì)話數(shù)據(jù)的垃圾回收。自 PHP 4.2.3 起用 mtime(修改時(shí)間)來(lái)代替了 atime。因此對(duì)于不能跟蹤 atime 的文件系統(tǒng)也沒(méi)問(wèn)題了。

GC 的運(yùn)行時(shí)機(jī)并不是精準(zhǔn)的,帶有一定的或然性,所以這個(gè)設(shè)置項(xiàng)并不能確保舊的會(huì)話數(shù)據(jù)被刪除。某些會(huì)話存儲(chǔ)處理模塊不使用此設(shè)置項(xiàng)。

對(duì)于這種刪除機(jī)制,我是存疑的。

比如 gc_probability/gc_divisor 設(shè)置得比較大,或者網(wǎng)站的請(qǐng)求量比較大,那么 GC 進(jìn)程啟動(dòng)就會(huì)比較頻繁。

還有,GC 進(jìn)程啟動(dòng)后都需要遍歷 Session 文件列表,對(duì)比文件的修改時(shí)間和服務(wù)端的當(dāng)前時(shí)間,判斷文件是否過(guò)期而決定是否刪除文件。

這也是我覺(jué)得不應(yīng)該使用 PHP 自帶的 files 型 Session 處理器的原因。而 Redis 或 Memcached 天生就支持 key/value 過(guò)期機(jī)制的,用于作為會(huì)話處理器很合適?;蛘咦约簩?shí)現(xiàn)一個(gè)基于文件的處理器,當(dāng)根據(jù) session_id 獲取對(duì)應(yīng)的單個(gè) Session 文件時(shí)判斷文件是否過(guò)期。

為什么重啟瀏覽器后 Session 數(shù)據(jù)就取不到了

session.cookie_lifetime 以秒數(shù)指定了發(fā)送到瀏覽器的 cookie 的生命周期。值為 0 表示"直到關(guān)閉瀏覽器"。默認(rèn)為 0。

其實(shí),并不是 Session 數(shù)據(jù)被刪除(也有可能是,概率比較小,參見(jiàn)上一節(jié))。只是關(guān)閉瀏覽器時(shí),保存 session_id 的 Cookie 沒(méi)有了。也就是你弄丟了打開超市儲(chǔ)物箱的鑰匙(session_id)。

同理,瀏覽器 Cookie 被手動(dòng)清除或者其他軟件清除也會(huì)造成這個(gè)結(jié)果。

為什么瀏覽器開著,我很久沒(méi)有操作就被登出了

這個(gè)是稱為“防呆”,為了保護(hù)用戶賬戶安全的。

這個(gè)小節(jié)放進(jìn)來(lái),是因?yàn)檫@個(gè)功能的實(shí)現(xiàn)可能和 Session 的刪除機(jī)制有關(guān)(之所以說(shuō)是可能,是因?yàn)檫@個(gè)功能不一定要借住 Session 實(shí)現(xiàn),用 Cookie 也同樣可以實(shí)現(xiàn))。 說(shuō)簡(jiǎn)單一點(diǎn),就是長(zhǎng)時(shí)間沒(méi)有操作,服務(wù)端的 Session 文件過(guò)期被刪除了。

一個(gè)有意思的事情

在我試驗(yàn)的過(guò)程中,發(fā)現(xiàn)了小有意思的事情:我把 GC 啟動(dòng)的概率設(shè)置為 100%。如果只有一個(gè)訪問(wèn)者請(qǐng)求,該訪問(wèn)者即使過(guò)了很久(超過(guò)了過(guò)期時(shí)間)后才發(fā)起第二次請(qǐng)求,那么 Session 數(shù)據(jù)也還是存在的('session.save_path' 目錄下面的 Session 文件存在)。是的,明明就超過(guò)了過(guò)期時(shí)間,卻沒(méi)有被 GC 刪除。這時(shí),我用另外一個(gè)瀏覽器訪問(wèn)時(shí)(相對(duì)于另一個(gè)訪問(wèn)者),這次請(qǐng)求生成了新的 Session 文件,而上一個(gè)瀏覽器請(qǐng)求生成的那個(gè) Session 文件終于沒(méi)有了(之前那個(gè) Session 文件在 'session.save_path' 目錄下面的消失了)。

還有,發(fā)現(xiàn) Session 文件被刪除后,再次請(qǐng)求,還是會(huì)生成和之前文件名相同的 Session 文件(因?yàn)闉g覽器并沒(méi)有關(guān)閉,再次請(qǐng)求發(fā)送的 session_id 是相同的,所以重新生成的 Session 文件的文件名還是一樣的)。但是,我不理解的是:這個(gè)重新出現(xiàn)的文件的創(chuàng)建時(shí)間竟然是第一次的那個(gè)創(chuàng)建時(shí)間,難道它是從回收站中回來(lái)的?(確實(shí),我做這個(gè)試驗(yàn)時(shí)是在 window 下進(jìn)行的)

我猜測(cè)的原因是這樣:當(dāng)啟動(dòng)會(huì)話后,PHP 根據(jù) session_id 找到并打開了對(duì)應(yīng)的 Session 文件,然后才啟動(dòng) GC 進(jìn)程。GC 進(jìn)程就只檢查除了當(dāng)前這個(gè) Session 文件外的其他文件,發(fā)現(xiàn)過(guò)期的就干掉。所有,即使當(dāng)前這個(gè) Session 文件已經(jīng)過(guò)期了,GC 也沒(méi)有刪除它。

我認(rèn)為這個(gè)不合理的。

由于發(fā)生這種情況影響也不大(畢竟線上請(qǐng)求很多,當(dāng)前請(qǐng)求的過(guò)期文件被其他請(qǐng)求喚起的 GC 干掉的可能性是比較大的) + 我沒(méi)有信心去看 PHP 源代碼 + 我并不在線上使用 PHP 自帶的 files 型 Session 處理器。所以,這個(gè)問(wèn)題我就沒(méi)有深入研究了。請(qǐng)諒解。

?php

// 過(guò)期時(shí)間設(shè)置為 30 秒

ini_set('session.gc_maxlifetime', '30');

// GC 啟動(dòng)概率設(shè)置為 100%

ini_set('session.gc_probability', '100');

ini_set('session.gc_divisor', '100');

session_start();

$_SESSION['name'] = 'Jing';

var_dump($_SESSION);

?

php session 數(shù)據(jù)保存在哪里?

當(dāng)然是在服務(wù)器端,但不是保存在內(nèi)存中,而是保存在文件或數(shù)據(jù)庫(kù)中。

默認(rèn)情況下,php.ini

中設(shè)置的

SESSION

保存方式是

files(session.save_handler

=

files),即使用讀寫文件的方式保存

SESSION

數(shù)據(jù),而

SESSION

文件保存的目錄由

session.save_path

指定,文件名以

sess_

為前綴,后跟

SESSION

ID,如:sess_c72665af28a8b14c0fe11afe3b59b51b。文件中的數(shù)據(jù)即是序列化之后的

SESSION

數(shù)據(jù)了。

如果訪問(wèn)量大,可能產(chǎn)生的

SESSION

文件會(huì)比較多,這時(shí)可以設(shè)置分級(jí)目錄進(jìn)行

SESSION

文件的保存,效率會(huì)提高很多,設(shè)置方法

為:session.save_path="N;/save_path",N

為分級(jí)的級(jí)數(shù),save_path

為開始目錄。

當(dāng)寫入

SESSION

數(shù)據(jù)的時(shí)候,PHP

會(huì)獲取到客戶端的

SESSION_ID,然后根據(jù)這個(gè)

SESSION

ID

到指定的

SESSION

文件保存目錄中找到相應(yīng)的

SESSION

文件,不存在則創(chuàng)建之,最后將數(shù)據(jù)序列化之后寫入文件。讀取

SESSION

數(shù)據(jù)是也是類似的操作流程,對(duì)讀出來(lái)的數(shù)據(jù)需要進(jìn)行解序列化,生成相應(yīng)的

SESSION

變量。

PHP典型模塊與項(xiàng)目實(shí)戰(zhàn)大全:客戶端數(shù)據(jù)存儲(chǔ)機(jī)制cookie[1]

客戶端數(shù)據(jù)存儲(chǔ)機(jī)制cookie

在實(shí)際的Web應(yīng)用中經(jīng)常需要在客戶端存儲(chǔ)一些客戶信息 一方面是為了改善用戶體驗(yàn)(如存儲(chǔ)訪問(wèn)密碼 歷史表單信息) 另一方面有效地減輕了服務(wù)器數(shù)據(jù)讀取壓力 訪問(wèn)者在第一次訪問(wèn)頁(yè)面時(shí)設(shè)置cookie變量是存儲(chǔ)在客戶端計(jì)算機(jī)中 當(dāng)下次瀏覽器請(qǐng)求某個(gè)頁(yè)面時(shí) 就可以讀取cookie中存儲(chǔ)的值 從而實(shí)現(xiàn)客戶端數(shù)據(jù)存取

下面將通過(guò)一個(gè)例子展示一個(gè)客戶端數(shù)據(jù)存儲(chǔ)的實(shí)際應(yīng)用 執(zhí)行流程如下

( )創(chuàng)建一個(gè)存儲(chǔ)訪問(wèn)者名字的cookie;

( )當(dāng)訪問(wèn)者首次訪問(wèn)網(wǎng)站時(shí) 訪問(wèn)者會(huì)被要求填寫姓名信息 該姓名信息會(huì)存儲(chǔ)于cookie中

( )當(dāng)訪問(wèn)者再次訪問(wèn)網(wǎng)站時(shí)瀏覽器會(huì)顯示歡迎詞信息

在JavaScript創(chuàng)建cookie

創(chuàng)建一個(gè)可在cookie變量中存儲(chǔ)訪問(wèn)者姓名的函數(shù) 代碼如下

function setCookie(c_name value expiredays)

{

var exdate=new Date()???????????????????????? //實(shí)例化日期變量

exdate setDate(exdate getDate()+expiredays)?? //設(shè)置日期變量

document cookie=c_name+ = +escape(value)+

((expiredays==null) ? : ;expires= +exdate toGMTString())

}

【代碼解讀】

setCookie()函數(shù)的功能是設(shè)置cookie的名稱 值及失效時(shí)間 首先將獲取當(dāng)前的日期轉(zhuǎn)換為有效的日期 然后設(shè)置cookie名稱 值及失效時(shí)間 并將該值存入document cookie對(duì)象

從JavaScript取回cookie的值

從JavaScript取回cookie的值 創(chuàng)建讀取客戶端cookie值的函數(shù) 同時(shí)判斷當(dāng)前cookie的狀態(tài) 代碼如下

function getCookie(c_name)

{

if (document cookie length )?????????????????? //判斷當(dāng)前cookie是否為空

{

c_start=document cookie indexOf(c_name + = )

if (c_start!= )

{

c_startc_start=c_start + c_name length+

c_end=document cookie indexOf( ; c_start)

if (c_end== ) c_end=document cookie length

return unescape(document cookie substring(c_start c_end))

//返回客戶端cookie的值

}

}

return

}

【代碼解讀】

getCookie()函數(shù)首先會(huì)判斷document cookie對(duì)象中是否存有cookie 如果document cookie對(duì)象存有某些cookie值 那么會(huì)繼續(xù)檢查指定的cookie是否已儲(chǔ)存 如果滿足判斷條件就返回cookie存儲(chǔ)值 否則返回空字符串

JavaScript流程控制

當(dāng)完成了cookie的創(chuàng)建和讀取之后 需要?jiǎng)?chuàng)建一個(gè)流程控制函數(shù) 這個(gè)函數(shù)的作用是 如果cookie已設(shè)置 則顯示歡迎詞 否則顯示提示框要求用戶輸入名字

function checkCookie() {

username=getCookie( username )????????????????? //獲得cookie中的用戶名變量

if (username != null username != ) {

alert( Wele again +username+ ! )??? //彈出歡迎信息

} else {

username=prompt( Please enter your name: )

if (username != null username != ) {

setCookie( username username )? //設(shè)置cookie

}

}

}

客戶端數(shù)據(jù)存儲(chǔ)示例的完整代碼如下

lishixinzhi/Article/program/PHP/201311/21526


當(dāng)前文章:php將數(shù)據(jù)保存在客戶端 php將數(shù)據(jù)庫(kù)內(nèi)容顯示到網(wǎng)頁(yè)
文章地址:http://weahome.cn/article/dohjhhh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部