8天從零學習PHP-day1 PHP初探

這一章主要對PHP基礎語法進行學習,篇幅可能過長。php

首先咱們都要明白一個道理,學習一門語言不是一蹴而就的事情,一篇博客也不可能窮盡PHP的方方面面。從會到精通,須要一個漫長的過程。我只是最快的方式學會PHP,而不是精通PHP。html

1、語法

由於語法實在太多,沒辦法所有覆蓋講解。我這裏語法的這一部分,適合瞭解一些編程語言的人看。做爲快速入門。java

這裏假設你已經具有一門其餘編程語言的基本知識。若是你是徹底的編程新手,建議你去PHP官網系統的學習這部份內容。c++

https://www.php.net/manual/zh/langref.phpgit

特性

  • 語法簡單,開發速度快,效率高,學習成本低。github

  • 簡單但功能強大,很是適合web網站開發。golang

  • 服務端腳本語言運行速度快,無需編譯。web

  • 跨平臺能力強。shell

特色

  • 面向對象的語言。編程

  • 弱類型,動態類型語言。

  • 沒有main入口。

  • 具備訪問域關鍵字。

  • 多線程語言。

  • 多繼承語言。

關鍵字

__halt_compiler() abstract and array() as
break callable (as of PHP 5.4) case catch class
clone const continue declare default
die() do echo else elseif
empty() enddeclare endfor endforeach endif
endswitch endwhile eval() exit() extends
final finally (從PHP 5.5開始) for foreach function
global goto (從PHP 5.3開始) if implements include
include_once instanceof insteadof (從PHP 5.4開始) interface isset()
list() namespace (從PHP 5.3開始) new or print
private protected public require require_once
return static switch throw trait (從PHP 5.4開始)
try unset() use var while
xor yield (從PHP 5.5開始)      

編譯時常量

CLASS DIR (從PHP 5.3開始) FILE FUNCTION LINE METHOD
NAMESPACE (從PHP 5.3開始) TRAIT (從PHP 5.4開始)        

有時也被稱爲魔術常量,是PHP預約義的常量。不區分大小寫。

和Node.js中的__dirname__filename概念相同。使用方式:__常量名__

基本語法

PHP 基本用法有兩種,第一種是寫在單獨的PHP文件中,第二種是寫在html文件中。

php文件中的寫法是第一行以<?php開頭便可。

<?php
echo "hello";

若是是嵌套在html文件中,使用<?php ?>這種寫法,寫過JSP的同窗應該知道,這和<% %>做用幾乎同樣。

<h1><?php echo 'hello';?></h1>

PHP沒有在行尾補充分號的機制,因此代碼的每一行,咱們都須要添加分號 ;

命名規則

PHP 中變量、常量、函數等都遵循相同的規則。

一個有效的變量名由字母或者下劃線開頭,後面跟上任意數量的字母,數字,或者下劃線。即字母 a-z,A-Z,以及 ASCII 字符從 127 到 255(0x7f-0xff)。

PHP社區喜歡使用下劃線命名法,而不是駝峯命名法。雖然這種風格看上去很彆扭,但咱們仍是儘可能遵照吧。

$dog_name = "little white";// good
$catName = "big black";// bad

輸出/調試

經常使用的有兩個,echo 和 print。區別不大,echo 更經常使用一些,你能夠一直使用echo。

echo能夠輸出多個字符串到頁面上,print只能輸出一個。

echo沒有返回值,運行更快。print返回值老是1。

<?php
$dog_name = "little white";
$cat_name = "big black";
echo '<div>' ,$dog_name, '</div>';
print $cat_name;

註釋

PHP支持3種註釋,分別借鑑了C、C++和shell的註釋。

// c語言風格註釋
/* c++風格註釋 */
# shell風格註釋

變量

PHP 中的變量用一個美圓符號後面跟變量名來表示。變量名是區分大小寫的。

<?php

$a = 123;
echo $a;

要注意一點,變量的聲明和使用,始終都須要帶着美圓符號$符號。

變量做用域

PHP變量做用域有4種。

  • local

  • global

  • static

  • parameter

local

本地變量的做用域,好比在函數中,用完即清理掉。

global

在全部函數以外定義的變量,擁有全局做用域。

全局變量能夠在除了函數外任何地方使用。在函數內使用須要加global關鍵字。

全局變量被手機在一個叫作 $GLOBALS 的數組裏面,也能夠經過 $GLOBALS['name']的方式訪問,但不推薦這麼些。

static

將local變量持久保存。

parameter

參數做用域。

<?php
$x = 1;// global做用域

function add($num/* parameter做用域 */)
{
   static $z = 0;// static做用域,用於記錄add函數被調用的次數。add運行結束後,$z仍然存在,但沒法再訪問到。
   $z++;

   global $x;// 使用global必須使用global關鍵字
   $y = 2;// local做用域,最普通的本地變量,每次add函數運行結束,被清理掉,再次運行再次建立。

   return $x + $y + $z + $num;
   // 另外一種訪問 global 變量的方法
   // return $GLOBALS['x'] + $y + $z + $num;
}

echo add(1);// 5 (1+2+1+1)
echo add(2);// 7 (1+2+2+2)
echo add(3);// 9 (1+2+3+3)

常量

定義一個常量,須要使用define函數。

define有3個參數。常量名、常量值、是否大小寫敏感。前兩個必選,第三個可選參數默認false,對大小寫不敏感。設置成true,就對大小寫敏感。

<?php
// 大小寫敏感
define('tiger', "i'm tiger");
echo tiger;
// 大小寫不敏感
define('Dog', "i'm dog", true);
echo '<div> doG </div>';

數據類型

字面量類型 4種
  • string 字符串

  • boolean 布爾值

  • integer 整型

  • float(double) 浮點型/雙精度

<?php
$str = "hello";
$int = 123;
$float = 1.2;
$bool = true;
複合類型 3種
  • array 數組

使用array函數建立,也可使用字面量形式[]建立

<?php
$arr = array('1', 2, 3.0);
$arr2 = ['1', 2, 3.0];
  • object 對象

須要經過new關鍵字來建立。

  • callable 可調用

其實本質就是函數

特殊類型

resource 資源

NULL 無類型

獲取變量類型
  • var_dump 函數,查看變量內容

  • gettype 函數,調試時使用,返回字符串類型

  • is_type 函數,檢驗類型,返回boolean值

<?php
$arr = array("1", 2, 3.0);
echo var_dump($arr);// 輸出array(3) { [0]=> string(1) "1" [1]=> int(2) [2]=> float(3) }
echo "<br/>";
echo gettype($arr);// 輸出 array
echo "<br/>";
echo is_array($arr);// 輸出1,實際上是boolean值true,可是會被轉換成1輸出到頁面
轉換變量類型
  • 強制類型轉換 語法類同 java

  • settype函數

<?php
// 將 int 類型轉換成 string類型    
$one = 1;
(string)$one;// 強制類型轉換,變量前面加(類型)
settype($one, "string");// settype函數轉換,接受2個參數

表達式

這一部分涉及內容過多,但和其餘大部分編程語言相似,我只把運算符當在這裏,進行補充說明。不會詳細解讀。

運算符
賦值運算符=
算術運算符
例子 名稱 結果
-$a 取反 $a 的負值。
$a + $b 加法 $a 和 $b 的和。
$a - $b 減法 $a 和 $b 的差。
$a * $b 乘法 $a 和 $b 的積。
$a / $b 除法 $a 除以 $b 的商。
$a % $b 取模 $a 除以 $b 的餘數。
$a ** $b Exponentiation Result of raising $a to the $b'th power. Introduced in PHP 5.6.
位運算符
例子 名稱 結果
$a & $b And(按位與) 將把 $a 和 $b 中都爲 1 的位設爲 1。
$a | $b Or(按位或) 將把 $a 和 $b 中任何一個爲 1 的位設爲 1。
$a ^ $b Xor(按位異或) 將把 $a 和 $b 中一個爲 1 另外一個爲 0 的位設爲 1。
~ $a Not(按位取反) 將 $a 中爲 0 的位設爲 1,反之亦然。
$a << $b Shift left(左移) 將 $a 中的位向左移動 $b 次(每一次移動都表示「乘以 2」)。
$a >> $b Shift right(右移) 將 $a 中的位向右移動 $b 次(每一次移動都表示「除以 2」)。
比較運算符
例子 名稱 結果
$a == $b 等於 TRUE,若是類型轉換後 $a 等於 $b。
$a === $b 全等 TRUE,若是 $a 等於 $b,而且它們的類型也相同。
$a != $b 不等 TRUE,若是類型轉換後 $a 不等於 $b。
$a <> $b 不等 TRUE,若是類型轉換後 $a 不等於 $b。
$a !== $b 不全等 TRUE,若是 $a 不等於 $b,或者它們的類型不一樣。
$a < $b 小與 TRUE,若是 $a 嚴格小於 $b。
$a > $b 大於 TRUE,若是 $a 嚴格大於 $b。
$a <= $b 小於等於 TRUE,若是 $a 小於或者等於 $b。
$a >= $b 大於等於 TRUE,若是 $a 大於或者等於 $b。
$a <=> $b 太空船運算符(組合比較符) 當$a小於、等於、大於$b時 分別返回一個小於、等於、大於0的integer 值。 PHP7開始提供.
$a ?? $b ?? $c NULL 合併操做符 從左往右第一個存在且不爲 NULL 的操做數。若是都沒有定義且不爲 NULL,則返回 NULL。PHP7開始提供。
遞增遞減運算符
++$a 前加 $a 的值加一,而後返回 $a。
$a++ 後加 返回 $a,而後將 $a 的值加一。
--$a 前減 $a 的值減一, 而後返回 $a。
$a-- 後減 返回 $a,而後將 $a 的值減一。
邏輯運算符
例子 名稱 結果
$a and $b And(邏輯與) TRUE,若是 $a 和 $b 都爲 TRUE
$a or $b Or(邏輯或) TRUE,若是 $a 或 $b 任一爲 TRUE
$a xor $b Xor(邏輯異或) TRUE,若是 $a 或 $b 任一爲 TRUE,但不一樣時是。
! $a Not(邏輯非) TRUE,若是 $a 不爲 TRUE
$a && $b And(邏輯與) TRUE,若是 $a 和 $b 都爲 TRUE
$a || $b Or(邏輯或) TRUE,若是 $a 或 $b 任一爲 TRUE
錯誤控制運算符

@當將其放置在一個 PHP 表達式以前,該表達式可能產生的任何錯誤信息都被忽略掉。

執行運算符

`` PHP 將嘗試將反引號中的內容做爲 shell 命令來執行,並將其輸出信息返回。能夠利用執行運算符對操做系統進行直接接觸。

字符串運算符

鏈接運算符(「.」) 返回其左右參數鏈接後的字符串

鏈接賦值運算符(「.=」),它將右邊參數附加到左邊的參數以後

數組運算符
例子 名稱 結果
$a + $b 聯合 $a 和 $b 的聯合。
$a == $b 相等 若是 $a 和 $b 具備相同的鍵/值對則爲 TRUE
$a === $b 全等 若是 $a 和 $b 具備相同的鍵/值對而且順序和類型都相同則爲 TRUE
$a != $b 不等 若是 $a 不等於 $b 則爲 TRUE
$a <> $b 不等 若是 $a 不等於 $b 則爲 TRUE
$a !== $b 不全等 若是 $a 不全等於 $b 則爲 TRUE
類型運算符

instanceof

流程控制

PHP的流程控制和其餘語言相似。比較簡單,有如下幾種:

  • 判斷:if 和 else 及 elseif/else if

  • 循環:while、do-while、for、foreach

  • 跳出/中斷循環:break、continue

  • switch和case

  • declare

  • 返回:return

  • 導入:require/include和require once

  • 跳轉:goto

這裏主要講一下 declare 、 require/include 、 goto,它們比較特殊。而其餘流程控制關鍵字比較簡單也比較常見,幾乎在全部語言中都有相似概念。

require/include

require的概念能夠理解爲引包。和JavaScript中的require很像,更相似於Java中的import。

假設有這樣一個目錄結構

在utils.php 中寫一個函數

<?php
function my_log($message)
{
   echo '<div>'.$message.'</div>';
}

咱們想在其餘地方複用,那麼就是用require便可。好比index.php

<?php
require('utils.php');

echo my_log('hi.');

include的用途與require是徹底同樣的,你能夠嘗試將index.php中的require替換爲include。

它們的區別主要在於錯誤處理方式的不一樣以及返回值的不一樣。

require出錯會中斷程序,拋出致命錯誤。

include出錯不會中斷程序,拋出警告錯誤。

最佳實踐是將它們放置在文件的最頂部。

include_once和require_once的做用是防止屢次導入,若是在程序中其餘地方導入過相同的文件,就不會再次導入。

declare

主要做用:每執行n行低級代碼,就會執行一遍註冊的函數。

除此以外,還能夠開啓嚴格模式和定義源本件編碼。

語法:只有一個參數是ticks = n,通常會配合register_tick_function()使用。

<?php
// 每執行3行低級代碼會觸發一次 yell 函數
declare(ticks = 3);
function yell(){
   echo '<h1>wangwang</h1>';
}
register_tick_function('yell');
// 註冊後,什麼都不作,yell 函數也會執行1遍

// for 是高級代碼,不會算入
for($i = 0; $i < 10; $i++)
{
   $i;// 訪問 $i 屬於低級語法,會計算
}
goto

跳轉到程序中的另外一位置。

goto容易讓程序難以理解,相似於golang中的go。不建議使用。

<?php
a:
echo 'a';

goto c;

b:
echo 'b';

c:
echo 'c';

goto會跳轉到標記爲c的位置,頁面會輸出ac。而直接跳過goto和c之間的代碼段。這樣就致使程序不會按照從上到下逐行執行。

命名空間 namespace

PHP命名空間與Java的分包,ES6的模塊化概念相似。

主要做用是防止自定義的類、函數或常量名稱重複。

用法:使用關鍵字namespace 聲明命名空間,使用 use 關鍵字使用其餘空間常量/函數/類。

一個文件能夠有多個命名空間。可使用正常語法,也可使用大括號語法,更推薦大括號的語法。

命名空間應該是在PHP代碼的最頂部出現,也就是程序的第一句。

PHP支持子命名空間。

<?php
// 聲明一個命名空間 Animal
namespace Animal {
// 命名空間中有一個Dog類
   class Dog
  {
  }
}
// 另外一個命名空間 Main
namespace Main{
// 使用 此空間之外空間的常量/函數/類時,須要用 use 關鍵字
   use Animal\Dog;
   new Dog();
}

函數 function

用 function 來自定義函數

PHP 中的全部函數和類都具備全局做用域,能夠定義在一個函數以內而在以外調用,反之亦然。

PHP 不支持函數重載,也不可能取消定義或者重定義已聲明的函數。

PHP 的函數支持可變數量的參數默認參數

<?php
function func($name = "f"/* 若是不傳參數,name默認就是f */, ...$option/* 默認是數組,能夠接受多個參數,最後轉換成數組 */)
{
   echo '<h1>',$name,'</h1>';
   echo '<h1>',var_dump($option),'</h1>';
}

func();
參數
引用參數傳遞&

PHP裏面全部的參數都是按值傳遞的。

<?php
$arr = array('1', '2');
function func($arr_p)
{
   $arr_p['3'] = '3';
   echo '<h1>', var_dump($arr_p), '</h1>';
}

func($arr);
echo var_dump($arr);

若是是寫JavaScript的同窗,可能會認爲輸出的兩個對象應該是一個內存塊的數據對吧?但在PHP中不是這樣的。

輸出結果爲:

array(3) { [0]=> string(1) "1" [1]=> string(1) "2" [3]=> string(1) "3" }

array(2) { [0]=> string(1) "1" [1]=> string(1) "2" }

也就是說$arr_p['3'] = '3';這行代碼並無改變global中的arr變量,若是你想直接改變原來的變量內容,這時就須要使用按引用傳遞。

只須要在參數前面加一個&符號,這樣就會把參數的指針傳遞進去,而後在函數內部訪問arr_p變量時,就會尋址到全局變量arr的內存地址。

function func(&$arr_p)

這時的輸出結果就符合預期了。

參數類型聲明

能夠進行參數類型聲明,這樣能夠限制函數的使用方式。

但在默認狀況下,php會強制轉化指望的類型。

能夠開啓嚴格類型,這樣會拋出TypeError。惟一例外是integere傳給float。

function func(array $arr_p)
返回值

函數省略return,返回值爲NULL。

能夠返回任意類型。

只能有一個返回值。

返回值也能夠有類型聲明,和golang語法同樣,在參數後面添加:type。

function func(array $arr_p):string{}// 返回值指定string類型 

但注意,這個寫法只支持PHP7之後的版本。

可變函數

若是一個變量名後有圓括號,PHP 將尋找與變量的值同名的函數,而且嘗試執行它。

$func('args')

也能夠用可變函數的語法來調用一個對象的方法。

當調用靜態方法時,函數調用要比靜態屬性優先。

<?php
$func = function () {
   echo 'hi';
};

$func();
內置函數

PHP 有不少標準的函數和結構。

可是須要PHP擴展模塊編譯支持。

不安裝模塊,直接使用內置函數會致使function is undefined 異常

匿名函數

也叫閉包函數,容許 臨時建立一個沒有指定名稱的函數。最常常用做回調函數參數的值。

閉包函數也能夠做爲變量的值來使用。PHP 會自動把此種表達式轉換成內置類 Closure 的對象實例。

相似於JavaScript中的var func = function (){}的形式

類 class

屬性

使用var定義,默認爲共有。

屬性訪問

在類的成員裏面,訪問類的非靜態屬性使用->,訪問靜態屬性使用::

常量

使用const聲明。訪問常量時不須要$。

構造函數

__construct。具備構造函數的類會在每次建立新對象時先調用此方法,因此很是適合在使用對象以前作一些初始化工做。

析構函數

__destruct

析構函數會在到某個對象的全部引用都被刪除或者當對象被顯式銷燬時執行。

引擎自動調用

若是子類中定義了構造函數則不會隱式調用其父類的構造函數。要執行父類的構造函數,須要在子類的構造函數中調用 parent::__construct()。若是子類沒有定義構造函數則會如同一個普通的類方法同樣從父類繼承。

要執行父類的析構函數,必須在子類的析構函數體中顯式調用 parent::__destruct()

訪問控制(可見性)

和 Java 語言同樣:有關鍵字 public(公有),protected(受保護)或 private(私有)

被定義爲公有的類成員能夠在任何地方被訪問。被定義爲受保護的類成員則能夠被其自身以及其子類和父類訪問。被定義爲私有的類成員則只能被其定義所在的類訪問。

類屬性必須定義爲公有,受保護,私有之一。若是用 var 定義,則被視爲公有。

方法和屬性相同。

<?php

class Animal
{
//   var $name;// 和下面那句聲明徹底相同
   public function __construct($name)
  {// 構造函數,new 調用時最早執行
       $this->name = $name;
  }

   public function __destruct()
  {// 析構函數,new 調用時,生命週期的最後一步
       echo '建立實例成功';
  }

   public $name;// 這個是公有的,能夠在實例中訪問
   private $age;// 私有的,僅在 Animal 內能夠訪問
   const category = 'Animal';// 常量

   public function getCategory(): string
  {
       return category;// 訪問常量不須要$
  }

   public function eat(): string
  {
       return $this->name . 'eat';
  }
}

$dog = new Animal('dog');
繼承 extends

我比較承認golang團隊的觀點,繼承是面嚮對象語言設計中比較失敗的一個概念。對於類的擴展,組合要比繼承好得多。

使用關鍵字 extends 來繼承,子類會覆蓋父類的方法。和Java的繼承基本上沒什麼差異,這裏不講了。

接口 interface

PHP的接口與其餘面向對象編程語言無異。

接口是面向對象很是重要的概念,其本質就是一種約定。

約定了類應該具備哪些特徵。但接口不會作具體實現。

一個類能夠實現多個接口,用逗號隔開。

將上面的例子改造一下:

<?php
// 定義了一個IAnimal接口,裏面要求實現兩個共有方法,getCategory和eat。
interface IAnimal{
   public function getCategory();
   public function eat($food);
}
// implement關鍵字來實現接口
class Animal implements IAnimal
{
   public function __construct($name)
  {
       $this->name = $name;
  }

   public function __destruct()
  {
       echo '建立實例成功';
  }

   public $name;
   private $age;
   const category = 'Animal';

   public function getCategory()
  {
       return category;
  }

   public
   function eat($food): string
  {
       return $this->name.'eat'.$food;
  }
}

new Animal('dog');

 

2、代碼風格

PSR

PSR是PHP Standard Recommendations(PHP標準推薦)的簡稱,這個是php-fig組織制定的一套規範。至今,php-fig已經發布了五個規範。

  • PSR-0:自動加載標準,2014-10-21該標準已經被廢棄,使用PSR-4替代

  • PSR-1:基本的編碼風格

  • PSR-2:編碼風格(更嚴格)

  • PSR-3:日誌記錄器接口

  • PSR-4:自動加載

這一點上,PHP作的仍是很好的,有一個統一的標準,比Java和JavaScript強。

這裏咱們只須要看PSR-2就行了,大約有這麼幾個方面。

  • 代碼必須使用4個空格符而不是 tab鍵 進行縮進。

  • 每行的字符數應該軟性保持在80個以內, 理論上必定不可多於120個, 但必定不能有硬性限制。

  • 每一個 namespace 命名空間聲明語句和 use 聲明語句塊後面,必須插入一個空白行。

  • 類的開始花括號({)必須寫在函數聲明後自成一行,結束花括號(})也必須寫在函數主體後自成一行。

  • 方法的開始花括號({)必須寫在函數聲明後自成一行,結束花括號(})也必須寫在函數主體後自成一行。

  • 類的屬性和方法必須添加訪問修飾符(privateprotected 以及 public), abstract 以及 final 必須聲明在訪問修飾符以前,而 static 必須聲明在訪問修飾符以後。

  • 控制結構的關鍵字後必須要有一個空格符,而調用方法或函數時則必定不能有。

  • 控制結構的開始花括號({)必須寫在聲明的同一行,而結束花括號(})必須寫在主體後自成一行。

  • 控制結構的開始左括號後和結束右括號前,都必定不能有空格符。

 

3、總結

簡單學習了PHP基本語法和代碼風格,爲後續PHP學習奠基基礎。

相關文章
相關標籤/搜索