系列筆記:
Modern PHP 筆記(一):語言特性
Modern PHP 筆記(二):良好實踐
Modern PHP 筆記(三):部署測試和調優(yōu)
現(xiàn)在正式加入世界上最好的語言大家庭了。jimbochen大佬給推薦了 Josh Lockhart 寫的,安道翻譯的《Modern PHP》. 準備記錄下一些學習筆記却嗡。剛剛入坑伤锚,如果理解的不對,歡迎指出滚朵。
這本書剛看湾碎,覺得內容很扎實尸闸。對PHP的整個生態(tài)有了更深的理解觉增。強烈推薦讀一下兵拢。順便吐槽下,簡書的markdown不支持toc逾礁,這個蠻影響體驗说铃。
第一章:新時代的PHP
PHP正在重生,得益于命名空間嘹履、性狀腻扇、閉包和內置的操作碼緩存等有用的特性
現(xiàn)狀
跳出了框架的束縛,依賴composer
管理插件砾嫉,混搭合適的組件幼苛。
歷史
- 創(chuàng)始人:拉斯姆斯·勒多夫
- PHP tools:Personal Home Page Tools
- 1998年,PHP3: PHP: Hypertext Preprocessor
- PHP引擎: Zend Engine焕刮、HipHop Virtual Machine
- 基于PHP之上的語言:Hack
第二章:特性
命名空間
目的:避免命名沖突
使用命名空間
// 聲明命名空間
namespace Oreilly\ModernPHP;
// 廠商命名空間最重要舶沿,必須具有全局唯一性
// 導入類和別名
use Symfony\Component\HttpFoundation\Response as Res;
// 導入函數
use func Namespace\functionName;
// 導入常量
use constant Namespamce\CONST_NAME;
全局命名空間
<?php
namespace My\App;
class Foo
{
public function doSomething()
{
$exception = new Exception();
}
}
Exception
類沒有命名空間,在全局命名空間中配并,此時調用\My\App\Foo::doSomething()
會
報錯括荡。
正確寫法為:new \Exception()
使用接口
接口是兩個PHP對象之間的契約,其目的不是讓一個對象依賴另一個對象的身份溉旋,而是依賴另一個
對象的能力畸冲。我們不關心第三方代碼如何實現(xiàn)接口,只關心是否實現(xiàn)了指定接口观腊。
// 操作的入參Documentale不是類邑闲,是接口
class DocumentStore
{
public function addDocument(Documentable $document)
{
...
$document->getId();
$document->getContent();
}
}
// 接口定義
interface Documentable
{
public function getId();
public function getContent();
}
// 類1實現(xiàn)了接口
class HtmlDocument implements Documentable
{
public function getId()
{
// ...
}
public function getContent()
{
// ...
}
}
// 類2實現(xiàn)了接口
class StreamDocument implements Documentable
{
public function getId()
{
// ...
}
public function getContent()
{
// ...
}
}
性狀trait
性狀有兩個作用:表明類可以做什么(像接口),提供模塊化實現(xiàn)(像類)
為什么使用性狀
繼承模型不好用時梧油,比如想讓兩個無關的PHP類具有類似的行為监憎?(e.g.零售店類和汽車類都想使用
地理編碼轉換成經緯度功能時)
- 方案一:繼承共同父類∩羲荩——不好鲸阔。讓兩個無關類繼承自同一祖先。
- 方案二:創(chuàng)建地理轉換接口迄委『稚福——好一點。但是兩個類都需要實現(xiàn)相同的代碼叙身,不符合DRY原則
- 方案三:使用性狀渔扎,直接在兩個類中混入性狀——最好
創(chuàng)建性狀
<?php
trait MyTrait {
// 這里寫性狀實現(xiàn)
}
使用性狀
class MyClass
{
use MyTrait;
// 類其他實現(xiàn)
}
PHP會直接把性狀代碼粘貼在類中信轿,因此要注意兼容問題晃痴。
生成器generator
生成器是簡單的迭代器残吩。不同的是,不要求類實現(xiàn)Iterator接口倘核,每次只計算下一個值泣侮,不會在內存
中預先計算。提升性能紧唱。
創(chuàng)建生成器函數
是的活尊,生成器是使用了
yield
關鍵字的函數。只產出值漏益,不返回值蛹锰。
返回一個屬于
Generator
類的對象,可以用foreach()
迭代绰疤。-
生成器每產生一個值內部狀態(tài)就會停頓铜犬,然后恢復,停頓...
function myGenerator() { yield 'value1'; yield 'value2'; }
使用生成器
常用于需要節(jié)省內存時轻庆,比如生成一個大范圍的數癣猾、處理很多行的csv
文件等。
foreach (myGenerator() as $yieldValue) {
echo $yieldValue, PHP_EOL;
}
閉包
- 閉包是創(chuàng)建時封閉周圍狀態(tài)的函數榨了。即便閉包所在環(huán)境不存在了煎谍,閉包中封裝的狀態(tài)依舊存在。
- 匿名函數時沒有名稱的函數龙屉,非常適合作為函數或方法的回調呐粘。
PHP中將閉包和匿名函數視為相同概念。
創(chuàng)建閉包
與函數語法相同转捕,但實際上閉包是Closure
類的實例作岖,不是函數。
附加狀態(tài)
必須調用閉包對象的bindTo()
方法或者使用use
關鍵字五芝,將狀態(tài)附加到PHP閉包上痘儡。
$que = function ($query)use ($id) {
// $id是外面變量
}
bindTo()
方法將閉包實例的內部狀態(tài)綁定到其他對象上,則閉包可以訪問綁定閉包的對象中受保護方法和私有成員變量枢步。
e.g.沉删,PHP框架經常使用bindTo()
方法把路由URL映射到匿名函數。因此可以在匿
名函數中使用$this
引用應用對象醉途。
Zend OPcache 字節(jié)碼緩存
PHP是解釋型語言矾瑰,PHP解釋器執(zhí)行PHP腳本時會解析代碼,將其編譯成 Zend 操作碼隘擎,然后執(zhí)行
字節(jié)碼殴穴。每次HTTP請求都會不斷解析、編譯、執(zhí)行采幌。緩存字節(jié)碼可以節(jié)省時間劲够,提高性能。
Zend OPcache 默認不啟用休傍,需要手動開啟并配置征绎。
內置HTTP服務器
從PHP 5.4 開始
啟動內置服務器
// 根目錄
php -S localhost:4000
自定義配置
php -S localhost:8000 -c app/config/php.ini
路由器腳本
內置的服務器不支持.htaccess
文件,因此很難使用前端控制器尊残。
前端控制器是一個PHP文件炒瘸,用于轉發(fā)所有的HTTP請求(通過.htaccess文件或者重寫規(guī)則實現(xiàn))淤堵。
前端控制器的職責是寝衫,分發(fā)請求,以及調度適當的PHP代碼拐邪。
內置服務器使用路由腳本彌補這個功能慰毅。處理HTTP請求前,先執(zhí)行路由器腳本扎阶,如果為false汹胃,則
返回請求的靜態(tài)資源URI,否則返回腳本的執(zhí)行結果东臀。
php -S localhost:8000 router.php
判斷使用哪種服務器
if (php_sapi_name() === 'cli-server'){
// PHP 內置的服務器
} else {
// 其他 Web 服務器
}
缺點
不能用在生產環(huán)境:
- 一次只能處理一個請求
- 只支持少量媒體類型
- 通過路由器腳本支持少量URL重寫規(guī)則着饥,更高級不行
更多筆記還在讀書中O(∩_∩)O哈哈~
最后,照例記錄下一段很喜歡的話共勉惰赋。
過一個平凡無趣的人生實在太容易了宰掉,你可以不讀書,不冒險赁濒,不運動轨奄,不寫作,不外出拒炎,不折騰……但是挪拟,人生最后悔的事情就是:我本可以。 ——陳素封