- //第51題:統計一維數組中所有值出現的次數?返回一個數組,其元素的鍵名是原數組的值;鍵值是該值在原數組中出現的次數
- $array=array(4,5,1,2,3,1,2,"a","a");
- $ac=array_count_values($array);
- /**
- * 輸出結果:
- * Array(
- * [4] => 1
- * [5] => 1
- * [1] => 2
- * [2] => 2
- * [3] => 1
- * [a] => 2
- * )
- */
- echo "<pre>";print_r($ac);
- //第52題:如何統計字符串中每種字符的出現次數並排序?
- function countStr($str){
- $str_array=str_split($str);//str_split()函數能將字符串中每個字符都轉化爲數組的元素
- $str_array=array_count_values($str_array);
- arsort($str_array);//arsort()函數對數組進行逆向排序並保持索引關係
- return $str_array;
- }
- $str="asdfgfdas323344##$\$fdsdfg*$**$*$**$$443563536254fas";
- /**
- * 輸出結果:
- * Array(
- [$] => 7
- [3] => 6
- [*] => 6
- [4] => 5
- [f] => 5
- [s] => 4
- [d] => 4
- [5] => 3
- [a] => 3
- [6] => 2
- [2] => 2
- [g] => 2
- [#] => 2
- )
- */
- echo "<pre>";print_r(countStr($str));
- //第53題:str_word_count() 函數計算字符串中的單詞數?
- /**
- * 輸出結果:2
- */
- echo str_word_count("Hello world!");//參數二:默認0,返回單詞的數目
- /**
- * 輸出結果:
- Array(
- [0] => Hello
- [1] => world
- )
- */
- echo "<pre>";print_r(str_word_count("Hello world!",1));//參數二:1-返回包含字符串中的單詞的數組
- /**
- * 輸出結果:
- Array(
- [0] => Hello
- [6] => world
- )
- */
- echo "<pre>";print_r(str_word_count("Hello world!",2));//參數二:2-返回一個數組,其中的鍵是單詞在字符串中的位置,值是實際的單詞.
- <?php
- /**
- * 第56題:redis與memcached區別?
- *
- * 不同點:
- *
- * (1)redis中並不是所有數據在有效期內只能常駐內存的(如果需要,可定期同步持久化到磁盤),這是和memcached相比一個最大的區別(memcached中的數據在有效期內是以鍵值對的形式常駐內存的)
- * (2)redis不僅僅支持簡單的鍵值對類型的數據,同時還提供list,set,hash等數據結構的存儲;memcached僅支持簡單的鍵值對類型的數據,但是memcached卻可以緩存圖片、視頻等等數據
- * (3)redis支持數據的備份,即master-slave模式的數據備份
- * (4)redis支持數據的持久化和數據同步,可以將內存中的數據保存在磁盤中,重啓系統後可以再次加載進行使用,緩存數據不會因此而丟失.memached緩存數據是常駐內存的,重啓系統後數據就沒了
- * (5)redis可以通過expire設定有效期,memcached在set數據的時候可以指定要緩存的數據永不過期
- * (6)redis可以做一主多從;memcached也可以做一主多從
- * (7)redis當物理內存用完時,可以將一些很久沒用到的value交換到磁盤;memcached當物理內存用完後就會自動清理一些早期的數據
- *
- * 相同點:
- *
- * (1)redis和memcached都是將數據存放在內存中,都是內存數據庫
- * (2)redis和memcached都可以做一主多從
- *
- * 性能:
- *
- * (1)redis根據其官方的測試結果:在50個併發的情況下請求10w次,寫的速度是110000次/s,讀的速度是81000次/s
- * (2)redis將鍵名與值的最大上限各自設定爲512MB;memcached則<span id="transmark"></span>將鍵名限制在250字節,值也被限制在不超過1MB,且只適用於普通字符串.
- *
- * 何時使用memcached:
- *
- * (1)小型靜態數據:當我們需要緩存小型靜態數據的時候可以考慮memcached,最具代表性的例子就是HTML代碼片段;因爲memcached的內部內存管理機制雖然不像redis的那樣複雜,但卻更具實際效率,這是因爲memcached在處理元數據時所消耗的內存資源相對更少.作爲memcached所支持的惟一一種數據類型,字符串非常適合用於保存那些只需要進行讀取操作的數據,因爲字符串本身無需進行進一步處理<span id="transmark"></span>.
- *
- */
- ?>
- <?php
- //第57題:memcached的使用案例
- //第一步:獲取數據
- function get_data(){
- $sql = "SELECT * from order_master ";//一般來說都是超級複雜的sql語句
- return $this->db->cache_all($sql);//獲取緩存數據(如果緩存數據過期,則重新查詢數據庫並將查詢到的數據放到memcache中並返回)
- }
- //第二步:獲取memcache中緩存數據
- public function cache_all($sql, $reload = false, $limit = null) {//參數1-sql語句、參數2-是否從數據庫中重新獲取數據並寫入memcache、參數3-每次獲取記錄數量
- $this->reload = $reload;
- $sql = $this->get_query_sql($sql, $limit);//拼接sql語句,如:'select * from order_master limit 0,10'
- return $this->get_cache($sql, 'get_all');//參數1-拼接的sql、參數2-要執行的方法名;將sql語句作爲參數調用get_all()方法
- }
- //第三步:從memcache中獲取緩存數據 提示:1、如果緩存數據過期,則重新查詢數據庫並將查詢結果放到memcache緩存中,返回數據. 2、如果緩存數據未過期,則直接獲取緩存數據
- protected function get_cache($sql,$method) {
- $cache_file = md5($sql.$method);//memcache中緩存數據的鍵名,格式:鍵名=md5(sql語句+方法名) 提示:一定要保證鍵名唯一
- $res = $this->cache->get($cache_file);//根據緩存數據的鍵名獲取鍵值
- if(!$res) {//memcache中緩存數據過期的情況//如果memcache中緩存數據過期,則重新從數據庫中獲取數據,並將結果以鍵值對形式存儲到memcache中
- $res= $this->$method($sql);//調用 $this->get_all($sql);//直接從數據庫中獲取數據並返回
- if($res && $this->cache_mark && !$this->reload) {
- $this->cache->set($cache_file, $res);//將數據庫中查詢到的數據以鍵值對形式set到memcache緩存中
- }
- }
- return $res;//返回數據
- }
- //第四步:直接從數據庫中獲取數據並返回
- public function get_all($sql, $limit = null, $fetch_mode = MYSQLI_ASSOC) {
- $this->query($sql, $limit);
- $all_rows = array();
- $this->fetch_mode = $fetch_mode;
- while($rows = $this->fetch()) {
- $all_rows[] = $rows;
- }
- $this->free();
- return $all_rows;
- }
- ?>
- //第58題:文件緩存的使用案例
- public function &get($key, $cache_time = '') {
- if(empty ($cache_time)) {
- $cache_time = $this->cache_time;//緩存時間
- } else {
- $cache_time = intval($cache_time);//緩存時間
- }
- $cache_encode_key = $this->get_key($key);//獲取一個唯一的長字符串
- //緩存文件的命名和緩存文件的存放位置
- $filename = $this->cache_dir.'/'.substr($cache_encode_key,0,2).'/'.substr($cache_encode_key,2,2).'/'.$cache_encode_key.".cache.php";
- if(!is_file($filename) || time() - filemtime($filename) > $cache_time) {//如果緩存文件不存在或者緩存文件過期,則返回false
- return false;
- } else {
- return unserialize(file_get_contents($filename));//如果緩存文件存在且未過期,那麼讀取緩存文件內容並返回
- }
- }
- public function set($key,$data) {
- $cache_encode_key = $this->get_key($key);
- $cache_dir = $this->cache_dir.'/'.substr($cache_encode_key,0,2).'/'.substr($cache_encode_key,2,2).'/';//緩存文件的緩存目錄
- $filename = $cache_dir.$cache_encode_key.".cache.php";//緩存文件名
- if( $this->mkpath($cache_dir) ) {//遞歸創建緩存目錄
- $out = serialize($data);//將要緩存的數據序列化
- file_put_contents($filename, $out);//將序列化的數據寫入到緩存文件中
- }
- }
- public function add($key, $data) {
- $cache_encode_key = $this->get_key($key);
- $cache_dir = $this->cache_dir.'/'.substr($cache_encode_key,0,2).'/'.substr($cache_encode_key,2,2).'/';//緩存目錄
- $filename = $cache_dir.$cache_encode_key.".cache.php";//緩存文件名
- if(is_file($filename)) {//如果緩存文件存在,則返回false
- return false;
- } else {//如果緩存文件不存在,則生成一個新的緩存文件到緩存目錄
- $this->set($key, $data);
- }
- }
- public function del($key) {
- $cache_encode_key = $this->get_key($key);
- $cache_dir = $this->cache_dir.'/'.substr($cache_encode_key,0,2).'/'.substr($cache_encode_key,2,2).'/';//緩存目錄<span id="transmark"></span>
- $filename = $cache_dir.$cache_encode_key.".cache.php";//緩存文件名
- if(is_file($filename)) {//如果緩存文件存在則返回false<span id="transmark"></span>
- return false;
- } else {//如果緩存文件不存在,則刪除緩存文件
- @unlink($filename);
- }
- }
- public function get_key($key){
- return md5(CACHE_KEY.$key);//md5加密字符串
- }
- //第59題:redis使用案例
- //推送活動商品上線
- public function push_activity_goods_online($data) {
- $key = sprintf($this->config->item('activity_goods_push_key'), $data['goods_id']);
- $this->cache->redis->delete($key);
- $this->load->driver('cache', array('adapter' => 'redis'));
- return $this->cache->redis->hmset($key, $data);
- }
- //拉取上線活動商品
- public function pull_activity_goods_online($key) {
- $key = sprintf($this->config->item('activity_goods_push_key'), $key);
- $this->load->driver('cache', array('adapter' => 'redis'));
- return $this->cache->redis->hgetall($key);
- }
- //刪除上線的活動商品
- public function del_activity_goods_online($key) {
- $key = sprintf($this->config->item('activity_goods_push_key'), $key);
- $this->load->driver('cache', array('adapter' => 'redis'));
- return $this->cache->redis->delete($key);
- }
- //推送活動上線
- public function push_activity_online($data) {
- $activity_push_key = $this->config->item('activity_push_key');
- //非通用平臺作用哉活動,活動前綴+平臺作用域
- if (isset($data['plateform']) && ($data['plateform']) != 'all') {
- $activity_push_key = $data['plateform'] . ':' . $activity_push_key;
- }
- //訂單促銷
- if ($data['activity_range'] == 1) {
- $key = sprintf($activity_push_key, 'order');
- } else {
- $key = sprintf($activity_push_key, $data['activity_id']);
- }
- $this->cache->redis->delete($key);
- $this->load->driver('cache', array('adapter' => 'redis'));
- return $this->cache->redis->hmset($key, $data);
- }
- //拉取上線活動
- public function pull_activity_online($key) {
- if ($key == 'order') {
- $key = sprintf($this->config->item('activity_push_key'), 'order');
- }if ($key == 'mobile:order') {
- $key = "mobile:" . sprintf($this->config->item('activity_push_key'), 'order');
- } else {
- $key = sprintf($this->config->item('activity_push_key'), $key);
- }
- $this->load->driver('cache', array('adapter' => 'redis'));
- return $this->cache->redis->hgetall($key);
- }
- //刪除上線的活動
- public function del_activity_online($key, $activity = array()) {
- $activity_push_key = $this->config->item('activity_push_key');
- //非通用平臺作用哉活動,活動前綴+平臺作用域
- if (isset($activity['plateform']) && ($activity['plateform']) != 'all') {
- $activity_push_key = $activity['plateform'] . ':' . $activity_push_key;
- }
- $key = sprintf($activity_push_key, $key);
- $this->load->driver('cache', array('adapter' => 'redis'));
- //echo "redis->delete:" . $key . "\r\n<br>";
- return $this->cache->redis->delete($key);
- }
- //獲取全部活動
- public function pull_all_activity_online() {
- $aids = array();
- $key = "*" . sprintf($this->config->item('activity_push_key'), "*");
- $this->load->driver('cache', array('adapter' => 'redis'));
- $hashname = $this->cache->redis->keys($key);
- if (is_array($hashname)) {
- $prefix_key = str_replace("%s", '', $this->config->item('activity_push_key'));
- foreach ($hashname as $key => $value) {
- /* if ($value == ($prefix_key . "order")) {
- continue;
- } */
- $aid = str_replace($prefix_key, "", $value);
- $aids[] = $aid;
- }
- return $aids;
- } else {
- return null;
- }
- }
- //獲取所有活動商品
- public function pull_all_activity_goods_online() {
- $aids = array();
- $key = sprintf($this->config->item('activity_goods_push_key'), "*");
- $this->load->driver('cache', array('adapter' => 'redis'));
- $hashname = $this->cache->redis->keys($key);
- if (is_array($hashname)) {
- $prefix_key = str_replace("%s", '', $this->config->item('activity_goods_push_key'));
- foreach ($hashname as $key => $value) {
- $aid = str_replace($prefix_key, "", $value);
- $aids[] = $aid;
- }
- return $aids;
- } else {
- return null;
- }
- }
- //獲取線上活動商品by goods_id
- public function get_activity_goods_online($product_id) {
- if (empty($product_id)) {
- return false;
- }
- $activity_goods = $this->pull_activity_goods_online($product_id);
- if (!empty($activity_goods)) {
- return $activity_goods;
- }
- return false;
- }
- //第60題:php如何讀取php.ini配置文件中的配置選項的值
- echo ini_get('post_max_size');//獲取上傳文件的最大尺寸
- echo get_cfg_var('post_max_size');//獲取上傳文件的最大尺寸
- //第61題:php中如何動態的調用一個函數
- $name_list = '小強,張三,李四,王五,馬六';
- $funName = 'explode';//函數名當作字符串
- echo "<pre>";print_r($funName(',',$name_list));
- echo "<pre>";print_r(call_user_func_array($funName,array(',',$name_list)));
- /**
- * 結果:
- * Array(
- * [0] => 小強
- * [1] => 張三
- * [2] => 李四
- * [3] => 王五
- * [4] => 馬六
- * )
- *
- * Array(
- * [0] => 小強
- * [1] => 張三
- * [2] => 李四
- * [3] => 王五
- * [4] => 馬六
- * )
- */
- /**
- *第62題:__call是魔術方法
- * __call是魔術方法是指請求的方法不存在的時候採用的哪種處理方式;如果請求的方法名存在(跟參數列表無關),則不會調用此魔術方法
- */
- class MethodTest {
- /**
- * 再如:
- * public function __call($funName, $args){//參數1-要調用的方法名 參數2-傳遞給要調用方法的參數列表
- * switch (count($args)) {
- * case 0:
- * return $this->$funName();
- * case 1:
- * return $this->$funName($args[0]);
- * case 2:
- * return $this->$funName($args[0], $args[1]);
- * case 3:
- * return $this->$funName($args[0], $args[1], $args[2]);
- * case 4:
- * return $this->$funName($args[0], $args[1], $args[2], $args[3]);
- * case 5:
- * return $this->$funName($args[0], $args[1], $args[2], $args[3], $args[4]);
- * default:
- * return call_user_func_array($this->$funName, $args);
- * }
- * }
- */
- public function __call($name,$arguments) {//參數1-調用的方法名 參數2-傳遞給調用方法的參數列表
- if(method_exists($this,$name)){
- return $this->$name();
- }else{
- echo "調用的方法 $name() 不存在;傳遞給 $name() 方法的參數列表如下:".implode(',',$arguments)."\n";
- }
- }
- }
- $obj = new MethodTest();
- //結果:調用的方法 runTest() 不存在;傳遞給 runTest() 方法的參數列表如下:李四,張三
- $obj->runTest('李四','張三');//方法名、參數列表
- //第63題:php.ini配置文件的解析
- (1)如:配置文件 test.ini
- [names]
- me = Robert
- you = Peter
- [urls]
- first = "http://www.example.com"
- second = "http://www.w3school.com.cn"
- (2)代碼:<?php print_r(parse_ini_file("test.ini")); ?>
- 結果:
- Array(
- [me] => Robert
- [you] => Peter
- [first] => http://www.example.com
- [second] => http://www.w3school.com.cn
- )
- (3)代碼:<?php print_r(parse_ini_file("test.ini",true)); ?>
- 結果:
- Array(
- [names] => Array(
- [me] => Robert
- [you] => Peter
- )
- [urls] => Array(
- [first] => http://www.example.com
- [second] => http://www.w3school.com.cn
- )
- )
- <?php
- /**
- * 第65題:php中的重寫與重載
- * 首先來了解兩個概念:
- * 重寫/覆蓋: 指子類重寫了父類的同名方法,但重寫後的同名方法的參數個數及類型沒有限制 <span id="transmark"></span>發生在子類與父類之間
- * 重載: 指本類中存在多個同名方法,但參數類型/個數不同,當傳不同的參數時調用不同的方法 發生在本類內部
- * PHP中,不允許存在多個同名方法. 因此,不能夠完成java,c++中的這種重載;但是,PHP的靈活,可以模擬達到類似的效果
- */
- class human{
- public function say($name){
- echo $name,' 吃了嗎?<br />';
- }
- }
- class stu extends human{
- /*
- * 報錯:Fatal error: Cannot redeclare stu::say() in D:\wamp\www\php\61.php on line 28,因爲在PHP中,不允許存在多個同名方法,沒有重載概念這一說。
- * public function say($a,$b,$c){
- * echo '哥仨好';
- * }
- */
- public function say(){
- echo '切克鬧,卡貓百比<br />';
- }
- }
- $li=new stu();
- $li->say();//結果:切克鬧,卡貓百比;
- $li->say('binghui');//結果:切克鬧,卡貓百比;上面這個過程叫重寫
- //在PHP中模擬重載的方法
- class Calc {
- public function area() {
- //判斷一個調用area時,得到的參數個數
- $args = func_get_args();//獲取參數個數
- if(count($args) == 1) {
- return 3.14 * $args[0] * $args[0];
- } else if(count($args) == 2) {
- return $args[0] * $args[1];
- } else {
- return '未知圖形';
- }
- }
- }
- $calc = new Calc();
- //計算圓的頁面
- echo $calc->area(10),'<br />';
- //計算矩形的面積
- echo $calc->area(5,8);
- ?>
- <?php
- /**
- 第66題:static靜態局部變量(不是數組)在函數中的使用特點:
- (1)靜態局部變量不會隨着函數的調用和退出而發生變化;
- 不過,儘管該變量還繼續存在,但確不能在函數外部直接使用它(獲取不到值).
- 倘若再次調用定義它的函數時,它又可繼續使用,而且保存了前次被調用後留下的值.
- (2)靜態局部變量只會初始化一次.
- (3)靜態局部變量只能被初始化爲一個字符值或一個常量,不能使用表達式.
- 即使靜態局部變量定義時沒有賦初值,系統會自動賦初值0.
- (4)當多次調用一個函數且要求在調用之間保留某些變量的值時,可考慮採用靜態局部變量.
- (5)static $var=5;//【變量的賦值操作只會在變量第一次初始化時會被調用,在之後函數的執行過程中該操作不會被調用】
- (6)靜態變量是隻存在於函數作用域的變量,不過,在函數執行完成後,這種變量的值不會丟失,
- 也就是說,在下一次調用這個函數時,變量仍然會記得原來的值.
- 要將某個變量定義爲靜態的,只需要在變量前加上static關鍵字即可
- */
- function test(){
- static $var=5; //static $var = 1+1;就會報錯,不能使用表達式
- $var++;
- echo $var.'<br/>';
- }
- test(); //結果:6
- test(); //結果:7
- test(); //結果:8
- echo $var;//Notice:Undefined variable: var 即:不能在函數外部使用靜態局部變量,獲取不到值
- /**
- 類中的static靜態屬性和方法用什麼作用?
- (1)無論你實例化了多少個對象,static定義的屬性和方法,都只有一個,只佔有一次內存,節省了系統的內存開銷
- (2)訪問static屬性和方法時,只能用::訪問
- (3)靜態成員是一種類變量,可以把它看成時屬於整個類而不是屬於類的某個實例。
- 與一般的實例變量不同的是,靜態成員只保留一個變量值,而這個變量值對所有的實例都是有效的
- 也就是說,所有的實例共享這個成員
- (4)$this只表示類的當前實例,
- self::表示的是類本身,在類之外的代碼中不能使用這個操作符,而且它不能識別自己在繼承樹層次結構中的位置。
- 也就是說,在擴展類中使用self作用域時,self可以調用基類中聲明的方法,但它調用的總是已經在擴展類中重寫的方法。
- 與$this不同的是,在使用靜態變量時,必須在作用域限定符後面加上$符號
- 如:
- $this->name;//調用非靜態屬性
- self::$name;//調用靜態屬性
- (5)擴展類中,在基類的方法被重寫的情況下,使用 parent 作用域調用定義在基類中的方法。
- 靜態成員也可以只屬於父類。如果在子類和父類中同時聲明瞭某個成員,也可以使用parant::在子類中訪問父類中的變量。
- 在這種情況下,父類的靜態成員和子類的靜態成員保存的是不同的值
- (6)可以在::操作符的左邊寫上類的名稱來靜態地訪問某個成員,這樣避免創建類的實例.
- 不僅可以省略掉實例化類的代碼,而且還會更高效,因爲類的每個實例都會佔用一小部分的系統資源
- (7)案例:
- <?php
- class visitors{
- private static $visitors = 0;
- function __construct()
- {
- self::$visitors++;
- }
- static function getVisitors()
- {
- return self::$visitors;
- }
- }
- $visits = new visitors();
- echo visitors::getVisitors()."<br />";//結果:1
- $visits2 = new visitors();
- echo visitors::getVisitors()."<br />";//結果:2
- ?>
- 因爲$visitors字段聲明爲static,所以對其值的任何改變都會反映到所有實例化對象中。
- 還要注意,靜態字段和方法應使用self關鍵字和類名來引用,而不是通過this和箭頭操作符。
- 這是因爲使用“正常”方法引用靜態字段是不可能的,會導致語法錯誤。
- 不能在類中使用$this來引用爲static字段
- (8)靜態方法:
- 靜態方法和非靜態方法之間有一個重要的區別:在調用靜態方法時,不再需要擁有類的實例。
- 靜態方法和非靜態方法使用原則:
- (1)、是如果某個方法中不包含$this變量,就應該時靜態方法;
- (2)、如果不需要類的實例,可能還應該使用靜態類,這樣可以免去實例化類的工作。
- (3)、在靜態方法中時不能使用$this變量的,因爲靜態方法不屬於某個特定的實例。
- */
- ?>
第67題:session機制:
- <?php
- /**
- * 【session.save_handler = files】:默認的session處理機制
- * (1)session_start()是session機制的開始,它有一定概率開啓垃圾回收,因爲session是存放在文件中,PHP自身的垃圾回收是無效的,SESSION的回收是要刪文件的,這個概率是根據php.ini的配置決定的,
- 但是有的系統是 session.gc_probability = 0,這也就是說概率是0,而是通過cron腳本來實現垃圾回收
- session.gc_probability = 1 //垃圾回收機制
- session.gc_divisor = 1000 //垃圾回收機制
- session.gc_maxlifetime = 1440//過期時間 默認24分鐘
- //垃圾回收的機率爲:session.gc_probability/session.gc_divisor,即:1/1000,
- //不建議設置過小,因爲session的垃圾回收,是需要檢查每個文件是否過期的。
- session.save_path = //好像不同的系統默認不一樣,有一種設置是 "N;/path"
- //這是隨機分級存儲,這個樣的話,垃圾回收將不起作用,需要自己寫腳本
- * (2)session會判斷當前是否有$_COOKIE[session_name()];session_name()返回保存session_id的COOKIE鍵值;這個值可以從php.ini找到,session.name = PHPSESSID //默認值PHPSESSID
- * (3)如果不存在會生成一個session_id,然後把生成的session_id作爲COOKIE的值傳遞到客戶端;相當於執行了下面COOKIE 操作,注意的是,這一步執行了setcookie()操作,COOKIE是在header頭中發送的,
- * 這之前是不能有輸出的,PHP有另外一個函數 session_regenerate_id() 如果使用這個函數,這之前也是不能有輸出的
- setcookie(
- session_name(),//PHPSESSID,對應php.ini中session.name = PHPSESSID配置選項
- session_id(), //生成的session_id值
- session.cookie_lifetime,//默認0
- session.cookie_path,//默認'/'當前程序跟目錄下都有效
- session.cookie_domain,//默認爲空
- )
- * (4)如果存在session_id,那麼session_id = $_COOKIE[session_name];然後去session.save_path指定的文件夾裏去找名字爲'SESS_'. session_id()的文件,讀取文件的內容反序列化,然後放到$_SESSION中
- * (5)爲$_SESSION賦值:
- * 比如新添加一個值$_SESSION['test'] = 'blah';那麼這個$_SESSION只會維護在內存中,當腳本執行結束的時候,會把$_SESSION的值寫入到session_id指定的文件夾中,然後關閉相關資源
- 這個階段有可能執行更改session_id的操作,比如銷燬一箇舊的的session_id,生成一個全新的session_id.
- if (isset($_COOKIE[session_name()])) {//如:匿名用戶有一個SESSION的,當它登錄後需要換用新的session_id
- setcookie(session_name(), '', time() - 42000, '/');//舊session cookie過期
- }
- session_regenerate_id();//這一步會生成新的session_id,此時再通過session_id()返回的是新的值
- * (6)寫入SESSION:在腳本結束的時候會執行SESSION寫入操作,把$_SESSION中值寫入到session_id命名的文件中,可能已經存在,可能需要創建新的文件
- * (7)銷燬SESSION:SESSION發出去的COOKIE一般屬於即時COOKIE,保存在內存中,當瀏覽器關閉後,纔會過期,假如需要人爲強制過期,比如 退出登錄,而不是關閉瀏覽器,那麼就需要在代碼裏銷燬SESSION,方法有很多:
- setcookie(session_name(), session_id(), time() - 8000000, ..);//退出登錄前執行
- usset($_SESSION);//這會刪除所有的$_SESSION數據,刷新後,有COOKIE傳過來,但是沒有數據
- session_destroy();//這個作用更徹底,刪除$_SESSION 刪除session文件,和session_id
- *
- * 【session.save_handler = user】:用戶自定義session處理機制
- * (1)用戶自定義session處理機制:session_set_save_handler('open', 'close', 'read', 'write', 'destroy', 'gc');//【執行此函數將修改session默認的存儲介質;修改是隱式的,所以不會體現在php.ini配置文件中的session.save_handler配置項】
- session_start():
- 執行open($save_path, $session_name)打開session操作句柄,$save_path 在session.save_handler = files的情況下它就是session.save_path;但是如果用戶自定的話,這個兩個參數都用不上,直接返回TRUE
- 執行read($id)從中讀取數據.//【這個參數是自動傳遞的就是session_id()】,可以通過這個值進行操作
- (2)腳本執行結束:執行write($id, $sess_data) //兩個參數,很簡單
- (3)假如用戶需要session_destroy(),先執行destroy.在執行第2步
- (4)案例:
- <?php
- //SESSION初始化的時候調用
- function open($save_path, $session_name){
- global $sess_save_path;
- $sess_save_path = $save_path;
- return(true);
- }
- //關閉的時候調用
- function close(){
- return(true);
- }
- function read($id){//【參數會自動傳遞,就是session_id()】
- global $sess_save_path;
- $sess_file = "$sess_save_path/sess_$id";
- return (string) @file_get_contents($sess_file);
- }
- //腳本執行結束之前,執行寫入操作
- function write($id, $sess_data){//【參數會自動傳遞,就是session_id()】
- echo "sdfsf";
- global $sess_save_path;
- $sess_file = "$sess_save_path/sess_$id";
- if ($fp = @fopen($sess_file, "w")) {
- $return = fwrite($fp, $sess_data);
- fclose($fp);
- return $return;
- } else {
- return(false);
- }
- }
- function destroy($id){//【參數會自動傳遞,就是session_id()】
- global $sess_save_path;
- $sess_file = "$sess_save_path/sess_$id";
- return(@unlink($sess_file));
- }
- function gc($maxlifetime){
- global $sess_save_path;
- foreach (glob("$sess_save_path/sess_*") as $filename) {
- if (filemtime($filename) + $maxlifetime < time()) {
- @unlink($filename);
- }
- }
- return true;
- }
- ?>
- *
- */
- //【session.save_handler = user】:用戶自定義session處理機制
- $SESS_DBHOST = "127.0.0.1";
- $SESS_DBNAME = "cms";
- $SESS_DBUSER = "root";
- $SESS_DBPASS = "";
- $SESS_DBH = ""; //數據庫連接句柄
- $SESS_LIFE = get_cfg_var("session.gc_maxlifetime");//默認:8M
- //SESSION初始化的時候調用
- function sess_open($save_path, $session_name) {
- global $SESS_DBHOST, $SESS_DBNAME, $SESS_DBUSER, $SESS_DBPASS, $SESS_DBH;
- if (! $SESS_DBH = mysql_pconnect($SESS_DBHOST, $SESS_DBUSER, $SESS_DBPASS)) {
- echo "<li>Can't connect to $SESS_DBHOST as $SESS_DBUSER";
- echo "<li>MySQL Error: " . mysql_error();
- die;
- }
- if (! mysql_select_db($SESS_DBNAME, $SESS_DBH)) {
- echo "<li>Unable to select database $SESS_DBNAME";
- die;
- }
- return true;
- }
- //關閉的時候調用
- function sess_close() {
- return true;
- }
- function sess_read($key) {
- global $SESS_DBH, $SESS_LIFE;
- $qry = "SELECT value FROM session_tbl WHERE sesskey = '$key' AND expiry > " . time();
- $qid = mysql_query($qry, $SESS_DBH);
- if (list($value) = mysql_fetch_row($qid)) {
- return $value;
- }
- return false;
- }
- //腳本執行結束之前,執行寫入操作
- function sess_write($key, $val) { <span id="transmark"></span>
- global $SESS_DBH, $SESS_LIFE;
- $expiry = time() + $SESS_LIFE; //過期時間
- $value = addslashes($val);
- $qry = "INSERT INTO session_tbl VALUES ('$key', $expiry, '$value')";
- $qid = mysql_query($qry, $SESS_DBH);
- if (! $qid) {
- $qry = "UPDATE session_tbl SET expiry = $expiry, value = '$value' WHERE sesskey = '$key' AND expiry > " . time();
- $qid = mysql_query($qry, $SESS_DBH);
- }
- return $qid;
- }
- function sess_destroy($key) {
- global $SESS_DBH;
- $qry = "DELETE FROM session_tbl WHERE sesskey = '$key'";
- $qid = mysql_query($qry, $SESS_DBH);
- return $qid;
- }
- function sess_gc($maxlifetime) {
- global $SESS_DBH;
- $qry = "DELETE FROM session_tbl WHERE expiry < " . time();
- $qid = mysql_query($qry, $SESS_DBH);
- return mysql_affected_rows($SESS_DBH);
- }
- //【session.save_handler = user】:用戶自定義session處理機制主要是通過session_set_save_handler()來進行協調執行
- //【執行此函數將修改session默認的存儲介質;修改是隱式的,所以不會體現在php.ini配置文件中的session.save_handler配置項】
- session_set_save_handler(
- "sess_open", //可以進行重寫
- "sess_close", //可以進行重寫
- "sess_read", //可以進行重寫
- "sess_write", //可以進行重寫
- "sess_destroy", //可以進行重寫
- "sess_gc" //可以進行重寫
- );
- session_start(); //除了以上被重寫的session函數外,其它的session函數還是想以前一樣調用
- ?>
第68題:PHP 的垃圾回收機制:
- PHP垃圾回收機制是php5之後纔有的這<span id="transmark"></span>個東西,下面我來給大家介紹一下關於PHP垃圾回收機制一些理解,希望對各位同學有所幫助。
- php 5.3之前使用的垃圾回收機制是單純的“引用計數”,也就是每個內存對象都分配一個計數器,當內存對象被變量引用時,計數器 1;當變量引用撤掉後,計數器-1;當計數器=0時,表明內存對象沒有被使用,該內存對象則進行銷燬,垃圾回收完成。
- “引用計數”存在問題,就是當兩個或多個對象互相引用形成環狀後,內存對象的計數器則不會消減爲0;這時候,這一組內存對象已經沒用了,但是不能回收,從而導致內存泄露;
- php5.3開始,使用了新的垃圾回收機制,在引用計數基礎上,實現了一種複雜的算法,來檢測內存對象中引用環的存在,以避免內存泄露
第69題:將外網圖片本地化、將外網圖片下載到本地的原理
- <?php
- //將外網圖片本地化、將外網圖片下載到本地的原理
- copy("http://image.v1.cn/vodone/20150723/303862_0x0.jpg",'e:/wamp/www/303862_0x0.jpg');
- ?>
第70題:PHP緩存技術總結
- <?php
- /**
- 1、全頁面靜態化緩存
- 也就是將頁面全部生成html靜態頁面,用戶訪問時直接訪問的靜態頁面,而不會去走php服務器解析的流程。此種方式,在CMS系
- 統中比較常見,比如dedecms;
- 一種比較常用的實現方式是用輸出緩存:
- Ob_start()
- ******要運行的代碼*******
- $content = Ob_get_contents();
- ****將緩存內容寫入html文件*****
- Ob_end_clean();
- 2、頁面部分緩存
- 該種方式,是將一個頁面中不經常變的部分進行靜態緩存,而經常變化的塊不緩存,最後組裝在一起顯示;可以使用類似於
- ob_get_contents的方式實現,也可以利用類似ESI之類的頁面片段緩存策略,使其用來做動態頁面中相對靜態的片段部分的緩存
- (ESI技術,請baidu,此處不詳講)。該種方式可以用於如商城中的商品頁;
- 3、數據緩存
- 顧名思義,就是緩存數據的一種方式;比如,商城中的某個商品信息,當用商品id去請求時,就會得出包括店鋪信息、商品信息
- 等數據,此時就可以將這些數據緩存到一個php文件中,文件名包含商品id來建一個唯一標示;下一次有人想查看這個商品時,首
- 先就直接調這個文件裏面的信息,而不用再去數據庫查詢;其實緩存文件中緩存的就是一個php數組之類;
- Ecmall商城系統裏面就用了這種方式;
- 4、查詢緩存
- 其實這跟數據緩存是一個思路,就是根據查詢語句來緩存;將查詢得到的數據緩存在一個文件中,下次遇到相同的查詢時,就直
- 接先從這個文件裏面調數據,不會再去查數據庫;但此處的緩存文件名可能就需要以查詢語句爲基點來建立唯一標示(用md5($sql)???);
- 按時間變更進行緩存
- 其實,這一條不是真正的緩存方式;上面的2、3、4的緩存技術一般都用到了時間變更判斷;就是對於緩存文件您需要設一個有效
- 時間,在這個有效時間內,相同的訪問纔會先取緩存文件的內容,但是超過設定的緩存時間,就需要重新從數據庫中獲取數據,
- 並生產最新的緩存文件;
- 比如,我將我們商城的首頁就是設置2個小時更新一次;
- 5、按內容變更進行緩存
- 這個也並非獨立的緩存技術,需結合着用;就是當數據庫內容被修改時,即刻更新緩存文件;
- 比如,一個人流量很大的商城,商品很多,商品表必然比較大,這表的壓力也比較重;我們就可以對商品顯示頁進行頁面緩存;
- 當商家在後臺修改這個商品的信息時,點擊保存,我們同時就更新緩存文件;那麼,買家訪問這個商品信息時,實際上訪問的是
- 一個靜態頁面,而不需要再去訪問數據庫;
- 是想,如果對商品頁不緩存,那麼每次訪問一個商品就要去數據庫查一次,如果有10萬人在線瀏覽商品,那服務器壓力就大了;
- 6、內存式緩存
- 提到這個,可能大家想到的首先就是Memcached;memcached是高性能的分佈式內存緩存服務器。 一般的使用目的是,通過緩存數
- 據庫查詢結果,減少數據庫訪問次數,以提高動態Web應用的速度、 提高可擴展性。
- 它就是將需要緩存的信息,緩存到系統內存中,需要獲取信息時,直接到內存中取;比較常用的方式就是 key-->value方式;
- $memcachehost = '192.168.6.191';
- $memcacheport = 11211;
- $memcachelife = 60;
- $memcache = new Memcache;
- $memcache->connect($memcachehost,$memcacheport) or die ("Could not connect");
- $memcache->set('key','緩存的內容');
- $get = $memcache->get($key); //獲取信息
- 7、apache緩存模塊
- apache安裝完以後,是不允許被cache的。如果外接了cache或squid服務器要求進行web加速的話,就需要在htttpd.conf裏進行設
- 置,當然前提是在安裝apache的時候要激活mod_cache的模塊。
- 安裝apache時:./configure --enable-cache --enable-disk-cache --enable-mem-cache
- 8、php APC緩存擴展
- Php有一個APC緩存擴展,windows下面爲php_apc.dll,需要先加載這個模塊,然後是在php.ini裏面進行配置:
- [apc]
- extension=php_apc.dll
- apc.rfc1867 = on
- upload_max_filesize = 100M
- post_max_size = 100M
- apc.max_file_size = 200M
- upload_max_filesize = 1000M
- post_max_size = 1000M
- max_execution_time = 600 ; 每個PHP頁面運行的最大時間值(秒),默認30秒
- max_input_time = 600 ; 每個PHP頁面接收數據所需的最大時間,默認60
- memory_limit = 128M ; 每個PHP頁面所吃掉的最大內存,默認8M
- 9、Opcode緩存
- 我們知道,php的執行流程可以用下圖來展示:
- php的執行流程
- 首先php代碼被解析爲Tokens,然後再編譯爲Opcode碼,最後執行Opcode碼,返回結果;所以,對於相同的php文件,第一次運行
- 時可以緩存其Opcode碼,下次再執行這個頁面時,直接會去找到緩存下的opcode碼,直接執行最後一步,而不再需要中間的步驟了。
- 比較知名的是XCache、Turck MM Cache、PHP Accelerator等;
- **/
- ?>
第71題:xml文檔中的CDATA
- <?php
- /**
- *
- * xml文檔中的CDATA:
- *
- * 1、所有xml文檔中的文本均會被解析器解析,只有CDATA區段(CDATA section)中的文本會被解析器忽略
- * 2、術語CDATA指的是不應由xml解析器進行解析的文本數據(Unparsed Character Data)
- * 3、CDATA部分不能包含字符串 "]]>",也不允許嵌套的CDATA部分;標記CDATA 部分結尾的 "]]>" 不能包含空格或折行
- * 4、CDATA 部分由 "<![CDATA[" 開始,由 "]]>" 結束,CDATA 部分中的所有內容都會被解析器忽略
- * 5、在 XML 元素中,"<" 和 "&" 是非法的; "<" 會產生錯誤,因爲解析器會把該字符解釋爲新元素的開始;"&" 也會產生錯誤,因爲解析器會把該字符解釋爲字符實體的開始
- 案例:
- <document>
- <webName>優酷網</webName>
- <webSite>www.youku.com</webSite>
- <item id="1">...</item>
- <item id="2">...</item>
- <item id="3">
- <title>
- <![CDATA[ 唱說天下:銀幕上“不搭配”的情侶檔 ]]>
- </title>
- <category>
- <![CDATA[ 娛樂 ]]>
- </category>
- <subcat>
- <![CDATA[ 娛樂諮詢 ]]>
- </subcat>
- <image>
- <![CDATA[
- http://p01.youku.com/group2/M00/05/3D/ChQB0FW1udWAWwAHA16bTNZsaI03768-b.jpg
- ]]>
- </image>
- <link>
- <![CDATA[
- http://www.youku.com/player/youku/youku_player.swf?autoPlay=true&showAD=true&videoFrom=2345&videoUrl=http://f01.youku.com/group2/M00/05/3D/ChQB0FW1udWZs.flv
- ]]>
- </link>
- <duration>
- <![CDATA[ 00:02:27 ]]>
- </duration>
- <publish>
- <![CDATA[ 2015-07-27 12:56:17 ]]>
- </publish>
- <tag>
- <![CDATA[ 銀幕,情侶檔 ]]>
- </tag>
- <introduction>
- <![CDATA[ 唱說天下:銀幕上“不搭配”的情侶檔 ]]>
- </introduction>
- <count>
- <![CDATA[ 0 ]]>
- </count>
- </item>
- </document>
- *
- */
- ?>
第72題:如何列出目錄下的所有模板文件?遍歷文件夾、遍歷文件、遍歷目錄及子目錄、遍歷文件夾及子文件夾
- <?php
- /**
- * Array
- (
- [0] => E:/wamp/www/phpcms/phpcms/templates/default/content/category.html
- [1] => E:/wamp/www/phpcms/phpcms/templates/default/content/category_download.html
- [2] => E:/wamp/www/phpcms/phpcms/templates/default/content/category_picture.html
- [3] => E:/wamp/www/phpcms/phpcms/templates/default/content/category_video.html
- [4] => E:/wamp/www/phpcms/phpcms/templates/default/content/download.html
- [5] => E:/wamp/www/phpcms/phpcms/templates/default/content/footer.html
- [6] => E:/wamp/www/phpcms/phpcms/templates/default/content/header.html
- [7] => E:/wamp/www/phpcms/phpcms/templates/default/content/header_min.html
- [8] => E:/wamp/www/phpcms/phpcms/templates/default/content/header_page.html
- [9] => E:/wamp/www/phpcms/phpcms/templates/default/content/index.html
- [10] => E:/wamp/www/phpcms/phpcms/templates/default/content/list.html
- [11] => E:/wamp/www/phpcms/phpcms/templates/default/content/list_download.html
- [12] => E:/wamp/www/phpcms/phpcms/templates/default/content/list_picture.html
- [13] => E:/wamp/www/phpcms/phpcms/templates/default/content/list_video.html
- [14] => E:/wamp/www/phpcms/phpcms/templates/default/content/message.html
- [15] => E:/wamp/www/phpcms/phpcms/templates/default/content/page.html
- [16] => E:/wamp/www/phpcms/phpcms/templates/default/content/play_list.html
- [17] => E:/wamp/www/phpcms/phpcms/templates/default/content/rss.html
- [18] => E:/wamp/www/phpcms/phpcms/templates/default/content/search.html
- [19] => E:/wamp/www/phpcms/phpcms/templates/default/content/show.html
- [20] => E:/wamp/www/phpcms/phpcms/templates/default/content/show_download.html
- [21] => E:/wamp/www/phpcms/phpcms/templates/default/content/show_picture.html
- [22] => E:/wamp/www/phpcms/phpcms/templates/default/content/show_video.html
- [23] => E:/wamp/www/phpcms/phpcms/templates/default/content/show_videolist.html
- [24] => E:/wamp/www/phpcms/phpcms/templates/default/content/tag.html
- [25] => E:/wamp/www/phpcms/phpcms/templates/default/content/tag_list.html
- [26] => E:/wamp/www/phpcms/phpcms/templates/default/content/video_album.html
- [27] => E:/wamp/www/phpcms/phpcms/templates/default/content/video_for_ck.html
- )
- */
- echo "<pre>";
- print_r(glob('E:/wamp/www/phpcms/phpcms/templates/default/content/*.html'));
- //print_r(glob('E:/wamp/www/phpcms/phpcms/templates/default/content/video_*.html'));
- /**
- * Array
- (
- [0] => category.html
- [1] => category_download.html
- [2] => category_picture.html
- [3] => category_video.html
- [4] => download.html
- [5] => footer.html
- [6] => header.html
- [7] => header_min.html
- [8] => header_page.html
- [9] => index.html
- [10] => list.html
- [11] => list_download.html
- [12] => list_picture.html
- [13] => list_video.html
- [14] => message.html
- [15] => page.html
- [16] => play_list.html
- [17] => rss.html
- [18] => search.html
- [19] => show.html
- [20] => show_download.html
- [21] => show_picture.html
- [22] => show_video.html
- [23] => show_videolist.html
- [24] => tag.html
- [25] => tag_list.html
- [26] => video_album.html
- [27] => video_for_ck.html
- )
- */
- echo "<pre>";
- print_r(@array_map('basename',glob('E:/wamp/www/phpcms/phpcms/templates/default/content/*.html')));//array_map()回調函數
- //print_r(@array_map('basename',glob('E:/wamp/www/phpcms/phpcms/templates/default/content/video_*.html')));//array_map()回調函數
- ?>
第74題:遍歷函數:scandir()與glob()函數的區別
- <?php
- /**
- * scandir()與glob()函數的區別:
- *
- * 遍歷文件夾、遍歷目錄、遍歷子文件夾、遍歷子目錄、遍歷文件
- * 掃描單層文件夾的情況
- 1、scandir('E:/wamp/www/phpcms/');
- 案例:
- Array(
- [0] => .
- [1] => ..
- [2] => admin.php
- [3] => api
- [4] => api.php
- [5] => caches
- [6] => crossdomain.xml
- [7] => favicon.ico
- [8] => html
- [9] => index.html
- [10] => index.php
- [11] => js.html
- [12] => nbproject
- [13] => phpcms
- [14] => phpsso_server
- [15] => plugin.php
- [16] => robots.txt
- [17] => statics
- [18] => uploadfile
- )
- 2、glob('E:/wamp/www/phpcms/*');
- 案例:
- Array(
- [0] => E:/wamp/www/phpcms/admin.php
- [1] => E:/wamp/www/phpcms/api
- [2] => E:/wamp/www/phpcms/api.php
- [3] => E:/wamp/www/phpcms/caches
- [4] => E:/wamp/www/phpcms/crossdomain.xml
- [5] => E:/wamp/www/phpcms/favicon.ico
- [6] => E:/wamp/www/phpcms/html
- [7] => E:/wamp/www/phpcms/index.html
- [8] => E:/wamp/www/phpcms/index.php
- [9] => E:/wamp/www/phpcms/js.html
- [10] => E:/wamp/www/phpcms/nbproject
- [11] => E:/wamp/www/phpcms/phpcms
- [12] => E:/wamp/www/phpcms/phpsso_server
- [13] => E:/wamp/www/phpcms/plugin.php
- [14] => E:/wamp/www/phpcms/robots.txt
- [15] => E:/wamp/www/phpcms/statics
- [16] => E:/wamp/www/phpcms/uploadfile
- )
- */
- echo "<pre>";print_r(scandir('E:/wamp/www/phpcms/'));//跟glob相比多出來兩個元素,分別是: "." 和 ".."
- echo "<pre>";print_r(glob('E:/wamp/www/phpcms/*'));//以數組的形式返回與指定模式相匹配的文件名或目錄
- ?>
第75題:var_export()函數用法:
- <?php
- /**
- * 將字符串轉換爲數組
- *
- * @param string $data 字符串
- * @return array 返回數組格式,如果,data爲空,則返回空數組
- 結果:
- Array(
- [ishtml] => 1
- [template_list] => default
- [page_template] => page
- [meta_title] =>
- [meta_keywords] =>
- [meta_description] =>
- [category_ruleid] => 1
- [show_ruleid] =>
- [repeatchargedays] => 1
- )
- */
- function string2array($data) {
- if($data == '') return array();
- @eval("\$array = $data;");
- return $array;
- }
- $data='array (
- \'ishtml\' => \'1\',
- \'template_list\' => \'default\',
- \'page_template\' => \'page\',
- \'meta_title\' => \'\',
- \'meta_keywords\' => \'\',
- \'meta_description\' => \'\',
- \'category_ruleid\' => \'1\',
- \'show_ruleid\' => \'\',
- \'repeatchargedays\' => \'1\',
- )';
- echo "<pre>";print_r(string2array($data));
- $arr=array(
- 'username'=>'admin',
- 'password'=>'123'
- );
- /**
- * var_export()函數:返回字符串
- */
- $str=var_export($arr,true);//返回的是合法的php代碼,是一個字符串,不是數組
- /**
- * 結果:數組格式的字符串
- array (
- 'username' => 'admin',
- 'password' => '123',
- )
- */
- echo $str;//正確
- //echo $str['username'];//錯誤,因爲此時$str是一個數組格式的字符串,不是數組
- @eval("\$str = $str;");//將數組格式的字符串轉換爲數組
- print_r($str['username']);//結果:'admin',此時已將數組格式的字符串轉化爲數組
- ?>
51、php中如何統計一維數組中所有值出現的次數?返回一個數組,其元素的鍵名是原數組的值;鍵值是該值在原數組中出現的次數
52、php中如何統計字符串中每種字符的出現次數並排序?
53、php中使用str_word_count()函數計算字符串中的單詞數?
56、php中redis與memcached區別?
57、php中memcached的使用案例?
58、php中文件緩存的使用案例?
59、php中redis使用案例?
60、php如何讀取php.ini配置文件中的配置選項的值?
61、php中如何動態的調用一個函數?
62、php中__call魔術方法的使用
63、php中如何解析php.ini配置文件?
65、php中的重寫與重載的區別?
66、php中static靜態局部變量(不是數組)在函數中的使用
67、php中session的內部機制實現原理
68、php中的垃圾回收機制
69、php如何將外網圖片本地化或將外網圖片下載到本地的原理?
70、php中緩存技術總結
71、php中xml文檔的CDATA理解
72、php中如何列出目錄下的所有模板文件?遍歷文件夾、遍歷文件、遍歷目錄及子目錄、遍歷文件夾及子文件夾
74、php中遍歷函數:scandir()與glob()函數的區別?
75、php中通過var_export()函數返回數組格式的字符串