目錄
基礎數據類型
● 四種標量類型
1. Boolean 布爾類型;判斷方法 is_bool(); 類型強轉(bool),(boolean)
2. Integer 整型;判斷方法is_integer();類型強轉(int),(integer)
3. Float 浮點型,也稱作 Double;判斷方法is_float();類型強轉(float),(double),(real)
4. String 字符型;判斷方法is_string();類型強轉(string)
● 兩種複合類型
1. Array 數組;判斷方法is_array();類型強轉(array)
2. Object 對象 ;判斷方法is_object();類型強轉(object)
● 兩種特殊類型
1. Resource 資源;判斷方法is_resource()
2. NULL NULL;判斷方法 is_null();類型強轉(unset)
● 僞類型
僞類型(pseudo-types) 是 PHP 文檔裏用於指示參數可以使用的類型和值。 請注意,它們不是 PHP 語言裏原生類型。 所以不能把僞類型用於自定義函數裏的類型約束(typehint)。
1. mixed
2. number
3. callback
補充說明:
- 通過gettype()獲取變量的類型字符串
字符串單引號和雙引號的區別
- 轉義字符不同
- 對變量的解析不同(雙引號解析變量)
- 解析速度不同(單引號快)
預定義變量
- $GLOBALS 引用全局作用域中可用的全部變量
- $_SERVER 這種超全局變量保存關於報頭、路徑和腳本位置的信息。
- $_REQUEST HTTP Request 變量(默認情況下包含了 $_GET,$_POST 和 $_COOKIE 的數組。)
- $_GET 通過 URL 參數傳遞給當前腳本的變量的數組。
- $_POST 當 HTTP POST 請求的 Content-Type 是 application/x-www-form-urlencoded 或 multipart/form-data 時,會將變量以關聯數組形式傳入當前腳本
- $_FILES 通過 HTTP POST 方式上傳到當前腳本的項目的數組
- $_ENV 通過環境方式傳遞給當前腳本的變量的數組。
- $_COOKIE 通過 HTTP Cookies 方式傳遞給當前腳本的變量的數組。
- $_SESSION 當前腳本可用 SESSION 變量的數組。
補充說明$_GET和$_POST區別
- GET使用URL或Cookie傳參。而POST將數據放在BODY中。
- GET的URL會有長度上的限制,則POST的數據則可以非常大。
- POST比GET安全,因爲數據在地址欄上不可見。
魔術函數
-
PHP 5 允行開發者在一個類中定義一個方法作爲構造函數。具有構造函數的類會在每次創建新對象時先調用此方法,所以非常適合在使用對象之前做一些初始化工作。
-
PHP 5 引入了析構函數的概念,這類似於其它面向對象的語言,如 C++。析構函數會在到某個對象的所有引用都被刪除或者當對象被顯式銷燬時執行。
-
在對象中調用一個不可訪問方法時,__call() 會被調用。
-
在靜態上下文中調用一個不可訪問方法時,__callStatic() 會被調用。
-
讀取不可訪問屬性的值時,__get() 會被調用。
-
在給不可訪問屬性賦值時,__set() 會被調用。
-
當對不可訪問屬性調用 isset() 或 empty() 時,__isset() 會被調用
-
當對不可訪問屬性調用 unset() 時,__unset() 會被調用。
-
serialize() 函數會檢查類中是否存在一個魔術方法 __sleep()。如果存在,該方法會先被調用,然後才執行序列化操作。
-
與之相反,unserialize() 會檢查是否存在一個 __wakeup() 方法。如果存在,則會先調用 __wakeup 方法,預先準備對象需要的資源。
-
__toString() 方法用於一個類被當成字符串時應怎樣迴應。
-
當嘗試以調用函數的方式調用一個對象時,__invoke() 方法會被自動調用。
-
PHP 5.1.0 起當調用 var_export() 導出類時,此靜態 方法會被調用。
-
當複製完成時,如果定義了 __clone() 方法,則新創建的對象(複製生成的對象)中的 __clone() 方法會被調用,可用於修改屬性的值(如果有必要的話)。
-
當轉儲對象以獲取應顯示的屬性時,此方法由var_dump()調用。 如果方法未在對象上定義,那麼將顯示所有public,protected和private屬性。
-
嘗試加載未定義的類(該方法在PHP7.2中已經刪除)
魔術常量
- __LINE__ 當前文件中的行號
- __FILE__ 返回文件的完整路徑和文件名。如果用在包含文件中,則返回包含文件名。自 PHP 4.0.2 起,FILE 總是包含一個絕對路徑,而在此之前的版本有時會包含一個相對路徑。
- __FUNCTION__ 返回文件的完整路徑和文件名。如果用在包含文件中,則返回包含文件名。自 PHP 4.0.2 起,FILE 總是包含一個絕對路徑,而在此之前的版本有時會包含一個相對路徑。
- __CLASS__ 返回類的名稱(PHP 4.3.0 新加)。自 PHP 5 起本常量返回該類被定義時的名字(區分大小寫)。在 PHP 4 中該值總是小寫字母的。
- __METHOD__ 返回類的方法名(PHP 5.0.0 新加)。返回該方法被定義時的名字(區分大小寫)
COOKE和SESSION
COOKIE
/**
* 設置cookie
* @param string $name cookie 名稱
* @param string $value cookie 值
* @param int $expire cookie 保存時間
* @param string $path cookie 有效目錄
* @param string $domain cookie 保存域名
* @param bool $secure cookie 是否通過HTTPS協議傳輸
* @param bool $httponly cookie 不允許客戶端修改
*/
bool setcookie(string $name[, string $value = ''[, int $expire = 0[, string $path = '' [, string $domain = '' [, bool $secure = false[, bool $httponly = false ]]]]]])
SESSION
設置相關
1) session.save_handler = file
用於讀取/回寫session數據的方式,默認是files
2) session.save_path = “/var/lib/php/session”
指定保存session文件的目錄,可以指定到別的目錄,但是指定目錄必須要有httpd守護進程屬主(比如apache或www等)寫權限,否則無法回存session數據
3) session.auto_start = 0
如果啓用該選項,用戶的每次請求都會初始化session。我們推薦不啓用該設置,最好通過session_start()顯示地初始化session相關函數
session_start: 初始 session。
session_destroy: 結束 session。
session_unset: 釋放session內存。
session_name: 存取目前 session 名稱。
session_module_name: 存取目前 session 模塊。
session_save_path: 存取目前 session 路徑。
session_id: 存取目前 session 代號。
session_register: 註冊新的變量。
session_unregister: 刪除已註冊變量。
session_is_registered: 檢查變量是否註冊。
session_decode: Session 資料解碼。
session_encode: Session 資料編碼。
- session_start()
函數session_start會初始化session,也標識着session生命週期的開始。要使用session,必須初始化一個session環境。有點類似於OOP概念中調用構造函數構創建對象實例一樣。
session初始化操作,聲明一個全局數組$_SESSION,映射寄存在內存的session數據。如果session文件已經存在,並且保存有session數據,session_start()則會讀取session數據,填入$_SESSION中,開始一個新的session生命週期 - $_SESSION
它是一個全局變量,類型是Array,映射了session生命週期的session數據,寄存在內存中。在session初始化的時候,從session文件中讀取數據,填入該變量中。在session生命週期結束時,將$_SESSION數據寫回session文件。 - session_register()
在session生命週期內,使用全局變量名稱將注全局變量註冊到當前session中。所謂註冊,就是將變量填入$_SESSION中,值爲NULL。它不會對session文件進行任何IO操作,只是影響$_SESSION變量。注意,它的正確寫法是session_register(‘varname’),而不是session_register($varname) - session_unregister()
與session_register操作正好相反,即在session生命週期,從當前session註銷指定變量。同樣隻影響$_SESSION,並不進行任何IO操作 - session_unset()
在session生命週期,從當前session中註銷全部session數據,讓$_SESSION成爲一個空數組。它與unset($_SESSION)的區別在於:unset直接刪除$_SESSION變量,釋放內存資源;另一個區別在於,session_unset()僅在session生命週期能夠操作$_SESSION數組,而unset()則在整個頁面(page)生命週期都能操作$_SESSION數組。session_unset()同樣不進行任何IO操作,隻影響$_SESSION數組 - session_destroy()
如果說session_start()初始化一個session的話,而它則註銷一個session。意味着session生命週期結束了。在session生命週期結整後,session_register, session_unset, session_register都將不能操作$_SESSION數組,而$_SESSION數組依然可以被unset()等函數操作。這時,session意味着是未定義的,而\$_SESSION依然是一個全局變量,他們脫離了關映射關係。 通過session_destroy()註銷session,除了結束session生命週期外,它還會刪除sesion文件,但不會影響當前\$_SESSION變量。即它會產生一個IO操作 - session_regenerate_id()
調用它,會給當前用戶重新分配一個新的session id。並且在結束當前頁面生命週期的時候,將當前session數據寫入session文件。前提是,調用此函數之前,當前session生命週期沒有被終止(參考第9點)。它會產生一個IO操作,創建一個新的session文件,創建新的session文件的是在session結束之前,而不是調用此函數就立即創建新的session文件。 - session_commit()
session_commit()函數是session_write_close()函數的別名。它會結束當前session的生命週期,並且將session數據立即強制寫入session文件。不推薦通過session_commit()來手工寫入session數據,因爲PHP會在頁面生命週期結束的時候,自動結束當前沒有終止的session生命週期。它會產生一個IO寫操作 - session_end()
結束session,默認是在頁面生命週期結束的之前,PHP會自動結束當前沒有終止的session。但是還可以通過session_commit()與session_destroy()二個函數提前結束session。不管是哪種方式,結束session都會產生IO操作,分別不一樣。默認情況,產生一個IO寫操作,將當前session數據寫回session文件。session_commit()則是調用該函數那刻,產生一個IO寫操作,將session數據寫回session文件。而session_destroy()不一樣在於,它不會將數據寫回session文件,而是直接刪除當前session文件。有趣的是,不管是session_commit(),還是session_destroy()都不會清空$_SESSION數組,更不會刪除$_SESSION數組,只是所有session_*函數不能再操作session數據,因爲當前的session生命週期終止了,即不能操作一個未定義對象。
設計模式
- 一、單例設計模式
單例模式的要點有三個:
一是某個類只能有一個實例
二是它必須自行創建這個實例
三是它必須自行向整個系統提供這個實例
爲什麼要使用PHP單例模式
php的應用主要在於數據庫應用, 一個應用中會存在大量的數據庫操作, 在使用面向對象的方式開發時, 如果使用單例模式, 則可以避免大量的new 操作消耗的資源,還可以減少數據庫連接這樣就不容易出現 too many connections情況。
一個類來全局控制某些配置信息
<?php
namespace lib\mode;
/**
* Class Man
* @package lib\mode
* @desc 設計模式單例模式
* 1 私有化構造函數和克隆函數
* 2 提供方法實例化對象
*/
class Man
{
// 保存實例化對象屬性
private static $instance;
/**
* Man constructor.
* @desc 私有化構造函數
*/
private function __construct()
{
}
/**
* __clone() 私有化克隆函數
*/
private function __clone()
{
return self::$instance;
}
/**
* getInstance() 提供公共方法獲取對象
* @return Man
*/
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* 其他方法
*/
public function test()
{
echo '單例設計模式';
}
}
二、簡單工廠模式
- 抽象基類:類中定義抽象一些方法,用以在子類中實現
繼承自抽象基類的子類:實現基類中的抽象方法
- 工廠類:用以實例化所有相對應的子類
<?php
namespace lib\mode;
/**
* Class Factory
* @package lib\mode
* @desc 設計模式 簡單工廠模式
* 1、提供一個工廠類,生產出指定類
* 2、提供一個抽象類,設計出需要抽象的方法,讓子類實現
* 3、子類實現抽象基類
*/
class Factory
{
/**
* createObject() 工廠提供創建對象方法
* @param string $name 需要創建的類名
* @param mixed|null $config 配置信息
* @return bool
*/
public static function createObject($name, $config = null)
{
$mixReturn = false;
if ($name) {
$name = '\\lib\\mode\\'.$name;
if(class_exists($name)) {
try {
$mixReturn = new $name($config);
} catch (\Exception $e) {
$mixReturn = false;
}
}
}
return $mixReturn;
}
}
/**
* Class Operation
* @package lib\mode
* @desc 抽象基類, 提供抽象方法
*/
abstract class Operation
{
/**
* getValue() 提供抽象方法,計算兩個值的操作後的值
* @param $value1
* @param $value2
* @return mixed
*/
abstract public function getValue($value1, $value2);
}
/**
* Class Add
* @package lib\mode
* @desc 加法類
*/
class Add extends Operation
{
public function getValue($value1, $value2)
{
return $value1 + $value2;
}
}
/**
* Class Subtract
* @package lib\mode
* @desc 減法類
*/
class Subtract extends Operation
{
public function getValue($value1, $value2)
{
return $value1 - $value2;
}
}
// 使用 加法類
$obj = Factory::createObject('Add');
var_dump($obj->getValue(8, 13));
// 使用 減法類
$obj = Factory::createObject('Subtract');
var_dump($obj->getValue(8, 13));
三、觀察者模式
定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新【GOF95】 又稱爲發佈-訂閱(Publish-Subscribe)模式、模型-視圖(Model-View)模式、源-監聽(Source-Listener)模式、或從屬者(Dependents)模式抽象主題(Subject)角色:主題角色將所有對觀察者對象的引用保存在一個集合中,每個主題可以有任意多個觀察者。 抽象主題提供了增加和刪除觀察者對象的接口。
抽象觀察者(Observer)角色:爲所有的具體觀察者定義一個接口,在觀察的主題發生改變時更新自己。
具體主題(ConcreteSubject)角色:存儲相關狀態到具體觀察者對象,當具體主題的內部狀態改變時,給所有登記過的觀察者發出通知。具體主題角色通常用一個具體子類實現。
具體觀察者(ConcretedObserver)角色:存儲一個具體主題對象,存儲相關狀態,實現抽象觀察者角色所要求的更新接口,以使得其自身狀態和主題的狀態保持一致
<?php
namespace lib\mode;
/**
* Class Observe
* @package lib\mode
* @desc 設計模式 觀察者模式
* 1、監聽器
* 2、被觀察者
*/
/**
* Class Subject
* @package lib\mode
* @desc 抽象主題角色
*/
class Subject implements \SplSubject
{
private $observers;
private $name;
public function __construct($name)
{
$this->observers = new \SplObjectStorage();
$this->name = $name;
}
/**
* attach() 添加一個新的觀察者對象
* @param \SplObserver $observer
*/
public function attach(\SplObserver $observer)
{
$this->observers->attach($observer);
}
/**
* detach() 刪除一個已經註冊過的觀察者
* @param \SplObserver $observer
*/
public function detach(\SplObserver $observer)
{
$this->observers->detach($observer);
}
public function notify()
{
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
public function getName()
{
return $this->name;
}
}
/**
* Class Observe
* @package lib\mode
* @desc 觀察者角色信息類
*/
class Observe implements \SplObserver
{
public function update(\SplSubject $subject)
{
var_dump(__CLASS__. '-' . $subject->getName());
}
}
/**
* Class Observe
* @package lib\mode
* @desc 觀察者角色信息類1
*/
class Observe1 implements \SplObserver
{
public function update(\SplSubject $subject)
{
var_dump(__CLASS__. '-' . $subject->getName());
}
}
// 使用說明
$observer1 = new Observe();
$observer2 = new Observe1();
$subject = new Subject("test");
$subject->attach($observer1);
$subject->attach($observer2);
$subject->notify();
排序算法
冒泡排序
思路分析:在要排序的一組數中,對當前還未排好的序列,從前往後對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒。即,每當兩相鄰的數比較後發現它們的排序與排序要求相反時,就將它們互換。
/**
* 冒泡排序
* @param array $array
* @return array
*/
function bubbleSort($array)
{
$length = count($array);
if ($length > 1) {
for ($i = 0; $i < $length; $i++) {
for ($x = 0; $x < ($length - $i - 1); $x++) {
if ($array[$x] > $array[$x + 1]) {
$tmp = $array[$x + 1];
$array[$x + 1] = $array[$x];
$array[$x] = $tmp;
}
}
}
}
return $array;
}
快速排序
找到當前數組中的任意一個元素(一般選擇第一個元素),作爲標準,新建兩個空數組,遍歷整個數組元素,
如果遍歷到的元素比當前的元素要小,那麼就放到左邊的數組,否則放到右面的數組,然後再對新數組進行同樣的操作,
不難發現,這裏符合遞歸的原理,所以我們可以用遞歸來實現。
使用遞歸,則需要找到遞歸點和遞歸出口:
遞歸點:如果數組的元素大於1,就需要再進行分解,所以我們的遞歸點就是新構造的數組元素個數大於1
遞歸出口:我們什麼時候不需要再對新數組不進行排序了呢?就是當數組元素個數變成1的時候,所以這就是我們的出口。
/**
* 快速排序
* @param array $array
* @return array
*/
function quickSort(array $array)
{
if ($array && is_array($array)) {
$length = count($array);
if ($length > 1) {
$left = $right = [];
for ($i = 1; $i < $length; $i ++) {
// 判斷當前元素的大小和第一個元素比較
if ($array[$i] < $array[0]) {
$left[] = $array[$i];
} else {
$right[] = $array[$i];
}
}
// 遞歸調用
if ($left) {
$left = quickSort($left);
}
if ($right) {
$right = quickSort($right);
}
return array_merge($left, [$array[0]], $right);
}
}
return $array;
}
選擇排序
思路分析:在要排序的一組數中,選出最小的一個數與第一個位置的數交換。然後在剩下的數當中再找最小的與第二個位置的數交換,如此循環到倒數第二個數和最後一個數比較爲止。
/**
* 選擇排序
* 在要排序的一組數中,選出最小的一個數與第一個位置的數交換。然後在剩下的數當中再找最小的與第二個位置的數交換,如此循環到倒數第二個數和最後一個數比較爲止。
* @param array $array
* @return array
*/
function selectSort(array $array)
{
$length = count($array);
if ($length > 1) {
for ($i = 0; $i < $length - 1; $i ++) {
$index = $i;
for ($x = $i + 1; $x < $length; $x ++) {
// 默認$array[$index] 爲最小值
if ($array[$index] > $array[$x]) {
// 記錄最小值
$index = $x;
}
}
// 已經確定最小值的位置,保持到$index中;如果發現最小值的位置與當前假設的位置$i不同,則位置互換即可。
if ($index != $i) {
$tmp = $array[$index];
$array[$index] = $array[$i];
$array[$i] = $tmp;
}
}
}
return $array;
}
插入排序
在要排序的一組數中,假設前面的數已經是排好順序的,現在要把第n個數插到前面的有序數中,使得這n個數也是排好順序的。如此反覆循環,直到全部排好順序。
/**
* 插入排序
* 在要排序的一組數中,假設前面的數已經是排好順序的,現在要把第n個數插到前面的有序數中,使得這n個數也是排好順序的。如此反覆循環,直到全部排好順序。
* @param array $array
* @return array
*/
function insertSort(array $array)
{
$length = count($array);
if ($length > 0) {
for ($i = 1; $i < $length; $i ++) {
$tmp = $array[$i];
// 內層循環,比較插入
for ($x = $i - 1; $x >= 0; $x --) {
if ($tmp < $array[$x]) {
// 發現插入的元素要小,交換位置,將後邊的元素與前面的元素互換
$array[$x + 1] = $array[$x];
$array[$x] = $tmp;
} else {
break;
}
}
}
}
return $array;
}