日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

读书笔记:PHP和MySQL高性能应用开发 (2019.2.20-2019.3.4)

發布時間:2024/1/8 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 读书笔记:PHP和MySQL高性能应用开发 (2019.2.20-2019.3.4) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.emtpy、isset、is_null的區別

??isset()檢測一個變量是否已聲明且值不為NULL,并且聲名一個變量沒有賦值也算false,但是空字符串或者空格為true
? empty()用來檢測一個變量是否為空,當變量為空字符串、false、空數組、null、0、‘’以及被unset刪除后的變量
? is_null()判斷變量內容是否是null,是isset()函數的反函數,區別是isset()可以應用到未知變量,但是is_null只能針對已聲名變量

2.超級全局數組

? PHP執行時會自動將當前腳本需要收集的數據分類保存在這些超級全局數組中

? ? ?$GLOBALS超級全局數組可以讓我們在函數里訪問全局變量

? ? ?例如

?<?php$globalName='全局變量';function say(){echo $GLOBALS['globalName'];}


?3.global關鍵字與global數組的區別
?$GLOBALS['var']是外部的全局變量本身
?global $var是外部$var的同名引用或者指針
?

<?php $val=1; function test(){//1、unset($GLOBALS['val']);global $val;unset($val); } test(); echo $val;


1.的時候$val變量被刪除 ?
global $val 與&GLOBALS['val']等價,相當于調用外部變量的一個別名,所以上面代碼中的$val和$GLOBALS['val']指的是同一個變量
注:php的全局變量和c有點不同,在c的全局變量在函數體內無效,而在php中,在函數中想要調用外部的全局變量可用global什么,php的
'全局'不是指整個網站,而是應用于當前頁面,包括include或require的全部文件
結論:$GLOBALS['var']是外部的全局變量本身
? ? ? global $var是外部$var的同名引用或者指針

4.靜態變量
? 函數內的局部變量執行時存在,完畢后會在內存里直接刪除,但是如果想在函數調用保存上次變量執行的結果,以便下次執行時使用,這時就用靜態變量,當腳本運行完畢退出的時候,靜態變量也會銷毀,這一點和全局、局部變量特性相同
5.require_once要慢于require,使用autoload速度最快,在實際運營環境中,使用error_reporting(0)禁止所有的錯誤顯示
6.匿名函數
?

<?php $greet =function($name){echo "$name";?? ? };


array_map('函數',數組) ? 數組內的每個元素都將使用之前的函數遍歷一遍
而在匿名函數中 array_map(function(value){},$names);
PHP在默認情況下,匿名函數不能調用所在代碼塊的上下文變量,而需要通過使用use關鍵字。
function getMoney() {
? ? $rmb = 1;
? ? $dollar = 6;
? ? $func = function() use ( $rmb ) {
? ? ? ? echo $rmb;
? ? ? ? echo $dollar;
? ? };
? ? $func();
}
//輸出:
//1
//報錯,找不到dorllar變量
7.is_callable與method_exists函數 ?都是用來檢查一個對象里的方法是否存在
? 在method_exists(array(對象,'方法'))函數中判斷一個私有或者保護方法,能夠得到正確的返回,但是執行的時候會得到一個錯誤警告
? 而is_callable(array(對象,'方法'))函數接受一個回調參數,如果在當前作用域可以執行就返回true
8.文件處理
$handle=fopen("/var/logs/somefile.txt",'r');
如果處理意見存在的文件,也不想刪除它原來的內容:
? r : 只讀。指針定位在文件的開頭,如果文件不會報錯。
? r+: 讀/寫。指針定位在文件的開頭,如果文件不存會報錯。
如果想新創建一個文件或代替現有文件:
? w : 只寫。打開并清空文件的內容,如果文件不存在,則創建新文件。
? w+: 讀/寫。打開并清空文件的內容,如果文件不存在,則創建新文件。
php允許我們使用兩種追加寫入文件的模式:
? a-:追加模式,如果不存在,則嘗試創建它
? a+:讀/追加模式,游標置于文件尾部,將從文件末尾開始追加(寫),如果該文件不存在,則創建它
謹慎的文件寫操作:
? x : 只寫。創建新文件。如果文件以存在,則返回 FALSE。
? x+ : 讀/寫。創建新文件。如果文件已存在,則返回 FALSE 和一個錯誤。
? 大多數讀取文件場景,都是讀取文件的每一行后進行操作,這時就可以使用file()函數讀取整個文件到一個數組中

? $lines=file('1.txt');foreach($lines as $line =>$l){echo "Line #{$line_num}:".$line."n";}


file()函數可選參數:
include_path?? ?可選。如果也想在 include_path 中搜尋文件的話,可以將該參數設為 "1"。
context可選。規定文件句柄的環境。context 是一套可以修改流的行為的選項。若使用 null,則忽略。

file_get_contents(path,include_path,context,start,max_length)

可以接受這幾個參數:start:規定在文件中開始讀取的位置 max_length:可選。規定讀取的字節數
file_get_contents 獲取遠程文件時會把結果都存在一個字符串中 fiels函數則會儲存成數組形式,這個函數是一次性讀取所有文件內容并顯示出來,但是如果文件超大會導致php占很大的內存了。

注:下面給大家介紹下fopen()和file_get_contents()打開URL獲得網頁內容的用法區別
在php里,要想打開網頁URL獲得網頁內容,比較常用的函數是fopen()和file_get_contents()。如果要求不苛刻,此兩個函數多數情況下是可以根據個人愛好任意選擇的,本文談下此兩函數的用法有什么區別,以及使用時需要注意的問題。
fopen()打開URL

下面是一個使用fopen()打開URL的例子:??

?<?php$fh = fopen('http://www.php.cn/', 'r');if($fh){while(!feof($fh)) {echo fgets($fh);}} ?>


從此例子可以看到,fopen()打開網頁后,返回的$fh不是字符串,不能直輸出的,還需要用到fgets()這個函數來獲取字符串。fgets()函數是從文件指針中讀取一行。文件指針必須是有效的,必須指向由 fopen() 或 fsockopen() 成功打開的文件(并還未由 fclose() 關閉)。
可知,fopen()返回的只是一個資源,如果打開失敗,本函數返回 FALSE 。
file_get_contents()打開URL
下面是一個使用file_get_contents()打開URL的例子:

<?php$fh= file_get_contents('http://www.php.cn/');echo $fh;?>


從此例子看到,file_get_contents()打開網頁后,返回的$fh是一個字符串,可以直接輸出的。
通過上面兩個例子的對比,可以看出使用file_get_contents()打開URL,也許是更多人的選擇,因為其比fopen()更簡單便捷。
不過,如果是讀取比較大的資源,則是用fopen()比較合適。

readfile()函數不像之前兩個函數很方便抓取遠端文件,這是直接的方式來獲取緩沖區中的文件內容

<?php $file="1.txt"; $bytesRead=readfile($file); echo $bytesRead;

fgets()函數可以幫我們讀取文件時從文件指針的位置開始讀取一行,并作為一個字符串返回,也可以指定想讓他讀取的字節長度
例如:

$file="1.txt"; $hadle=fopen($file,"rt"); if($handle){while(!feof($handle)){ //檢查是否到達文件末尾,如果指針到了EOF或者出錯返回TRUE,否則返回一個錯誤(包括socket超時),其他false$buffer=$fets($handle,8192)//8kbecho $buffer;}fclose($handle); }

fread()函數,主要是來安全讀取二進制文件,它需要一個文件句柄和文件指針讀取字節的長度
例如:安全讀取二進制文件

$file='1.txt'; $handle=fopen($file,"r"); $contents=fread($handle,filesize($file)); fclose($handle);

例如:安全讀取遠端二進制文件

$hadle=fopen("http://www.2.com/1.gif","rt"); $contents=''; if($handle){while(!feof($handle)){ ?$contents=$contents.fread($handle,8192);}fclose($handle); }

9.局部goto語句(無法跳出一個函數或類方法)

<?php goto a; echo 'Foo';a: echo 'Bar'; ?>


輸出 :Bar
10手冊上的小瑕疵

echo "hollo".getInfo()."還有:".showInfo();
這段代碼的執行過程:
?1>創建一個新的臨時字符串
?2>把hollo加入字符串
?3>然后調用getInfo()函數返回的內容加入字符串
?4>創建一個新的臨時字符串
?5>放入第一次創建的字符串
?6>把還有加入字符串
?7>調用showInfo()返回的內容加入字符串
?8>打印
優化:echo "hollo",getInfo(),"還有:",showInfo();

?

面向對象可實現的目標

? ? ? ? ? ? ? ? ? ? ? 容易在已有代碼的基礎上擴展,代碼重構和擴展
? ? ? ? ? ? ??? ??? ? 允許類型微調,以在方法中對這些變量進行權限控制
? ? ? ? ? ? ??? ??? ? 結合設計模式,能夠解決大多數軟件設計的問題,擴展性好,調試更容易

雖然會損耗一些性能,但是面向對象的開發重要性在于封裝,它將問題分割成小塊,容易理清并易解決

1.構造方法:function_construct()和類名相同的方法 ,但是PHP虛擬機會先執行前一個
2.接口:接口就是一個空類,只包含方法的聲明,任何類要實現接口,必須完成里面定義的所有方法
3.抽象類:當聲明抽象方法的時候,意味著子類必須重寫該方法,一個抽象的方法不包含任何內容
4.魔術方法:?
? 1> __get() __set() __call()來存取類中沒有定義的成員方法和屬性
? ? ?當寫入一個不存在或不可見的屬性時,執行__set($name,$value)方法
? ? ?當調用一個不存在或者不可見的屬性時,執行__set($name)方法
? ? ?當試圖調用類中一個不存在或者不可見的方法,執行__call($method_name,$parameters)方法,接受兩個參數,用來存放試圖調用方法名稱及參數
? ? ? ?(參數會被放在一個與該參數同名的數組中)
? 2>__sleep()方法在序列化一個實例的時候被調用,必須返回一個數組或者對象(一般是返回的是當前對象$this),返回
? ? ? ? 的值將會被用來做序列化的值,如果不返回這個值,則表示序列化失敗,也意味著反序列化不會觸發__wakeup()事件
? ? __wakeup()則是在反序列化的時候被調用

? ? $i=new 類;
? ? $si=serialize($i);
? ? unserizlize($i);
? 3>__toString() 可以把類的實例轉化為字符串,這個成員方法調用并打印當前類中構建器中的值,在這個結構中,調用了公共的字符串操作,這樣的字符串連接也就形成了字符串
? 4>__autoload() 當訪問一個還未定義的類,這個方法開始將這個類名作為文件類參數來調用該類,如果能夠成功引入該類,則順利執行下去,如果沒有調用到該類,PHP引擎則拋出一個fatal錯誤,停止該腳本的執行
5.PHP單繼承的問題 ?traits ?
<?php
? ? trait Drive {
? ? ? ? public $carName = 'trait';
? ? ? ? public function driving() {
? ? ? ? ? ? echo "driving {$this->carName}\n";
? ? ? ? }
? ? }
? ? class Person {
? ? ? ? public function eat() {
? ? ? ? ? ? echo "eat\n";
? ? ? ? }
? ? }
? ? class Student extends Person {
? ? ? ? use Drive;
? ? ? ? public function study() {
? ? ? ? ? ? echo "study\n";
? ? ? ? }
? ? }
? ? $student = new Student();
? ? $student->study();
? ? $student->eat();
? ? $student->driving();
? 1> 如果Trait、基類和本類中都存在某個同名的屬性或者方法,最終會保留哪一個呢??
? ? 當方法或屬性同名時,當前類中的方法會覆蓋 trait的 方法,而 trait 的方法又覆蓋了基類中的方法。
? 2> 如果要組合多個Trait,通過逗號分隔 Trait名稱:
? ? ?use Trait1,Trait2
? 3> 如果多個Trait中包含同名方法或者屬性時,會怎樣呢?
? ? 是當組合的多個Trait包含同名屬性或者方法時,需要明確聲明解決沖突,否則會產生一個致命錯誤。使用insteadof和as操作符來解決沖突,insteadof是使用某個方法替代另一個,而as是給方法取一個別名,具體用法請看代碼:
?? ? ? ?class Class1 {
?? ? ? ?use Trait1, Trait2 {
?? ? ? ? ? ?Trait2::hello insteadof Trait1;
?? ? ? ? ? ?Trait1::hi insteadof Trait2;
?? ? ? ?}
?? ?}
? ?4> as關鍵詞還有另外一個用途,那就是修改方法的訪問控制:
?? ? ? ? ?<?php
?? ? ? ?trait Hello {
?? ? ? ? ? ?public function hello() {
?? ? ? ? ? ? ? ?echo "hello,trait\n";
?? ? ? ? ? ?}
?? ? ? ?}
?? ? ? ?class Class1 {
?? ? ? ? ? ?use Hello {
?? ? ? ? ? ? ? ?hello as protected;
?? ? ? ? ? ?}
?? ? ? ?}
?? ? ? ?class Class2 {
?? ? ? ? ? ?use Hello {
?? ? ? ? ? ? ? ?Hello::hello as private hi;
?? ? ? ? ? ?}
?? ? ? ?}
?? ? ? ?$Obj1 = new Class1();
?? ? ? ?$Obj1->hello(); # 報致命錯誤,因為hello方法被修改成受保護的
?? ? ? ?$Obj2 = new Class2();
?? ? ? ?$Obj2->hello(); # 原來的hello方法仍然是公共的
?? ? ? ?$Obj2->hi(); ?# 報致命錯誤,因為別名hi方法被修改成私有的
?? ?5>Trait 也能組合Trait,Trait中支持抽象方法、靜態屬性及靜態方法

PHP輸出緩沖區
? ?緩沖區:實際上是一個內存地址空間。它用來存儲速度不同步的設備或者優先級不同的設備之間傳輸數據的區域。通過緩沖可
? ?以使進程之間的交互時間等待變小,從而使從速度慢的設備讀取數據時,速度快的設備的操作進程不發生間斷
? ?
? ?PHP的輸出流包含很多內容,通常都是開發者要PHP輸出的文本,這些文本大多是用echo或printf()函數來輸出的
? ?

? ? 1>任何輸出內容的函數都會用到輸出緩沖區
? ? ? 這是指正常的PHP腳本,如果開發的是PHP擴展,使用的函數(C函數)可能會直接輸出寫到SAPI緩沖區層,不需要經過輸出緩沖層(我們可以在PHP源文件 main/php_output.h了解這些C函數的API文檔)
?

? ? 2>輸出緩沖區不是唯一用于緩沖輸出的層,它實際上只是很多層中的一個,輸出緩沖層的行為與使用的SAPI(Web或CLI)有關,不同的SAPI可能有不同的行為

? ? ? ? ? ? ? ? ? ? ? ? ? ?緩沖邏輯關系圖

最上端的兩次就是我們通常所認識的‘輸出緩沖區’


3>SAPI中的輸出緩沖區,這些都是PHP中的層,當輸出的字節離開PHP進入計算機體系結構中的更底層時,緩沖區又會不斷出現(終端緩沖區(terminal buffer)、fast-cgi緩沖區、Web服務器緩沖區、操作系統緩沖區、TCP/IP棧緩沖區等)。
? ?PHP CLI的SAPI有點特殊,CLI也稱命令行界面,它會將php.ini配置中output_buffer選項強制設置為0,這表示禁用默認PHP輸出緩沖區,所以在CLI中,默認情況下你要輸出的內容會直接傳遞到SAPI層,除非你手動調用ob_()類函數,并且在CLI中,implicit_flush的值也會被設置為1,
? ?注:我們經常混淆implicit_flush的作用,php的源代碼已說明一切:當implicit_flush被設置為打開(值為1)時,一旦有任何輸出寫到SAPI緩沖區,它都會立刻刷新(flush,意思把這些數據寫到更底層,并且緩沖區會被清空)
? ?也就是說任何數據到CLI SAPI中時,CLI SAPI都會立即將這些數據仍到它的下一層去,一般會是標準輸出管到,write()和fflush()這兩個函數就是負責做這件事情的

默認PHP輸出緩沖區:如果使用不同于CLI的SAPI,比如PHP-FPM,會用到下面3個與緩沖區相關的php.ini配置選項
? ?output_buffering
? ?implicit_flush
? ?output_handler
?首先不能再運行時使用ini_set()函數修改這幾個選項的值,因為這些值會在PHP程序啟動的時候,還沒有運行任何腳本之前解析,所以在運行時可以使用ini_set()改變值,但是并不會生效。我們只能通過編輯php.ini文件或者是在執行PHP程序的時候使用-d選項才能改變它們的值
?默認情況下,PHP發行版會在php.ini中會把output_buffering設置為4096個字節,如果將它的值設置為ON,那么默認的輸出緩沖區的大小為16KB
? ?在Web應用環境中對輸出的內容使用緩沖區對性能有好處
? ? ? 默認的4K的設置是一個合適的值,意味著你可以先寫入4096個ASCLL字符,然后在與下面的SAPI層通信,并且在Web應用環境中,通過Socket一個字節一個字節地傳輸消息的方式對性能并不好,更好的方式是把所有內容一次性傳輸給服務器,或者至少是一塊一塊地傳輸,層與層之間的數據交換次數越少,性能越好,應該總是保持輸出緩沖區處于可用狀態,PHP會負責在請求結束后把它們中的內容傳輸給終端用戶,開發者不用做任何事

? ? ? implicit_flush默認是設置為關閉,這樣的話新數據寫入就不會刷新SAPI,對于FastCGI協議,刷新操作是每次寫入后都發送一個FastCGI數組包,如果發送數據包之前先把FastCGI的緩沖器寫滿會更好。如果需要手動刷新SAPI的緩沖區,使用flush()函數,如果想寫一個就刷新一次可以設置implicit_flush或者調用一次ob_implicit_flush()函數
? ? ? 推薦使用配置:
? ? ? output_buffering=4096
? ? ? implicit_flush = Off/no
? ? ? 要修改輸出緩沖區的大小,硬確保使用的值是4/8的倍數,它們分別是32/64位操作系統
? ? ??
? ? ? output_handler是一個回調函數,它可以在緩沖區刷新之前修改緩沖區中的內容

? ? ? ?緩沖區中的內容會傳遞給你選擇的回調函數(只能用一個)來執行內容轉換的工作,所以說如果想獲取PHP給Web服務器以及用戶的內容,可以使用輸出緩沖區回調,輸出是指:消息頭、消息頭。HTTP的消息頭也是輸出緩沖區層的一部分
? 消息頭和消息體
? ? ? 實際上,任何與消息頭的輸出有關的PHP函數(header()、setcookie()、session_start())都使用內部的sapi_header_op函數,這個函數只會把內容寫入消息頭緩沖區中。 當我們如使用printf()函數的時候,內容會先被寫入到輸出緩沖區(可能是多個),當這個輸出環城區的內容需要被發送的時候,PHP會先發送消息頭,然后發送消息體。PHP為了搞定了所有的事情,如果想自己動手,那就只能禁掉輸出緩沖區

? 用戶輸出緩沖區:

? ? ? 如果想使用默認PHP輸出緩沖區層,就不能使用CLI,因為它已經禁用了這個層

/*launched via php -d output_buffering=32 -d implicit_flush=1 * */ echo str_repeat('a',31); sleep(3); echo 'b'; sleep(3); echo 'c'; ?>

? ?默認輸出緩沖區的大小設置32字節,程序運行會先寫入31字節,然后休眠,然后在寫入1一個字節,這個字節填滿緩沖區,它會立即刷新自身,把里面的數據傳遞給SAPI層的緩沖區,因為把implicit_flush設置為1,所以SAPI層的緩沖區也會立即刷新到下一層,所以輸出aa...b,然后休眠,然后在輸出一個字節,此時緩沖區有31空字節,但是腳本執行完畢,所以包含這個字節的緩沖區也會立即刷新,從而會在屏幕輸出c

? 用戶輸出緩沖區:通過ob_start()創建,我們可以創建多個這種緩沖區(直到內存耗盡為止),這些緩沖區組成一個堆棧結構,每個新建緩沖區都會堆疊到之前的緩沖區上,每次當它被填滿或者溢出,都會執行刷新操作,然后把其中的數據傳遞給下一個緩沖區

function callback($buffer) {// replace all the apples with orangesreturn ucfirst($buffer); }function callback1($buffer) {// replace all the apples with orangesstatic $a=0;return $a++.'-'.$buffer."\n"; } ob_start('callback1',10); ob_start("callback",3); echo "fo"; sleep(2); echo 'o'; sleep(2); echo "barbazz"; sleep(2); echo "hello";

按照棧的先進后出原則,任何輸出都會先存放在緩沖區2中。緩沖區2的大小為3個字節,所以當第一個echo語句輸出的字符串'fo'會先存放在緩沖區2中,還差一個字符,當第二個echo語句輸出'o'后,緩沖區2滿了,所以它會刷新(flush)。在刷新之前先調用ob_start()的回調函數,這個函數將緩沖區的首字母轉換成大寫,所以輸出為‘Foo’,然后它會被保存在緩沖區1中,第三個輸出為‘barbazz’,它還是會先放在緩沖區2中,這個字符串有7個字節,緩沖區2已經溢出了,所以它立刻刷新,調用回調函數得到的結構是‘Barbazz’,然后傳遞給緩沖區1中,這個緩沖區1中保存了'FooBarbazz'這十個字符,緩沖區1會刷新,同樣的先會調用ob_start()的回調函數,緩沖區1的回調函數會在字符串簽名添加型號,所以第一行是'0-FooBarbazz',

? ? 最后一個echo語句輸出一個字符串'hello',它大于三個字符,所以會觸發緩沖區2,因為此時腳本執行完畢,所以也會立即刷新緩沖區1,得到 ‘1-Hello’。

?因此使用echo函數如此簡單的事情,如果涉及緩沖區和性能也是復雜的,所以要注意使用echo輸出內容的大小,如果緩沖區配置與輸出內容相似,那么性能會比較優良,如果緩沖器配置小于輸出內容,需要在應用中輸出的內容做切分處理。

輸出緩沖區的機制:主要是在5.4以后整個緩沖層都被重寫,我們自己開發PECL擴展時,可以聲明屬于自己的輸出緩沖區回調方法,這樣可以于其他PECL擴展做區分,避免產生沖突

輸出緩沖區的陷阱

? ? ? 有些PHP的內部函數也使用了輸出緩沖區,它們會疊加到其他的緩沖區上,這些函數會填滿自己的緩沖區然后刷新,或者返回里面的內容,比如print_r()、higglight_file()和highlight_file::handle()都是此類,所以不應該在輸出緩沖區的回調函數中使用這些函數,這樣會導致未定義的錯誤

? ? ?同樣的道理,當PHP執行echo、print時,也不會立即通過tcp輸出到瀏覽器,而時將數據先寫入PHP的默認緩沖區,我們可以理解PHP有一套自己的輸出緩沖機制,在傳送給系統緩存之前建立一個新的隊列,數據經過該隊列,當一個PHP緩沖區寫滿以及腳本執行邏輯需要輸出時,腳本會把里面的數據傳輸給SAPI瀏覽器

? ? echo/print->php輸出緩沖區->SAPI緩沖區->TCP緩沖區->瀏覽器緩沖區->瀏覽器展示

? ? ?ob_flush()和flush()區別

? ? ? ? ob_flush():把數據從php的緩沖區中釋放出來

? ? ? ? flush():把不再緩沖區中的或者說是被釋放出來的數據發送到瀏覽器,嚴格來講, 這個只有在PHP做為apache的Module(handler或者filter)安裝的時候, 才有實際作用. 它是刷新WebServer(可以認為特指apache)的緩沖區.

? ? ? 在nginx中ob_flush和flush兩個都失效

? ? ? ? 解決辦法:? 發現在nginx的配置中,有如下的設置

? ? ? ? ? ? ??fastcgi_buffer_size 128k;

? ? ?fastcgi_buffers 8 128k;

Nginx會緩沖PHP輸出的信息,當達到128k時才會將緩沖區的數據發送給客戶端,那么我們首先需要將這個緩沖區調小

比如:

? ? ?fastcgi_buffer_size 4k;

? ? ?fastcgi_buffers 8 4k;

并且,必須禁用gzip

? ? ? ? ? ? ?gzip off;

然后,在php中,在ob_flush和flush前,輸出一段達到4k的內容,例如:

? ? ? ? ? ??echo str_repeat(‘ ‘, 1024*4);

到此,PHP就可以正常通過ob_flush和flush逐行輸出需要的內容了。

輸出緩沖區實踐

? ? 1>?通過ob_start()函數手動處理PHP緩沖區機制,這樣即便輸出內容超過配置參數大小,也不會把數據傳輸給瀏覽器,ob_start()將PHP緩沖區空間設置到足夠大,只有腳本執行結束后或調用ob_end_flush()函數,才會把數據發送給瀏覽器?

for($i=0;$i<10;$i++){ echo $i.'<br/>'; sleep($i+1); }

?執行之后不會每隔幾秒就有輸出,知道腳本循環結束后,才會一次性輸出,這是因為數據量太小,輸出緩沖區沒有寫滿

2>當修改output_buffering=0

for($i=0;$i<10;$i++){ echo $i.'<br/>'; flush(); sleep($i+1); }

?因為緩沖區的容量設置為0,禁用PHP緩沖區機制,這是我們在瀏覽器看到斷斷續續輸出,而不必等到腳本執行完畢才看到輸出,這是因為數據沒有在緩存中停留

3>我們把參數修改為output_buffering=4096,輸出數據大于一個緩沖區,不調用ob_start()函數

? ? 首先先輸出一個4k的內容記下來加本來輸出的內容:? ?

for($i=0;$i<10;$i++){ echo ?echo str_repeat(' ', 1024*4*8).$i<br/>; sleep($i); }

發現可以HTTP連接未關閉,可以看到間斷輸出,盡管啟用了PHP輸出緩沖區機制,但是也不是一次性輸出,這還是因為PHP緩沖區空間不夠,每寫滿一個緩沖區,數據就會發送到瀏覽器。

4>參照上例子,這次我們調用ob_start()

ob_start(); //開啟PHP緩沖區 for($i=0;$i<10;$i++){ echo ?echo str_repeat(' ', 1024*4*8).$i<br/>; sleep($i); }

等到服務端腳本全部處理完,響應結束才會看到完整的輸出,在輸出前瀏覽器會一直保持空白,這是因為,PHP一旦調用了ob_start()會將PHP緩沖區擴展到足夠大,知道ob_end_flush函數調用或者腳本運行結束才發送PHP緩沖區中的數據到客戶端瀏覽器

? 可以通過tcpdump命令監控TCP的報文,來觀察一下使用ob_start()和沒有使用它的區別

?總結:ob_start激活output_buffering機制,一旦激活,腳本不再直接輸出給瀏覽器,而是先暫時寫入PHP緩沖區

? ? ? ? ? ? PHP默認開啟out_buffering機制,通過調用ob_start函數把output_buffering值擴展到足夠大,也可以通過$chunk_size來指定output_buffering的值,$chunk_size默認值是0,表示直到腳本運行結束后,PHP緩沖區中的數據才會發送到瀏覽器,若設置了$chunk_size的大小,則只要緩沖區達到這個值,就會發送給瀏覽器你

? ? ? ? ? ?可以通過指定output_callback參數來處理PHP緩沖區的數據,比如ob_gzhandler()將緩沖區中的數據壓縮后傳送給瀏覽器,ob_get_contents()是獲取一份PHP緩沖區中的數據拷貝

ob_start(); echo date('Y-m-d h:i:s');$output=ob_get_contents(); ob_end_flush(); echo '<!output>'.$output;

?后者是從ob_get_contents取的緩沖區的內容

?ob_end_flush()與ob_end_clean(0這兩個函數都會關閉輸出緩沖,區別是前者只是把PHP緩沖中的數據發生給客戶端瀏覽器,而后者將PHP緩沖區中的數據刪掉,但不發送給客戶端,前者調用之后數據依然存在,ob_get_contents()依然可以獲取PHP緩沖區中的數據拷貝

輸出緩沖與靜態頁面

? ? ?大家都知道靜態頁面的加載速度快,不用請求數據庫,以下就是生成靜態頁面的腳本代碼

echo str_pad('',1024);//使緩沖區溢出 ob_start();//打開緩沖區 $content=ob_get_contents();//獲取緩沖區內容 $f=fopen('./index.html','w'); fwrite($f,$content);//寫入到文件 fclose($f); ob_end_clean()清空并關閉緩沖區

? 在一些模板引擎和頁面文件緩沖中ob_start()函數被使用,如 WP、Drupal、Smarty,例如:

在Wp經常在主題目錄header.php看到類似的代碼:

只有一個flush(),它的所在的位置就是告訴瀏覽器那一部分的緩存需要更新,即頁面頭部以上部分需緩存

以及Wp的部分代碼,可以看到,在緩沖區開啟時,加入自己的回調方法
?內容壓縮輸出:就是把輸出到客戶端瀏覽器的內容進行壓縮

好處:降低客戶端對服務器出口帶寬的占用,提升帶寬的利用率。降低Web服務器(如Nginx、Apache、Tomcat等)處理文本時引入的開銷,用戶端可以減少網絡傳輸延時對用戶體驗的影響,降低瀏覽器加載頁面內容時占用的內存,有利于改善瀏覽器穩定性?

ob_start('ob_gzhandler');//使用gz格式壓縮輸出 print'my contents'; ob_end_flush();

? ?之壓縮當前腳本與緩沖區,對其他腳本沒有影響,PHP還提供另外一種壓縮方式,在php.ini修改

? zlib_output_compression=On

? 這樣輸出時所有頁面都以zlib的壓縮方式輸出,但是兩者混用是毫無意義的,只會額外消耗CPU性能,讓它壓縮已經壓縮好的內容,但是基于實踐,使用PHP壓縮效果并不是十分理想,通常做法是放在Web服務器,比如Apache啟用defate、Nginx使用gzip的方式都比PHP端壓縮效果好得多

? ?輸出緩沖允許第三方庫和應用框架(Laravel、TP等)開發者完全控制它們自己輸出的內容。比如把他們放在一個全局緩沖區中處理,對于任何輸出流的內容(如數據壓縮)和任何HTTP消息頭、PHP都以正確的書序發送,使用輸出緩沖區能夠有效地節省帶寬,比如圖片、字體、CSS、JS等前端內容,特別是限制前端框架也越來越來,讓它使用戶反應速度更快,從而有效提高系統性能

PHP緩存技術
?Session:信息保存在服務器端,用鍵值訪問
?Cookie:通常為保存在客戶端瀏覽器中的Session的鍵值
? ? PHP創始人在設計PHP的時候,也同時發明了‘完全不共享的架構’。也就是服務器端的Session可以保存在文件、數據庫或內存緩存里,客戶端Cookie保存當前SessionID或瀏覽器URL中,帶一個加密字符串用來查詢Session狀態就可以了解當前會話狀態,由此就可保證網站中用戶的持續會話

? ? 緩存實現的基本原理是將數據庫查詢結果以字符串序列化形式保存在磁盤文件中,打開時再反序列化,這樣的效率會高于MySql數據庫查詢,特別是奪表連接查詢時會特別明顯? ? 靜態HTML與動態頁面的結合:內容保存在MySql中,但想在前端訪問的靜態HTML頁面,而且讓它在一定時間自動更新
? ? 代碼實例:

? <?php?ob_start();//開啟緩沖區$fileName='/cache/static.html';$filename=30; ?//3秒緩存if(file_exists($fileName)&&time()-filename<filemname($fileName){include($fileName);echo "<!--published at ".date("H:i".filemtime($cachefile))."by Think Creative CMS --> \n";exit();}echo '<--此處是要生成靜態的PHP腳本文件-->';echo filemtime($cachefile);$fp=fopen($fileName,'w');fwrite($fp,ob_get_contents());//將輸出緩沖區的內容寫到文件fcolse($fp);//關閉文件ob_end_flush();//將緩沖區內容立即輸出到瀏覽器,并關閉緩沖區

? ?1>執行靜態文件生成時,需要手工干預或者置于頁面以<script src='1.php'></script>或<img src='build_static.php' height=1 widht=1>這種類似標簽,在訪問所在頁面時觸發
? ?2>定時運行的話可以放在linux下的cron或者windows的計劃任務中運行,如果想24小時內生成頁面我們去掉filename的代碼判斷
? ?代碼實例:

?ob_start();//開啟緩沖輸出$fileName='/cache/static.html';$fp=fopen($fileName,'w');fwrite($fp,ob_get_contents());//將輸出緩沖區的內容寫到文件fcolse($fp);//關閉文件ob_end_flush();

隨著cron的時間來定期生成一個static.html

數據級別緩存
? 全頁面靜態化缺點:需要占用更多的存儲空間,有時候無法預計某一頁面的更新頻率過高,會使這部分的硬盤IO開銷更大
? ? 對于一些交互并不是特別高,但是負載又很大的應用,就需要考慮使用緩存這一機制:
? ? ? 1>數據緩存是在全動態的低效與全靜態占用大量存儲空間尋找一個平衡點。
? ? ? 2>數據緩存可在最新的或是比較活躍的數據上使用,在節約存儲空間的前提下,盡量提高數據緩存的使用效果
? ? 代碼實例:比如用戶管理類叫my_auth,并且所有用戶都使用id作為標識,比如保存的緩存內容就是'my_auth:users:123456',最后的數字是用戶id

?

opcode緩存:在系統編譯PHP時加入的緩存機制
? ? 由于PHP是解釋性語言,當解釋器執行PHP腳本時會解析腳本代碼,將它們生成可以直接運行的中間代碼,稱為ZendOpcode
? ? 1>PHP腳本執行順序與zend opcode
? ? ? zend引擎是PHP的編譯引擎和執行引擎,當它在執行一段PHP腳本時,會做出以下4個步驟:
? ? ? ? scanning:掃描,將PHP代碼轉換為語言片段
? ? ? ? Parsing:解析,將Tokens轉換成簡單而有意義的表達式
? ? ? ? Compilation:編譯,將表達式編譯成Opcode
? ? ? ? Execution:順次執行opcode,每次一條,執行完刷新內存后銷毀

? ? ? ? ? ? ??

?Nginx或其他Web服務器把HTTP請求轉發給PHP-FPM,PHP-FPM再把請求交給某個PHP子進程處理,PHP進程找到PHP腳本后執行,把腳本編譯為opcode后生成響應,每次請求一個PHP腳本都要編譯一次zend opcode,然后執行字節碼。
? ?字節碼緩存:能緩存預告編譯好的字節碼,減少應用的響應時間
? ? ?zend opcache:它將在PHP zend引擎的編譯器和執行器之間運行,并負責對已編譯的腳本進行代碼優化,以便交給執行引擎,使執行速度更快,在PHP5.5版本以后被內置,但是默認沒有啟用

?如果是自己的PHP運行環境,需要在configure命令時包含如下:
? --enable -opcache
? 編譯好,須在php.ini文件制定Zend OpCache的擴展庫的所在路徑
??

opecache.memory_consumption=64 ?OpCode緩存分配的內存數據,單位為M
opcache.interned_strings_buffer=16 存儲駐留字符串的內存量。PHP解釋器會使用指針處理,保存在內存中,如果再次使用相同的字符串,PHP解釋器會使用指針處理,以保證節省內存。在默認情況下,PHP駐留的字符串會在各個PHP進程中隔離,該選項能夠讓PHP-FPM進程池中的所有進程共享字符串存儲,可以讓PHP-FPM進程之間引用駐留字符串,從而節省更多內存
opcache.max_accelerated_files=4000 設置opcode緩存中最多保存多少個PHP腳本
opcache.validate_timestamps=1 設置為1,PHP會檢查是否有更新。檢查的時間間隔由opcache.revalidate_rreq選項指定,設置為0,PHP就不會檢查PHP腳本的內容是否發生了變化,需要我們手工清除緩存操作碼(建議在開發環境設置1,生產設置為0)
opcache.fast_shutdown=1 這個設置能夠讓opcode使用更快的退出步驟。把對象析構與內存釋放交給Zend Engine的內存管理器來完成

Ioncube:ioncube是一個保護使用PHP編程語言編寫的軟件不被查看的工具。這些工具使用在編碼之前編譯為字節碼的技術,從而消除了源代碼,減少了運行時開銷(加密)。還有一個名為ionCubeLoader的PHP擴展在運行時處理編碼文件的讀取和執行(解密)。
?與Zend Guard不同:不僅支持期限、注冊碼等加密方式,還支持對IP、MAC地址等復雜的加密算法,還可以加密除了PHP文件外的XML、JS等,如果要巡行ioncube Encode 加密的PHP軟件 就要安裝ioncube PHP loader,必須在Zend Optimizer之前運行

? ? ? ? ? ? ? ? ? ? ?使用ionCube Encode 加密的PHP編譯與執行過程

使用APC
? PHP APC提供兩種緩存功能,編譯緩存和用戶數據緩存,即opcode,同是它還提供一些接口將用戶數據駐留在內存中,稱為apc_user_cache(apc_store和apc_fetch)函數操作讀取、寫入的
APC與Zend opcode:
? 1>APC有數據緩存API,而Zend opcache沒有
? 2>APC能夠回收舊的無效的腳本占用的內存,APC有內存管理器,可以將那些不再使用的腳本管理的內存進行回收,而Zend opcache不同,它將這一的內存標記為臟數據,不會回收他們,一旦內存占用到達配置的閾值,zend opcache就將自己重新啟動
? 鳥哥在這里有說明:http://www.laruence.com/2013/03/18/2846.html

使用deflate壓縮頁面: HTTP協議允許壓縮傳輸數據,提升并節約帶寬

? 在Apache中的標準壓縮擴展沒款,以前稱為gzip,這表示會對html、js等壓縮后在輸出到瀏覽器,在nignx配置文件中添加這個配置就可以了

?

內存數據庫


? 基于文件的緩存和基于內存的數據庫有兩個本質區別:首先基于內存的緩存需要一個中間件,即要訪問系統內存,其次,實現內存的緩存容易丟失和有限的空間,此外,基于內存的緩存通常不會出現鎖定,而基于文件的緩存有此問題或者有權限屬性等
memcached特性
? 是基于libevent庫 一個非阻塞式的網絡程序庫開發的,libevent是一個事件觸發的程序庫,它將Linux的epoll、BSD類操作系統的kqueue等時間處理功能封裝成統一的接口,即服務器的并發數量非常大的時候也能保持快速響應的能力
內存存儲處理
? ??1>memcached 首先按照預先規定大小,將內存分割成各種尺寸的塊(chunk),并把尺寸相同的塊分成組(chunkgroup),從而解決內存碎片問題
? ? 2>memcached根據收到數據大小,選擇合適的slab,memcached中保存著slab內空閑的chunk列表,根據該列表選擇chunk,然后緩存與其中,但是由于分配都是固定長度的內存塊,因此無法有效利用分配的內存空間比如100字節放入128chunk中
memcached的數據處理算法
? ? ?當內存容量達到指定值,就會基于LRU(刪除最近最少使用)算法自動刪除不適用的緩存
? ? 數據過期方式包括兩種:lazy Expiration 和 LRU 。 內部不會監視記錄是否已經過期,而是進行get時查看記錄的時間錯判斷是否過去,這種技術成為(惰性)Lazy Expiration,所以memcached不會在過期監視上耗費CPU
? ? ?memcached會優先使用已經過期記錄的內存空間,但也會發生追加新記錄時內存不足的情況,此時LRU機制開始使用,當內存空間不足時(無法從slab class獲取新的空間時),就從最近未被使用的記錄中搜索,并將其空間分配給新的記錄,從緩存的使用角度,該模型是十分理想的
memcached分布式結構與算法
? ? 盡管memcached是分布式緩存服務器,但是服務端并沒有分布式功能,所以說客戶端通過一個分布算法和維護一個服務器列表來實現分布式,目前的分布式有兩種:
? ? ?1>取模算法
? ? ?2>一致性算法
memcached解決Session共享問題
? ? 修改php.ini

或是在php腳本寫:

如果是多個可以用逗號隔開:

PHP網絡編程


?1.Socket原理 是由操作系統提供的通信層的一組API
? ? ?Socket位于TCP/IP協議的傳輸控制層,提供客戶服務器模式的異步通信,即客戶向服務器發出服務請求,服務器收到請求后,提供相應的反饋或服務,也就是兩臺主機之間通信的通道
? ? ? ?應用程序通過它來發送和接受數據,就像應用程序打開一個文件句柄,將數據讀寫到穩定的存儲器上一樣
? ? ? ? 客戶/服務器模式在操作系統的是主動請求方式:
? ? ? ? 服務器處理步驟如下:
? ? ? ? ? 1>打開一個通信通道并告知本地主機,它愿意在某一IP地址和端口上接收客戶端請求
? ? ? ? ? 2>等待客戶請求達到該端口
? ? ? ? ? 3>接收重復服務請求,處理該請求并發送應答信號
? ? ? ? ? ? 接收到并發服務請求,要激活一個新進程來處理這個客戶請求(如Linux中fork和exec)新進程處理此次客戶請求,并不需要對其他請求做出應答,服務完成后,關閉此新進程和客戶的通信鏈路,并終止服務
? ? ? ? ? 4>返回第(2)步,等待另一個客戶請求
? ? ? ? ? 5>關閉服務器
? ? ? ? 客戶端的處理步驟:
? ? ? ? ? 1>打開一通信通道,并連接到服務器所在主機的特定端口
? ? ? ? ? 2>向服務器發送服務請求報文,等待并接收應答,繼續提出請求
? ? ? ? ? 3>請求結束,關閉通信通道并終止
? ? ? ? Socket是連接其他網絡主機的一種方法,該主機可以使互聯網或局域網上的任何一臺計算機,創建Socket服務器,監聽外部請求并制定端口提供連續的服務,通常作為一種服務或者一個系統守護進程持續運行

? ? ?在TCP/IP協議族中的主要Socket類型為:
? ? ? ? ? ? ? ? ? ? 1>流套接字(stream socket),傳輸層使用TCP協議,提供了一個可信賴的字節流服務
? ? ? ? ? ? ? ? ? ? 2>數據報套接字:傳輸層使用UDP 協議,最長以發送65500字節數據,
? ? ? ? ? TCP適合發送圖片、文件或者其他信息必須全部結束和反饋(電子郵件)等服務
? ? ? ? ? UDP適合發送流數據、如音樂、視頻數據流,UDP是無連接協議,但是TCP它可以遵守IP協議
? ? ?Socket的出現只是使得程序員更方便地使用TCP/IP協議棧而已,是對TCP/IP協議的抽象
? 2.Socket函數
? ? PHP提供了開發者 Socket API有兩種: 內核中,只能做主動連接而無法實現端口監聽相關功能 ?PECL擴展卡,支持監聽和交互模式
? ??

該函數功能是初始化一個Socket套接字并連接到目標主機
?psockopen()函數實現的持久化連接,也被稱為長連接

? 它和socketopen函數功能相同,唯一區別就是建立的是長連接
? 這兩個函數執行后都會返回一個資源編號,這個資源幾乎可以使用其他文件操作函數對其進行操作,如fgets()、fwrite()、fclose()等。比如fread()從函數指針讀取指定長度自己

<?php$fp=fsockopen("www.baidu.com",80,$errno,$errstr,30);//$fp=fsockopen("udp://127.0.0.1",13,$errn,$errstr); udpif(!$fp){echo "$errstr($errno)<br/>n";}else{$out="GET/HTTP/1.1\n\n";//發送數據fwrite($fp,$out);while(!feof($fp)){echo fgets($fp,128);}fclose($fp);} echo $fp; ?>

cURL核心技術

? ? 主要是獲取遠程文件或傳輸文件,支持FTP\FTPS、HTTP\HTTPS等協議


PHP cURL參數:
??
? 1>CURL_OPT_FOLLOWLOCATION和 CURLOP_MAXREDIRS
? ?第一個參數用來跟蹤目標頁面是否有重定向,目前只支持header重定向處理,對于后面的mata和js跳轉則無法識別
? ?第二個參數用于定義最大的重定向跟蹤次數,以防止過程總是進入同一個網站,死循環
?curl_setopt($ch,CURLOPT_FOLLOWCATION,TRUE); //跟蹤header頭重定向
?curl_setopt($ch,CURLOPT_MAMREDIRS,5);//設置重定向跟隨為5次
? ?
? ?2>CURLOPT_USERAGENT
? ? 用來定義用戶代理的名稱,比如我們模擬微信的內置瀏覽器訪問某個網站:
? ? $agent='Mozilla/5.0 (iphon;CUP iphone).......';
? ? curl_setopt($ch,CURLOPT_USERAGENT,$agent);
? ? 現在有一些網站會檢測用戶代理,然后決定是否提供服務,或代理的不同,顯示不同的頁面
? ? 可以用自己的設備訪問:
? ? ?echo $_SERVER['HTTP_USER_AGENT'];
? ?
? ?3>CURLOPT_NOBODY與CURLOPT_HEADER
? ? ?前者返回內容的主體內容,后者返回內容的頭內容
? ? ?curl_setopt($ch,CURLOPT_HEADER,TRUE);
? ? ?curl_setopt($ch,CURLOPT_NOBODY,TRUE);
? ?
? ?4>CURLOPT_TIMEOUT與CURLOPT_CONNECTTIMEOUT
? ? ?設置cURL操作時等待目標服務器的響應時間比如目標服務器宕機這樣會造成我們爬蟲無線等待,其實常用在抓取一些訪問量大的站點,返回較慢
? ? ?鏈接404等

? ? ?curl_setopt($ch,CURLOPT_TIMEOUT,30);

? ? 5>CURLOPT_COOKIEFILE與CURLOPT_COOKIEJAR
? ? ? 它能夠幫我們在傳輸抓取過程中向服務器傳遞Cookie信息,可以使用前者定義之前存儲Cookie的文件位置,會話完成時,cURL把新的Cookie寫入到第二個指定文件中:
? ? ? ?curl_setopt($ch,CURLOPT_COOKIEFILE,'/usr/tmp/cookies.txt');//讀取cookie文件
? ? ? ?curl_setopt($ch,CURLOPT_COOKIEFILE,'/usr/tmp/cookies.txt');//寫入到cookie文件
? ? 6>CURLOPT_HTTPHEADER
? ? ? 它可讓我們自定義在讓目標服務器接受的header頭內容,如告知目標服務器能接受的MIME、內容類型、用戶代理及壓縮類型等內容
? ? ? ?$header_arr[]='Mime-version:1.0';
? ? ? ?$header_arr[]='Content-type:text/html;charset=utf-8';
? ? ? ?$header_arr[]='Accept-encoding:commperss,gzip';

? ? 7>CURLOPT_SSL_VERYFYPEER
? ? ? 適用于服務器使用了SSL加密,及HTTPS時用到
? ? ? ?curl_setopt($ch,CURLOPR_SSL_VERYFYPEER,FALSE); //沒有使用正式

? ? 8>CURLOPT_SSL_VERSION
? ? ? 用來定義目標服務器SSL版本相對于,使用的SSL版本2或3,但是過去SSL漏洞,騰訊已經廢棄了2和3版本,改成了TLS
? ? ? ?curl_setopt($ch,CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1);
? ??
? ? 9>CURLOPT_USERPWD和CURLOPT_UNRESTRICTED_AUTH
? ? ? ?此選項適合于對方服務器有基本認證的情況,這兩個選項分別加入基本認知用戶密碼
? ? ? ?curl_setopt($ch,CURL_USERPWD,"name:pwd");
? ??
? ? 10>CURLOPT_POST與CURLOPT_POSTFILELDS
? ? ? ?模擬提交時重要參數
? ? ? ?curl_setopt($ch,CURLOPT_POST,TRUE);
? ? ? ?$data='name=post數據&';
? ? ? ?curl_stopt($ch,CURLOPT_POSTFIELD,$data);
? ? ? 如果使用get方法的話,只需要在目標URL后加入查詢的字符串可以實現
? ??
? ? 11>CURLOPT_PORT
? ? ? ?設置連接的端口號

實例一:
?? ? ? ?

? <?php$ch=curl_init() or die(curl_error());curl_setopt($ch, CURLOPT_URL,"http://www.baidu.com/");curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);//設置exec獲取信息以字符流的形式返回curl_setopt($ch,CURLOPT_REFERER, "http://weibo.com/");curl_setopt($ch,CURLOPT_HEADER,1);//啟用的時候會將頭信息作為字符流輸出$output=curl_exec($ch) or die(curl_error());if($output==FALSE){ //區分空格輸出和布爾值FALSEecho curl_error($ch);}else{echo $output;}curl_close($ch);


?? ?其中 $info=curl_getinfo($ch,CURLINFO_HTTP_CODE); 返回curl執行后這一請求的相關信息


實例二:使用cURL上傳圖片
?

? ?$url='';$file_path='1.jpg';$post=array('info'=>'123','file_contents'=>new \CURLFile(realpath($file_pat)));//接下來用post上傳curl_setopt($ch,CURLOPT_POSTFIELDS,$post);

實例三:cURL批量處理

? $ch1=curl_init('http//aa.com');$ch2=curl_init('http//bb.com');curl_stopt($ch1,CURLOPT_RETURNTRANSFER,true);curl_stopt($ch2,CURLOPT_RETURNTRANSFER,true); //兩個cur資源加入$mh句柄中$mh=curl_multi_init();curl_multi_add_handle($mh,$ch1);curl_multi_add_handle($mh,$ch2); //執行批處理等待全部完成$running=null;do{curl_multi_exec($mh,$running);}while($running); //完成后,返回獲取內容$r1=curl_multi_getcontent($ch1);$r2=curl_multi_getcontent($ch2); //關閉句柄curl_muilti_remove_handle($mh,ch1);curl_muilti_remove_handle($mh,ch2);//? 這個循環重復調用curl_muilti_exec() 這個函數是有阻塞的,但是它會盡可能減少執行


?實例四:模擬cookie登陸
? ? ?

?$ch=curl_init();curl_setopt($ch,CURLOPT_URL,'http://mis.example.com/index.php');curl_setopt($ch,CURLOPT_POST,1);curl_setopt($ch,CURLOPT_POSTFIELDS,'name=admin&pwd=123&action=login');//模仿瀏覽器行為,并保存cookie內容curl_setopt($ch,CURLOPT_COOKIEJAR,'cookie.txt');curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//執行請求,表單登陸curl_exec($ch);//設置文件下載的參數curl_setopt($ch,URLOPT_URL,'http://mis.example.com/index.php?file_id=2');//執行第二次請求 文件下載$content=curl_exec($ch);//為取得的文件內容//關閉curl_close($ch);

cURL的底層也是Socket
? ? ??

?

?

PHP測試與調優


?1.使用魔術常量:就是這個常量保存著當前PHP腳本運行時的狀態

2.建立堆棧跟蹤
? ?1>debug_zval_dump() ?
? ? ?輸出結果跟var_dump類似,唯一增加的一個值是refcount,就是記錄一個變量被引用多少次,這是PHP的copy on write(寫時復制)的機制的一個重要特點。
?3.活用日志
? ? ? ? ?為了節約磁盤IO操作,可以放在一個對象里,等對象析構的時候再執行物理寫入操作
? ? ? ? 簡寫代碼:
? ? ? ?function logtext($text){
? ? ? ? $time =date('y-m-d h:i:s',time());
? ? ? ? file_put_contents('log.txt',$time." ?".$text."\n",FILE_APPEND); ? ? ? ?
};

用戶驗證策略


? ?作為開發者,要充分了解PHP安全的必要性,特別是帶有用戶信息等敏感數據時。
? ?純PHP驗證
? ? 1.自定義session:PHP的SESSION會話是將用戶信息存儲在服務器上,一般情況下,一個sessionID會存儲在客戶端的Cookie中,然后通過SessionID的時間維護Session生命周期的建立和保存
? ? ? 注意:Session也可不需要使用cookie,sessionID可以通過GET和POST變量傳遞,該驗證設置在配置文件修改
? ? ? 好處

?????1>.提高系統的安全性,并且在共享主機服務器上,如果沒有進行特別的設定,所有網站站點都會使用同一個臨時目錄,意味著數十個程序都在同一個位置對文件進行讀寫操作。我們就很容易地編寫一個腳本從這個目錄讀取會話文件夾中所有文件的內容

???? 2>.另外把會話數據放在數據庫里還可以更方便地搜索Web站點會話更多的信息,我們可以查詢會話的數量,還可以對會話數據進行備份?

???? 3>.如果站點運行與多個服務器上,在這種情況下,同一個用戶在一個會話過程中可能會對不同的服務器上的多個頁面發送請求,但是會話數據如果保存在某一個服務器上的文件里,就不能被這臺服務器外的其他服務器上的頁面所使用,所以除了數據庫寶UC你,就沒有其他解決的辦法了

注:在共享主機上,設計安全問題的另一個技巧就是改變會話的目錄,我們可以每次調用seeion_start()之前調用session_save_path(),當然要確保新目錄存在并且具有合適的權限
? ??
? ? 2.構造安全的Cookie:
? ? ? ? ?當用戶登陸后,會將登陸的相關信息以純文本的形式放在Cookie中,這樣容易地被攻擊者看并復制。
? ? ? ?1> 需要以下的cookie的內容進行加密處理
? ? ? ? ? UserID、用戶最后登錄的IP地址、一個時間戳
? ? ? ? 第一個是用來了解是哪些用戶登錄,第二個是用來記錄最后登錄的IP地址,可以用它與服務端IP地址比較,如果IP地址不匹配,有可能發生Cookie被劫持,或者是用戶在同一個地點使用筆記本里用其他無線接入點上網
? ? ? ? 時間戳:是由來記錄Cookie的創建日期和時間,這條記錄有兩個目的,第一個是可以檢測用戶多長時間沒有登錄,第二個是比較用戶登錄間隔時間,當發現用戶很短時間在不同IP地址登錄,對登陸加以限制
? ? ? ??
? ? ? ? 2>三點信任度可以表示使用這個Cookie設計
? ? ? ? ? 最信任:IP地址與最近的時間戳匹配
? ? ? ? ? 較信任:IP地址匹配,但時間戳太舊,這表示用戶已經離開計算機,屬于無人值守
? ? ? ? ? 最不信任:IP地址不匹配

? ? ? ? ? 以下為自己總結的一個方法:
? ? ? ? ? ? 固定的數字不可靠,用戶的密碼字符串作為salt是更好的辦法
? ? ? ? ? ? 簽名字符串:
? ? ? ? ? ? ? $sign = md5('$user_id+$user+_password[+瀏覽器UA[+IP地址[...]]]');
? ? ? ? ? ? 存儲到cookie里面的字符串為:
? ? ? ? ? ? ? $token = $user_id.','.$sign;
? ? ? ? ? ? 然后你需要對用戶記錄做一個服務器端的緩存,緩存通過用戶編號查詢,里面至少要包含用戶的密碼
? ? ? ? ? ? 這樣的好處有:
? ? ? ? ? ? ? ? 不存在私鑰泄漏的問題,即使出問題也不會影響所有用戶
? ? ? ? ? ? ? ? slat字符串泄漏就等同于用戶的密碼泄漏,邏輯上是嚴密的
? ? ? ? ? ? ? ? 即使有人持有$token字符串,只要用戶一修改密碼,老的$token就馬上失效了
? ? ? ? ? ? 在此基礎上還可以有其它的發揮,比如用戶記錄設計專門的一個字段:salt,每次用戶登錄成功時就生成一個隨機字符串更新到salt內,數字簽名計算用
? ? ? ? ? ? ? ? ?記得把$user_salt也放到緩存里
? ? ? ? ? ? ? ? ?$sign = md5('$user_id+$user_password+$user_salt+...');
? ? ? ? ? ? 這樣一來,每次用戶重新登錄之后,之前的$token一定會失效,不但安全性更高,而且還實現了每次只允許一個人登錄使用?

? ? ? ? ? 當出現不信任就要提示用戶再次輸入密碼,輸入正確后重置時間戳和IP地址
? ? ? ? ? 作為安全的最后級別,加密有益于數據驗證以及用戶數據的安全,我們將UserId也同時添加到Session中,當Cookie和Session兩端的UserId不匹配時候,可以證明有人偽裝Cookie或者數據被破壞,這時,登陸的Session和Cookie被銷毀

深度理解MySql驅動與存儲引擎


?mysql采用基于組件的模塊化設計,使用C/C++開發。架構是一個類似于子系統組成的架構,子系統緊密和高效配合。
? 主要講一下PHP與mysql關系
? ? 在PHP5.3以后用C重寫了連接MySQL的驅動庫,稱為mysqlnd,它是由一個完全用PHP許可證編寫的,準守MYSQL通信協議的新驅動,不像之前的驅動編譯過程中還需要連接MYSQL官網,然后分發當前主機。 并且支持mysqli客戶端API庫的持久連接。由于mysqlnd是PHP擴展,意味著它可以使用管理PHP內存和其他枯燥和扭矩,與PHP Zend引擎高度集成,充分使用PHP的流API(stream API)以及客戶端緩存機制,執行速度更快、內存消耗更小。
? ? 查看當前連接驅動:
?

? ? <php$mysqlnd=function_exists('mysqli_fetch_all');if($mysqlnd){echo 'mysqlnd enabled';}


? ? 測試PDO中使用的驅動是否正常:

? ? if(strpos($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION), 'mysqlnd')!==FALSE){echo 'PDO mysqlnd enabled'; }


?

?

總結

以上是生活随笔為你收集整理的读书笔记:PHP和MySQL高性能应用开发 (2019.2.20-2019.3.4)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人影视免费观看 | 国产啊啊啊啊 | 丁香婷婷视频 | www.麻豆av.com | 亚洲av无码久久忘忧草 | 国产伦精品一区二区 | 国产在线视频二区 | 黄色三级小视频 | 在线视频一区二区三区四区 | 欧洲成人在线观看 | 亚洲国产精品成人午夜在线观看 | 日韩夜夜操 | 一区二区不卡在线 | 黄色理伦片 | 人人爽人人射 | 久久精品视频1 | 日本黄色片. | 久久精品影视 | 男人插女人的网站 | 亚洲色图制服诱惑 | brazzers欧美极品少妇 | 黄污视频网站 | 无码精品国产一区二区三区免费 | 日批av | 青青草手机视频 | 成人在线免费高清视频 | 古典武侠av | 18成人在线观看 | 国产综合久久久久久鬼色 | 欧美黄色免费大片 | 中文字幕人妻一区二区三区 | 亚洲永久免费网站 | 爽爽影院免费观看 | 成人伊人| 美女黄色一级片 | 97人妻天天摸天天爽天天 | 黄色录像大片 | 国产无套精品一区二区 | 三区在线观看 | 国产精品综合一区二区 | 国产精品毛片久久久久久久av | 亚洲自拍偷拍欧美 | 免费成人高清 | 可以直接观看的av | 五月开心婷婷 | 四虎永久地址 | jiuse九色 | 永久免费未满视频 | 五月婷婷六月综合 | 天堂av资源在线观看 | av大帝在线观看 | 亚洲伦理在线观看 | 麻豆视频一区 | 拍国产真实乱人偷精品 | 九九热这里有精品视频 | 日本一区二区不卡在线观看 | 成人福利一区二区 | 97超碰在线免费 | 欧美高清hd18日本 | 亚洲国产精品电影 | 午夜影院在线免费观看 | 国产精品久久久久久久久久久久久久 | 国产精品一区二 | 久久久久一区二区精码av少妇 | 国产喷水视频 | 国产伦精品一区二区三区千人斩 | 国产一区二区三区91 | 都市激情av | www视频免费观看 | 奇米网狠狠干 | 亚洲熟女乱色综合亚洲小说 | 欧洲性开放大片 | 男同毛片 | 成人做受视频试看60秒 | 日韩欧美精品国产 | 欧美日韩国产片 | 用我的手指扰乱你 | 99久久久久无码国产精品 | 99久久99久久精品国产片 | 在线播放网址 | 三级网站免费看 | 国产精品毛片va一区二区三区 | 紧身裙女教师三上悠亚红杏 | 欧美午夜精品理论片a级按摩 | 99自拍偷拍 | 绯色av一区二区三区高清 | 69精品久久久久久久 | 亚洲二区在线观看 | 国产精品视频一区二区在线观看 | 在线观看中文字幕亚洲 | 中文字幕乱码人妻一区二区三区 | 日韩欧美中文字幕在线视频 | 91亚洲国产成人精品一区 | 黄毛片在线观看 | 黄色高清片| 综合久久av| 91精品国产aⅴ一区二区 | 久久久久国产精品一区 | 欧美乱大交xxxxx潮喷l头像 |