PHP簡(jiǎn)單入門

1.PHP內(nèi)核Zend

PHP由內(nèi)核Zend引擎和擴(kuò)展層組成,PHP內(nèi)核負(fù)責(zé)處理請(qǐng)求、完成文件流錯(cuò)誤處理等操作,Zend引擎可以將PHP程序文件轉(zhuǎn)換成可在虛擬機(jī)上運(yùn)行的機(jī)器語(yǔ)言,擴(kuò)展層提供一些應(yīng)用層操作需要的函數(shù)類庫(kù)等,比如數(shù)組和MySQL數(shù)據(jù)庫(kù)的操作等。

Zend引擎是用C語(yǔ)言實(shí)現(xiàn)的,將PHP代碼通過(guò)詞法語(yǔ)法解析成可執(zhí)行的opcode并實(shí)現(xiàn)相應(yīng)的處理方法、基本的數(shù)據(jù)結(jié)構(gòu)內(nèi)存分配和管理等,對(duì)外提供相應(yīng)的可供調(diào)用的API方法。Zend引擎是PHP的核心,所有的外圍功能都是圍繞它實(shí)現(xiàn)的。擴(kuò)展層通過(guò)組件的方式提供各種基礎(chǔ)服務(wù)、內(nèi)置函數(shù),標(biāo)準(zhǔn)庫(kù)都是通過(guò)它實(shí)現(xiàn)的。用戶也可以編寫(xiě)自己的擴(kuò)展來(lái)實(shí)現(xiàn)特定的需求。服務(wù)端應(yīng)用編程接口(Server Application Programming Interface, SAPI),通過(guò)一系列鉤子函數(shù)使得PHP可以和外圍交互數(shù)據(jù)。我們平時(shí)編寫(xiě)的PHP程序就是通過(guò)不同的SAPI方式得到不同的應(yīng)用模式,如通過(guò)WebServer實(shí)現(xiàn)的Web應(yīng)用和在命令行下運(yùn)行的腳本等。一段PHP程序被執(zhí)行的時(shí)候會(huì)先被解析成opcode指令,然后在虛擬機(jī)中按順序執(zhí)行,由于PHP本身是用C語(yǔ)言開(kāi)發(fā)的,所以其在執(zhí)行的時(shí)候調(diào)用的都是C的函數(shù)。opcode是PHP程序執(zhí)行的最基本單位。

HashTable是Zend的核心數(shù)據(jù)結(jié)構(gòu),實(shí)現(xiàn)了PHP里幾乎所有的功能,支持key->value查詢,添加刪除的復(fù)雜度是O(1),支持線性遍歷和混合類型。在HashTable中既有key->value形式的散列結(jié)構(gòu),也有雙向鏈表模式,使得它能夠非常方便地支持快速查找和線性遍歷。Zend的散列結(jié)構(gòu)是典型的hash表模型,通過(guò)鏈表的方式來(lái)解決沖突。Zend的HashTable是一個(gè)自增長(zhǎng)的數(shù)據(jù)結(jié)構(gòu),當(dāng)hash表數(shù)目滿了之后,其本身會(huì)動(dòng)態(tài)地以2倍的方式擴(kuò)容并重新布置元素位置,初始大小均為8。另外,在進(jìn)行key->value快速查找的時(shí)候,Zend本身還做了一些優(yōu)化,通過(guò)空間換時(shí)間的方式加快速度。比如在每個(gè)元素中都會(huì)用一個(gè)變量nKeyLength標(biāo)識(shí)key的長(zhǎng)度以做快速判定。Zend HashTable通過(guò)一個(gè)鏈表結(jié)構(gòu)實(shí)現(xiàn)了元素的線性遍歷。理論上,做遍歷使用單向鏈表就夠了,使用雙向鏈表的主要目的是為了快速刪除鏈表元素,避免遍歷。PHP是一門弱類型語(yǔ)言,本身不嚴(yán)格區(qū)分變量的類型。PHP在聲明變量的時(shí)候不需要指定類型。PHP在程序運(yùn)行期間可能進(jìn)行變量類型的隱式轉(zhuǎn)換。和其他強(qiáng)類型語(yǔ)言一樣,程序中也可以進(jìn)行顯式的類型轉(zhuǎn)換。Zval是Zend中另一個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu),用來(lái)標(biāo)識(shí)并實(shí)現(xiàn)PHP變量。

2.php核心數(shù)據(jù)結(jié)構(gòu)

Zval主要由以下3部分組成。

  • Type指定了變量所述的類型(整數(shù)、字符串、數(shù)組等)。
  • refcount&is_ref用來(lái)實(shí)現(xiàn)引用計(jì)數(shù)。
  • value是核心部分,存儲(chǔ)了變量的實(shí)際數(shù)據(jù)。

Zval用來(lái)保存一個(gè)變量的實(shí)際數(shù)據(jù)。因?yàn)橐鎯?chǔ)多種類型,所以zval是一個(gè)union,也由此實(shí)現(xiàn)了弱類型。引用計(jì)數(shù)在內(nèi)存回收、字符串操作等地方使用得非常廣泛。PHP中的變量就是引用計(jì)數(shù)的典型應(yīng)用。Zval的引用計(jì)數(shù)通過(guò)成員變量is_ref和ref_count實(shí)現(xiàn)。通過(guò)引用計(jì)數(shù),多個(gè)變量可以共享同一份數(shù)據(jù),避免頻繁復(fù)制帶來(lái)的大量消耗。

在進(jìn)行賦值操作時(shí),Zend將變量指向相同的Zval,同時(shí)ref_count++,在unset操作時(shí),對(duì)應(yīng)的ref_count-1。只有ref_count為0時(shí)才會(huì)真正執(zhí)行銷毀操作。如果是引用賦值,Zend就會(huì)修改is_ref為1。PHP變量通過(guò)引用計(jì)數(shù)實(shí)現(xiàn)變量共享數(shù)據(jù),當(dāng)試圖寫(xiě)入一個(gè)變量時(shí),Zend若發(fā)現(xiàn)該變量指向的Zval被多個(gè)變量共享,則為其復(fù)制一份ref_count為1的Zval,并遞減原Zval的refcount,這個(gè)過(guò)程稱為“Zval分離”??梢?jiàn),只有在有寫(xiě)操作發(fā)生時(shí),Zend才進(jìn)行復(fù)制操作,因此也叫copy-on-write(寫(xiě)時(shí)復(fù)制)。對(duì)于引用型變量,其要求和非引用型相反,引用賦值的變量間必須是捆綁的,修改一個(gè)變量就修改了所有捆綁變量。

3.php7的新特性

相較于以前的版本,PHP 7在語(yǔ)言語(yǔ)法層面和底層架構(gòu)層面都有一些改進(jìn)。在語(yǔ)法層面的改進(jìn)主要是增加了一些新特性、移除了一些擴(kuò)展、改變了錯(cuò)誤異常處理等。在底層結(jié)構(gòu)方面,改變了存儲(chǔ)各種變量的Zval和Zend_String結(jié)構(gòu)體、優(yōu)化了Zend Array的HashTable、改進(jìn)了函數(shù)的調(diào)用機(jī)制等。這些底層結(jié)構(gòu)的改進(jìn)大幅提升了PHP的執(zhí)行效率,使得其執(zhí)行速度比PHP 5高出一倍左右。PHP是一個(gè)弱類型的語(yǔ)言,不過(guò)在PHP 7中支持變量類型的定義,引入了一個(gè)開(kāi)關(guān)指令declare(strict_type=1);。這個(gè)指令一旦開(kāi)啟,就會(huì)強(qiáng)制當(dāng)前文件下的程序遵循嚴(yán)格的函數(shù)傳參類型和返回類型。不開(kāi)啟strict_type, PHP將會(huì)嘗試轉(zhuǎn)換成要求的類型;開(kāi)啟之后,PHP不再做類型轉(zhuǎn)換,類型不匹配就會(huì)拋出錯(cuò)誤。要使用嚴(yán)格模式,一個(gè)declare聲明指令必須放在文件的頂部。這意味著嚴(yán)格聲明標(biāo)量是基于文件可配的。這個(gè)指令不僅影響參數(shù)的類型聲明,還影響函數(shù)的返回值聲明。

PHP 7中的新特性主要有以下幾點(diǎn):

  • (1)標(biāo)量類型聲明。
  • (2)函數(shù)返回值類型聲明。
  • (3)新增null合并運(yùn)算符。
  • (4)新增組合比較符。
  • (5)支持通過(guò)define()定義常量數(shù)組。
  • (6)新增支持匿名類。
  • (7)支持Unicode codepoint轉(zhuǎn)譯語(yǔ)法。
  • (8)更好的閉包支持。
  • (9)為unserialize()提供過(guò)濾。
  • (10)新增加IntlChar類。
  • (11)支持use語(yǔ)句從同一namespace導(dǎo)入類、函數(shù)和常量。
  • (12)新增整除函數(shù)intdiv()。
  • (13)session_start()支持接收數(shù)組參數(shù)。

4.php數(shù)據(jù)類型

數(shù)據(jù)類型是指對(duì)數(shù)據(jù)的抽象描述,比如“整型數(shù)據(jù)”就是對(duì)所有整數(shù)數(shù)字的抽象。PHP的數(shù)據(jù)類型包括String(字符串)、Integer(整型)、Float(浮點(diǎn)型)、Boolean(布爾型)、Array(數(shù)組)、Object(對(duì)象)、NULL(空值)7種,本節(jié)介紹這些數(shù)據(jù)類型的定義和使用。

  • 字符串
$str  = "hello  world";
eche $str;
  • 整型
$num = 10;
  • 浮點(diǎn)型
$price = 1.0
  • Boolean
$isFlag = true;
  • array
$arr = array("hello","world"=>array("php","is","the","best"))
  • object
class Hello {
  var $str;
  
  function get_str() {
    return $this->str;
  }

  function set_str($str = "hello world") {
    $this->str = str;
  }
}
  • 常量
    可以用define定義,也可以用const定義(php7)
    可以是標(biāo)量和資源。
define ("Foo", "bar");
const Version = "1.0.0";

自定義常量盡量不要用下劃線__Name__,一般留給內(nèi)置的預(yù)定義常量

  • 預(yù)定義常量
__LINE__ 行號(hào)
__FILE__ 文件路徑和文件名
__DIR__ 文件所在的目錄
__FUNCTION__ 函數(shù)名
__CLASS__ 類名
__TRAIT__ trait的名字
__METHOD__類的方法名
__NAMESPACE__ 命名空間名

4.php流程控制

  • if else
if ($a < $b) {
  return $a;
} else if ($a == $b) {
  return $b;
} else {
  return $b;
}
  • switch
switch  ($num1) {
  case $num1 == "hello":
    echo $num1;
    break;
  case $num1  ==  "world":
    echo $num1;
    break;
  default:
    echo  "hello world";
    break;
}
  • while
while ($num < 10)  {
  echo $num;
  -$num;
}
  • do while
do {
  echo $num;
}  while  ($num <  10);
  • for
for  ($num = 0; $num < 100;  $num++)  {
  echo $num;
}
  • foreach
foreach ($num_array as $num) {
  echo $num;
}

foreach($num_array as $key =>  $value)  {
  echo $key;
  echo $value;
}

在PHP 5版本中,當(dāng)foreach開(kāi)始循環(huán)執(zhí)行時(shí),每次數(shù)組內(nèi)部指針都會(huì)自動(dòng)向后移動(dòng)一個(gè)單元,但是在PHP 7中卻不是這樣

在PHP 7中,按照值進(jìn)行循環(huán)時(shí),foreach是對(duì)數(shù)組的復(fù)制操作,在循環(huán)過(guò)程中對(duì)數(shù)組的修改不會(huì)影響循環(huán)行為,但在PHP 5中卻會(huì)有影響。

在PHP 7中按照引用循環(huán)的時(shí)候?qū)?shù)組的修改會(huì)影響循環(huán),在PHP 5中則不會(huì)改變。

  • goto
    goto語(yǔ)句可以用來(lái)跳轉(zhuǎn)到程序中的另一個(gè)位置。該目標(biāo)位置可以用目標(biāo)名稱加上冒號(hào)來(lái)標(biāo)記,而跳轉(zhuǎn)指令是goto之后接上目標(biāo)位置的標(biāo)記。PHP中對(duì)goto語(yǔ)句有一定限制,即目標(biāo)位置只能位于同一個(gè)文件和作用域,也就是說(shuō)無(wú)法跳出一個(gè)函數(shù)或類方法,也無(wú)法跳入另一個(gè)函數(shù)、其他循環(huán)或者switch結(jié)構(gòu)中??梢蕴鲅h(huán)或者switch,goto語(yǔ)句常用來(lái)代替多層的break語(yǔ)句。
goto  a;
echo "hello";
a:
echo  "world";

主要用來(lái)跳出復(fù)雜循環(huán)

for ($num =  0;  $num < 100;  ++$num)  {
  if ($num  === 3)   {
    echo "is  3";
    goto a;  
}
  echo  $num;
}
a:
ehco  "end  loop";
  • 包含語(yǔ)句用于在PHP文件中引入另一個(gè)文件,這樣有利于代碼重用。PHP中共有4個(gè)包含外部文件的方法,分別是include、include_once、require、require_once。
  • include
    include語(yǔ)句包含并運(yùn)行指定文件。被包含文件先按參數(shù)給出的路徑尋找,如果沒(méi)有給出目錄(只有文件名),就按照include_path(在配置文件中可查看include_path)指定的目錄尋找。如果在include_path下沒(méi)找到該文件,那么include最后會(huì)在調(diào)用腳本文件所在的目錄和當(dāng)前工作目錄下尋找。如果最后仍未找到文件,include結(jié)構(gòu)就會(huì)發(fā)出一條警告,例如:

當(dāng)一個(gè)文件被包含時(shí),其中所包含的代碼繼承了include所在行的變量范圍。從該處開(kāi)始,調(diào)用文件在該行處可用的任何變量在被調(diào)用的文件中也都可用。不過(guò)所有在包含文件中定義的函數(shù)和類都具有全局作用域。如果include出現(xiàn)于調(diào)用文件中的一個(gè)函數(shù)里,那么被調(diào)用的文件中所包含的所有代碼將表現(xiàn)得如同它們是在該函數(shù)內(nèi)部定義的一樣。所以它將遵循該函數(shù)的變量范圍。此規(guī)則的一個(gè)例外是魔術(shù)常量,它們是在發(fā)生包含之前就已被解析器處理的.

  • include_once
    include_once和includ效果類似,唯一的區(qū)別是如果文件已經(jīng)被包含,就不會(huì)再被包含。
    用于在腳本執(zhí)行期間同一個(gè)文件只會(huì)執(zhí)行一次的情況確保它只被執(zhí)行一次,以避免重復(fù)定義,變量重新賦值的問(wèn)題。

  • require
    require和include幾乎一模一樣,不同的是當(dāng)包含不存在的文件時(shí),require會(huì)爆出一個(gè)Fatal Error錯(cuò)誤并且終止執(zhí)行,include則會(huì)發(fā)出一個(gè)warning但繼續(xù)執(zhí)行代碼。

  • require_once
    require_once功能和include_once效果基本上相同,唯一的區(qū)別是php會(huì)檢查文件是否存在。

5.函數(shù)

將一段代碼封裝成一段函數(shù),在調(diào)用的時(shí)候只需要這個(gè)函數(shù)名即可。

function foo($argc_1,  $argc_2) {
  state;
}

其中foo是函數(shù)名,argc_1和argc_2是函數(shù)的參數(shù)。函數(shù)的參數(shù)可以是零個(gè)或者任意個(gè)。任何有效的php代碼都可以寫(xiě)在函數(shù)體內(nèi)。php的函數(shù)作用域是全局的,任何一個(gè)文件內(nèi)的函數(shù)定義后可以在該文件的任何地方調(diào)用。

function add_sum($num1, $num2)  {
  return $num1 + $num2;
}

6.函數(shù)的參數(shù)

PHP支持按值傳遞參數(shù)(默認(rèn)),通過(guò)引用傳遞參數(shù)及默認(rèn)參數(shù),也支持可變長(zhǎng)度參數(shù)列表。PHP支持函數(shù)參數(shù)類型聲明。

-按照值傳遞

function  add($num1, $num2) {
   $num1 += $num2;
}

echo $num1; // won't  change
  • 按照參數(shù)傳遞
function add(&$num1, $num2) {
  $num1 += $num2;
}
echo $num1;//change
  • 默認(rèn)參數(shù)
function  add($arr =  array("hello","world"), $num1  = 100) {
}
  • 參數(shù)的類型聲明
    php5已經(jīng)引入?yún)?shù)類型聲明,如果給定的值不是合法類型,php5會(huì)返回一個(gè)Fatal Error,php7則會(huì)返回一個(gè) TypeError Exception
class/interface       php5.0
Array                 php5.1
Callable              php5.4//有效的回調(diào)用
Bool                   php7
Float                  php7
Int                    php7
String                 php7
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容