摘要:作者上一篇提到了類的自動(dòng)加載和,今天就來(lái)逐一說(shuō)說(shuō)。為這個(gè)問(wèn)題提供了一個(gè)解決方案,這就是類的自動(dòng)裝載機(jī)制。為了方便使用自定義的全局,把方法也重寫了。
作者:Terry Gao
上一篇提到了類的自動(dòng)加載和Session,今天就來(lái)逐一說(shuō)說(shuō)。
1. 類的自動(dòng)加載在使用PHP的OO模式開發(fā)系統(tǒng)時(shí),通常大家習(xí)慣將每個(gè)類的實(shí)現(xiàn)都存放在一個(gè)多帶帶的文件里,這樣會(huì)很容易實(shí)現(xiàn)對(duì)類進(jìn)行復(fù)用,同時(shí)將來(lái)維護(hù)時(shí)也很便利,這也是OO設(shè)計(jì)的基本思想之一。如果需要使用一個(gè)類,只需要直接使用include/require將其包含進(jìn)來(lái)即可。但隨著項(xiàng)目規(guī)模的不斷擴(kuò)大,使用這種方式會(huì)帶來(lái)一些隱含的問(wèn)題:如果一個(gè)PHP文件需要使用很多其它類,那么就需要很多的require/include語(yǔ)句,這樣有可能會(huì)造成遺漏或者包含進(jìn)不必要的類文件。如果大量的文件都需要使用其它的類,那么要保證每個(gè)文件都包含正確的類文件肯定是一個(gè)噩夢(mèng)。
PHP5為這個(gè)問(wèn)題提供了一個(gè)解決方案,這就是類的自動(dòng)裝載(autoload)機(jī)制。
/* NovaFrameworkAutoloader.php */ import()注冊(cè)到sql_autoload,作為本項(xiàng)目中類的自動(dòng)加載方法 spl_autoload_register(array( $this, "import" )); } /** * Autoloader的入口函數(shù) * 用于創(chuàng)建Autoloader的唯一實(shí)例化對(duì)象 * * @return Autoloader */ public static function init() { if (self::$loader == NULL) self::$loader = new self(); return self::$loader; } /** * 類的自動(dòng)加載方法 * 根據(jù)傳入?yún)?shù)$className,自動(dòng)引入相應(yīng)類的源文件 * * @param string $className */ public function import($className) { $path = explode("", substr($className, strlen("Nova"))); $filePath = ROOT_DIR . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $path) . ".php"; if (is_file($filePath)) { require $filePath; } } }
這個(gè)自動(dòng)加載類比較簡(jiǎn)單,初始化后,只有一個(gè)主要的方法import(),它通過(guò)解析傳入進(jìn)來(lái)的類名(由于我們使用了命名空間,所以類名基本上都是“NovaFrameworkAutoloader這樣的形式”),從項(xiàng)目根目錄開始,按照類名本身指定的路徑來(lái)定位相應(yīng)類的源碼文件,如果存在該文件,則將其引入。
2. Session更多關(guān)于自動(dòng)加載類的機(jī)制和原理,可以參考PHP autoload原理
默認(rèn)情況下,PHP是將session以文件的形式存在服務(wù)器上,具體可以在php.ini中配置。但是實(shí)際生產(chǎn)環(huán)境中,稍大些的站點(diǎn)都不會(huì)采用這種形式,一般都會(huì)借助sql數(shù)據(jù)庫(kù)、或者nosql類型的如memcached、redis等緩存服務(wù)器來(lái)存儲(chǔ)session,這樣做可以有效緩解PHP服務(wù)器的壓力和處理速度,提高并發(fā)能力。
在Nova中我們使用redis服務(wù)器來(lái)存取Session。
/* NovaFrameworkSession.php get(self::$sessionId, SESSION_TABLE_NAME); if ($sessionValue) { $_SESSION = $sessionValue; } return true; } /** * 將Session變量的內(nèi)容寫入Redis中 * * @return bool */ public static function write() { if (!empty($_SESSION)) { self::$redisCache->set(self::$sessionId, $_SESSION, SESSION_TABLE_NAME, SESSION_TIMEOUT); } return true; } /** * 通過(guò)刪除Redis中SessionId對(duì)應(yīng)的數(shù)據(jù)來(lái)注銷Session * session_destory()是自動(dòng)調(diào)用 * * @return bool */ public static function destory() { if (self::$redisCache->exists(self::$sessionId, SESSION_TABLE_NAME)) { self::$redisCache->delete(self::$sessionId, SESSION_TABLE_NAME); } setcookie(SESSION_NAME, self::$sessionId, 1, COOKIE_PATH, COOKIE_DOMAIN, FALSE); return true; } public static function close() { return true; } public static function gc() { return true; } /** * 返回一個(gè)SessionId * 若Cookie中已存在SessionId,則直接返回該SessionId * 若不存在,則按照規(guī)則新生成一個(gè)SessionId * * @return string Session Id */ public static function get_sid() { self::$userIp = Tools::real_ip(); $arr = $_COOKIE; //判斷Cookie中是否已經(jīng)存在SessionId if (is_null(self::$sessionId) && empty($arr[SESSION_NAME])) { //使用MD5對(duì)用戶IP+隨機(jī)字符串加密后作為新的SessionId self::$sessionId = function_exists("com_create_guid") ? md5(self::$userIp . com_create_guid()) : md5(self::$userIp . uniqid(mt_rand(), true)); //對(duì)新的SessionId再做一次crc32運(yùn)算,作為最終的SessionId self::$sessionId .= sprintf("%08x", crc32(self::$sessionId)); //將SessionId寫入Cookie中 setcookie(SESSION_NAME, self::$sessionId, time() + SESSION_TIMEOUT, COOKIE_PATH, COOKIE_DOMAIN, FALSE); $_COOKIE[SESSION_NAME] = self::$sessionId; } else { self::$sessionId = $arr[SESSION_NAME]; } //返回SessionId return self::$sessionId; } }
Nova基本上重寫了Session的一些核心處理函數(shù)。為了方便使用自定義的全局Redis Rootkey,Nova把Redis方法也重寫了。
_redis = new Redis(); $this->_redis->connect(REDIS_HOST, REDIS_PORT); } public static function get_instance($redisKey = REDIS_ROOT) { if (!(self::$_instanceObj[$redisKey] instanceof self)) { self::$_instanceObj[$redisKey] = new self; } self::$_instanceObj[$redisKey]->redisKey = $redisKey; return self::$_instanceObj[$redisKey]; } public function set_group($groupName = "") { if (empty($groupName)) { return FLASE; } $this->groupName = $groupName; $this->groupPath = implode(":", explode("/", $groupName)) . ":"; return TRUE; } public function set($key, $data, $groupName = "", $timeout = SESSION_TIMEOUT) { if (empty($groupName)) { $groupName = $this->groupName . $this->tempName; } else { $groupName = $this->groupName . $groupName; } if (is_array($data)) { $data = json_encode($data); } $redisKey = $groupName . $key; return $this->_redis->setex($redisKey, $timeout, $data); } public function get($key, $groupName = "") { if (empty($groupName)) { $groupName = $this->groupName . $this->tempName; } else { $groupName = $this->groupName . $groupName; } $redisKey = $groupName . $key; $return = ""; $temp = $this->_redis->get($redisKey); $return = json_decode($temp, 1); return empty($return) ? $temp : $return; } public function delete($key, $groupName = "") { if (empty($groupName)) { $groupName = $this->groupName . $this->tempName; } else { $groupName = $this->groupName . $groupName; } $redisKey = $groupName . $key; return $this->_redis->delete($redisKey); } public function exists($key, $groupName = "") { if (empty($groupName)) { $groupName = $this->groupName . $this->tempName; } else { $groupName = $this->groupName . $groupName; } $redisKey = $groupName . $key; return $this->_redis->exists($redisKey); } }
你可以在Github上查看Nova項(xiàng)目的源代碼。
如果你有任何問(wèn)題或建議,可以掃描下方二維碼或者微信搜索[phpjiagoushier],關(guān)注我的微信公眾號(hào)[PHP架構(gòu)],與我交流互動(dòng)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/22554.html
摘要:作者作為的入門進(jìn)階,自己動(dòng)手寫一個(gè)框架可以從各方面鞏固和加深你對(duì)的理解,還能了解一些架構(gòu)方面的基礎(chǔ)知識(shí)。它將程序劃分為三層。最上面的一層,是直接面向最終用戶的視圖層。最底下的一層,是核心的模型層,負(fù)責(zé)檢索組織和處理程序所需的數(shù)據(jù)或信息。 作者:Terry Gao 作為PHP Coder的入門進(jìn)階,自己動(dòng)手寫一個(gè)MVC框架可以從各方面鞏固和加深你對(duì)PHP的理解,還能了解一些架構(gòu)方面的基礎(chǔ)...
摘要:假設(shè)我們站點(diǎn)的域名是,用戶請(qǐng)求地址。模型層我們可以將數(shù)據(jù)組織和處理邏輯放在模型層,這里封裝了數(shù)據(jù)庫(kù)操作,甚至有些大型的框架會(huì)在這一層對(duì)這個(gè)數(shù)據(jù)庫(kù)進(jìn)行對(duì)象化,目的都是為了組織和處理數(shù)據(jù),然后將處理好的數(shù)據(jù)返回給控制器層。 作者:Terry Gao 1. 控制器 第一篇我們聊到路由分發(fā)會(huì)把用戶請(qǐng)求按照規(guī)則分發(fā)到控制器層的不同類,而默認(rèn)的規(guī)則中,請(qǐng)求會(huì)下發(fā)到控制器的index類的main方法...
摘要:服務(wù)器通過(guò)協(xié)議與客戶端通信,因此也被稱為服務(wù)器。本文標(biāo)題為從零開始搭建論壇一服務(wù)器與框架本文鏈接為更多閱讀自己動(dòng)手開發(fā)網(wǎng)絡(luò)服務(wù)器一自己動(dòng)手開發(fā)網(wǎng)絡(luò)服務(wù)器二自己動(dòng)手開發(fā)網(wǎng)絡(luò)服務(wù)器三服務(wù)器網(wǎng)關(guān)接口實(shí)現(xiàn)原理分析最佳實(shí)踐指南應(yīng)用淺談框架編程簡(jiǎn)介 之前用 Django 做過(guò)一個(gè)小的站點(diǎn),感覺(jué)Django太過(guò)笨重,于是就準(zhǔn)備換一個(gè)比較輕量級(jí)的 Web 框架來(lái)玩玩。Web.py 作者已經(jīng)掛掉,項(xiàng)目好...
摘要:因?yàn)楣ぷ髦幸恢痹谑褂?,也一直以?lái)想總結(jié)一下自己關(guān)于的一些知識(shí)經(jīng)驗(yàn)。于是把一些想法慢慢整理書寫下來(lái),做成一本開源免費(fèi)專業(yè)簡(jiǎn)單的入門級(jí)別的小書,提供給社區(qū)。本書的后續(xù)可能會(huì)做成視頻版本,敬請(qǐng)期待。本作品采用署名禁止演繹國(guó)際許可協(xié)議進(jìn)行許可 React.js 小書 本文作者:胡子大哈本文原文:React.js 小書 轉(zhuǎn)載請(qǐng)注明出處,保留原文鏈接以及作者信息 在線閱讀:http://huzi...
閱讀 2520·2023-04-25 17:37
閱讀 1203·2021-11-24 10:29
閱讀 3709·2021-09-09 11:57
閱讀 704·2021-08-10 09:41
閱讀 2256·2019-08-30 15:55
閱讀 2822·2019-08-30 15:54
閱讀 1951·2019-08-30 15:53
閱讀 906·2019-08-30 15:43