PHP高級知識點彙總

面向對象 (OOP-object Oriented Progarmming)

  • 面向對象和麪向過程
    • 大象裝冰箱
    • 面向過程
      • 1 打開冰箱門
      • 2 把大象裝進去
      • 3 關閉冰箱門
    • 面向對象
      • 1 創建對象:冰箱,大象.
        • 1 冰箱-開門
        • 2 大象.進冰箱
        • 3 冰箱.關門
    • 面向過程好寫 面向對象好改;

類 對象

  • 類實例化==>對象
  • 對象抽象==>類
  • 類有屬性==>面向過程當中的 變量
  • 類有方法==>面向過程當中的 函數
  • 封裝
    • 把內部邏輯封裝起來,外部只有調用的權限,沒有修改的權限
  • 繼承
    • 子類能夠繼承父類的屬性(變量)和方法(函數)
    金剛鸚鵡(學舌(),毛,飛(),生長())==>鸚鵡類(學舌(),毛,飛(),生長())==>生物(生長());
    複製代碼
  • 多態
    • 調用者不同,執行邏輯不同

如何聲明一個類

  • 語法
[修飾符] class 類名{
    [修飾符] [屬性]
    [修飾符] [方法]
    }
複製代碼
  • 類的命名規範(大駝峯)
<?php
class Person{
    public $name = 'xiaoming';
    public $age = 18;
    public $sex = 'man';
    }
?>
複製代碼

屬性中的變量能夠初始化,可是初始化的值,必須是常數,能夠直接獲取值,不須要運算php

  • 從類實例化對象 $對象名 = new 類名() //"()"可加可不加mysql

    調用類的屬性和方法 用->web

<?php
//定義一個類
class Person{
    public name = null;
    public function eat(){
        echo "吃肉肉..........";
    }
    public function drink(){
        echo "喝酒..........";
    }
}
//把這個類實例化
$people = new Person;
$people->drink();   //  輸出  喝酒.........
$people->name = "張三";     //屬性賦值
echo $people->name;      //屬性調用
?>

$this 當前方法或屬性的調用者
對象之間的賦值,是按引用傳遞.
複製代碼

繼承

class A   extends  B{
    
}
//A 是子類   B 是父類
複製代碼

封裝

權限控制符,用來修飾屬性和方法redis

權限控制符 public:公共的 protected:受保護的 private:私人的sql

  • public 均可以訪問的到
  • Protected 子類和自身能夠調用,外部不能調用
  • private 私人的,最嚴格的的權限,只有本身能調用

魔術方法

構造方法__construct()__mongodb

實例化對象時自動觸發數據庫

析構方法__destruct__apache

對象銷燬時自動觸發,觸發時的三種方法編程

  • 腳本結束
  • unset(對象)
  • 對象 = null

靜態屬性 靜態方法

static 來定義靜態屬性和靜態方法,不用實例化對象,就能夠直接訪問,只能用類來訪問,使用::來調用windows

<?php

class Test{
    public static $course = "English";
    public static $score;
}
echo Test::$course;      //外部調用
複製代碼
<?php
//  內部調用 使用self::屬性/方法
class Test{
    public static $course = "English";
    public static $score = 0;

    public static function hello(){
        echo self::$score = 100; // 內部調用, 使用self::屬性/方法名
    }

}
echo Test::hello();
複製代碼

定義常量,使用const關鍵字來定義一個常量,通常常量名都是大寫的,區分大小寫 常量不能修改值,只能銷燬後從新定義

在類中定義的常量只能經過靜態方式來調用

重載

經過魔術方法,動態建立類屬性和方法

屬性重載 當調用當前環境下未定義或者不可見的類屬性或類方法時,重載方法會被調用

  • 不可訪問的屬性賦值__set()
<?php

class Person
{
    private $sex = 'male';

    public function __set($name, $value)
    {
        echo $name, ' ', $value;
    }

}

$stu = new Person();
$stu->sex = 'female';
複製代碼
  • 獲取不可訪問的屬性值,觸發__get()
<?php

class Person
{
    private $sex = 'male';
    protected $age = 39;

    public function __get($name)
    {
        if ($name == 'age') {
            echo "年齡 不是你想看, 想看就能看";
        }
    }


}

$stu = new Person();
$stu->age;
複製代碼
  • 對不可訪問屬性調用isset()empty()時,__isset()會被調用
<?php

class Person
{
    private $sex = 'male';
    protected $age = 39;


    public function __isset($name)
    {
        echo $name;
    }

}

$stu = new Person();
isset($stu->sex);
複製代碼
  • 當對不可訪問屬性調用unset()時,__unset()會被調用
<?php

class Person
{
    private $sex = 'male';
    protected $age = 39;


    public function __unset($name)
    {
        echo "您正在嘗試銷燬一個沒有權限的屬性 $name";
        unset(this->$name);
    }
}

$stu = new Person();
unset($stu->sex);
複製代碼

方法重載

  • 在對象中調用一個不可訪問方法時,__call()會被調用.
<?php

class Person
{
   private $sex = 'male';
   protected $age = 39;


   public function __call($name, $arguments)
   {
       var_dump($name); // 方法名字
       var_dump($arguments); // 參數數組
   }

   protected function getSex()
   {
       echo $this->sex;
   }
}

$stu = new Person();
$stu->getSex(1, 2, 3, 4);
複製代碼
  • 在靜態上下文中調用一個不可訪問方法時,__callStatic()會被調用
<?php

class Animal
{
    private function eat()
    {
        echo 'eat';
    }


    public static function __callStatic($name, $arguments)
    {
        echo '調用不存在的--靜態--方法名是:' . $name . '參數是:';
        print_r($arguments);
    }
}

$animal = new Animal();

Animal::smile('可愛', '大笑', '微笑');
複製代碼

繼承 extends

子類繼承父類全部的公有的和受保護的屬性和方法

<?php

class People
{
    public $name = "lisi";
    protected $age = 39;
    private $salary = 1000;
}

class Person extends People
{

}

$P1 = new Person();
echo $P1->name;
echo $P1->age; // 報錯
echo $P1->salary; // 報錯
複製代碼

繼承關鍵字extends,一個類繼承另外一個類,不能繼承多個,能夠鏈式繼承

class A extends B;      //類A 繼承  類B
class C extends A;      //類C 繼承  類A
複製代碼

重寫

重寫:繼承父類中的方法,子類中定義的與父類中同名的方法

當一個子類重寫其父類的方法時,PHP不會調用父類中已被重寫的方法,是否調用父類的方法取決於子類

<?php


class Person
{
  public function sayHi()
  {
      echo "hi";
  }
}

class Student extends Person
{
  public function sayHi()
  {
      echo 'hello';
  }
}

$stu = new Student();
$stu->sayHi();
複製代碼

關鍵字 parent:: 訪問父類中被重寫的屬性和方法,能夠再父類原有的代碼上追加新的代碼

<?php


class Person
{
    public function sayHi()
    {
        echo "hi";
    }
}

class Student extends Person
{
    public function sayHi()
    {
        parent::sayHi();
        echo " and say Hello";
    }
}

$stu = new Student();
$stu->sayHi();

複製代碼

final

若是一個類被聲明爲final,則不能被繼承.

<?php

final class Person{
    public $name = 'lisi';
}

class Student extends Person{
    public $sex = 'male';
} // 報錯, 不能繼承
複製代碼
<?php

// 去掉final, 則沒有問題
class Person
{
    public $name = 'lisi';
}

class Student extends Person
{
    public $sex = 'male';
}
複製代碼

若是父類中的方法被聲明爲final,則子類沒法重寫該方法

<?php

// 繼承父類的方法
class Person
{
    public $name = 'lisi';

    public function getName()
    {
        echo $this->name;
    }
}

class Student extends Person
{
    public function getName()
    {
        parent::getName();
        echo "\n";
        echo "能夠繼承父類!";
    }
}

$stu = new Student();
$stu->getName();

複製代碼

一樣的代碼,若是在getName函數前,添加final,則會報錯

<?php


class Person
{
    public $name = 'lisi';

    final public function getName() // 會報錯
    {
        echo $this->name;
    }
}

class Student extends Person
{
    public function getName()
    {
        parent::getName();
        echo "\n";
        echo "能夠繼承父類!";
    }
}

$stu = new Student();
$stu->getName();
複製代碼

多態

  • 多態(Polymorphism)按字面意思就是'多種狀態'
  • 接口的多種不一樣實行方式即爲多態
  • 同一操做做用於不一樣的對象,能夠有不一樣的解釋,產生不一樣的執行結果

抽象類

  • 聲明一個抽象類,聲明關鍵字abstract
  • 抽象的方法只是聲明瞭其調用方式(參數),不能定義其具體功能的實現,方法只寫名字,不寫具體內容
  • 抽象類不能被實例化
  • 抽象方法只能在抽象類裏
  • 抽象類能夠爲空,能夠不包含抽象方法

聲明一個抽象類

abstract class Person{
    abstarct public people(){
        
    }
}
複製代碼

具體類繼承而且實現

<?php

abstract class MyAbsClass
{
   abstract public function func();
}

class ChildClass extends MyAbsClass
{
   // 這樣寫會報錯, 由於沒有實現抽象類中定義的方法
}
複製代碼
<?php

abstract class MyAbsClass
{
    abstract public function func();
}

class ChildClass extends MyAbsClass
{
    public function func()
    {
        // 即使什麼都沒有寫, 也沒有關係...
    }
}
複製代碼

若是是抽象類繼承,則不用事先抽象方法

<?php

abstract class MyAbsClass
{
    abstract public function func();
}

abstract class ChildClass extends MyAbsClass
{
	// 什麼都沒寫, 也不會報錯...
}
複製代碼

抽象類,必須有抽象方法

abstract class MyAbsClass 
{
    public function func(); // 會報錯, 由於沒有abstract關鍵字
}

複製代碼

同理,含有抽象方法的類,必須是抽象類

class MyAbsClass // 會報錯, 由於沒有abstract關鍵字
{
    abstract public function func(); 
}
複製代碼

抽象類,必須有抽象方法,至少有一個便可

<?php

abstract class MyAbsClass
{
    public $name = '張三';
    public $age;

    public function test()
    {
        echo 'hello';
    }

    abstract public function func();
}
複製代碼

修飾詞關鍵順序

  • 類的屬性和方法必須添加訪問修飾符(private、protected以及public)
  • abstract以及final必須聲明在訪問修飾符以前
  • abstract和final不能共存
  • static必須聲明在訪問修飾符以後 final public static function

接口

  • 使用接口(interface),能夠指定某個類必須實現哪些方法,但不須要定義這些方法的具體內容。
  • 接口中也能夠定義常量。
  • 接口實現關鍵字implements
<?php

interface MyInterface
{
    const NUM = 123;

    public function func();

    public function test();
}

class MyClass implements MyInterface
{
    public function func()
    {

    }

    public function test()
    {
        echo 'hello';
    }
}
複製代碼
<?php

interface MyInterface
{
    const NUM = 123;

    public function func();

    public function test()
    {
        echo "test"; // 會報錯, 不能有具體方法
    };
}


複製代碼
<?php

interface MyInterface
{
    const NUM = 123;

    public function func();

    public function test();
}

class MyClass implements MyInterface
{
    public function func()
    {

    }

	// 報錯, 由於沒有實現test()
}
複製代碼
  • 抽象類實現接口, 能夠不用實現其中的方法, 可是抽象類的子類必須實現
<?php

interface MyInterface
{
    const NUM = 123;

    public function func();

    public function test();
}

abstract class MyClass implements MyInterface
{
	// 沒有實現接口的方法, 也不會報錯
}

class Demo extends MyClass
{
    public function func()
    {
        // 必須實現, 不然報錯
    }

    public function test()
    {
        // 必須實現, 不然報錯
    }
}
複製代碼
  • 接口也能夠繼承關鍵字extends, 若是接口B繼承了接口A, 而普通類 C實現了接口B, 則A和B全部的方法, C都要實現
<?php

interface A
{
    public function aaa();

}

interface B extends A
{
    public function bbb();
}

class C implements A
{
    public function bbb()
    {
		// 
    }

    public function aaa()
    {

    }
}
複製代碼
  • 一個類能夠實現多個接口, 兩個接口中的方法都須要實現
<?php

interface A
{
    public function aaa();

}

interface B
{
    public function bbb();
}

class C implements A, B
{
    public function bbb()
    {
		// 都得實現, 否則報錯
    }

    public function aaa()
    {
		// 都得實現, 否則報錯
    }
}
複製代碼
  • 繼承和實現能夠同時使用
<?php

interface A
{
    public function aaa();

}

interface B
{
    public function bbb();
}

class C
{
    public function bbb()
    {

    }

    public function aaa()
    {

    }
}

class D extends C implements A, B
{
	// 類D繼承C, C實現了A和B
}
複製代碼

抽象類和接口的區別

1.抽象類有普通的方法,接口沒有

2.抽象類能夠有本身的成員屬性和方法,接口只能有public 常量。

3.抽象類無關緊要構造方法,接口沒有構造方法

4.抽象類單繼承,接口多重繼承

類型運算符

  • instanceof用於肯定一個PHP變量是否屬於某一類class的實例
<?php


class A
{

}

class B
{

}

$a = new A();

var_dump($a instanceof A); // true
var_dump($a instanceof B); // false
複製代碼
  • instanceof也可用來肯定一個變量是否是繼承自某一父類的子類的實例
<?php


class A extends B
{

}

class B
{

}

$a = new A();

var_dump($a instanceof A); // true
var_dump($a instanceof B); // true
複製代碼
  • instanceof也可用於肯定一個變量是否是實現了某個接口的對象的實例
<?php


class A implements B
{

}

interface B
{

}

$a = new A();

var_dump($a instanceof A); // true
var_dump($a instanceof B); // true
複製代碼

類型約束

  • PHP5可使用類型約束
  • 函數的參數能夠指定其類型
<?php


class A
{

}

class B
{
    
}

$a = new A();


$b = new B();


function test(A $n)
{
    echo "ok";
}

test($a); // 輸出ok
test($b); // 報錯, 由於$b是B的實例, 不是A的實例
複製代碼
  • 若是一個類或接口指定了類型約束,則其全部的子類或實現也都如此
<?php


class A
{
    public function aaa(B $n)
    {

    }
}

class B
{

}

class C extends B
{
    public $a = '123';
}

class D extends A
{

}

$a = new A();
$c = new C();
$a->aaa($c);
複製代碼

自動加載

  • __autoload()函數也能自動加載類和接口
  • spl_autoload_register()函數能夠註冊任意數量的自動加載器,
  • 當使用還沒有被定義的類(class)和接口(interface)時自動去加載。
  • 建議使用spl_autoload_register()函數
  • 再也不建議使用__autoload()函數,在之後的版本中它可能被棄用

命名空間的基本使用

  • 從廣義上來講,命名空間是一種封裝事物的方法
  • 在不少地方均可以見到這種抽象概念
  • 例如,在操做系統中目錄用來將相關文件分組,對於目錄中的文件夾來講,它就扮演了命名空間的角色

編程中常見的兩類問題

  • 用戶編寫的代碼與PHP內部的類/函數/常量或第三方類/函數/常量之間的名字衝突
    • 好比引入的文件中,有當前文件已經使用的類/函數/常量名
  • 爲很長的標識符名稱(一般是爲了緩解第一類問題而定義的)建立一個別名(或簡短)的名稱,提升源代碼的可讀性

定義命名空間

  • 命名空間經過關鍵字namespace來聲明。
  • 若是一個文件中包含命名空間,它必須在其它全部代碼以前聲明命名空間
  • 聲明單個命名空間namespace MyProject

定義命名空間

  • 定義子命名空間namespace MyProject\Sub\Level;

  • 能夠在同一個文件中定義多個命名空間

  • 若是沒有定義任何命名空間,全部的類與函數的定義都是在全局空間,與PHP引入命名空間概念前同樣。

  • 在名稱前加上前綴\表示該名稱是全局空間中的名稱,即便該名稱位於其它的命名空間中時也是如此

  • __NAMESPACE__常量

  • 常量__NAMESPACE__的值是包含當前命名空間名稱的字符串

  • 在全局的,不包括在任何命名空間中的代碼,它包含一個空的字符串。

<?php

namespace hello\hello1;
var_dump(__NAMESPACE__); // hello\hello1
namespace hello\hello2;
var_dump(__NAMESPACE__); // hello\hello2
複製代碼<?php

var_dump(__NAMESPACE__); // ""
複製代碼非限定名稱, 徹底限定名稱, 限定名稱(絕對路徑, 相對路徑)
複製代碼
<?php

namespace A\B;
class MyClass
{
    public function __construct()
    {
        echo '空間A\B 中的類 實例化了' . "\n";
    }
}

namespace A;
class MyClass
{
    public function __construct()
    {
        echo '空間A 中的類 實例化了' . "\n";
    }
}

$obj = new MyClass();// 非限定名稱 就近
$obj = new \A\B\MyClass();// 徹底限定名稱 絕對路徑
$obj = new \A\MyClass();// 徹底限定名稱 絕對路徑
$obj = new B\MyClass();//限定名稱 相對路徑
複製代碼include不會改變當前命名空間, 可是include以後, 可使用引入文件中的命名空間
複製代碼
C:\Users\Administrator\Desktop\imooc\aaa.php
複製代碼
<?php

namespace aaa;

function demo()
{
    echo 'aaa';
}
複製代碼
C:\Users\Administrator\Desktop\imooc\bbb.php
複製代碼
<?php

namespace bbb;

function demo()
{
    echo 'bbb';
}

include 'aaa.php';
demo(); // bbb
var_dump(__NAMESPACE__); // bbb
\aaa\demo(); // 可使用aaa.php的命名空間
動態調用命名空間
複製代碼
動態調用函數
<?php


function demo()
{
    echo "demo\n";
}

demo(); // 調用demo

$a = 'demo';
$a(); // 一樣能夠調用demo
複製代碼
動態實例化對象
<?php


class A
{
    public function demo()
    {
        echo "demo\n";
    }
}

$a = new A();
$a->demo();

$b = "A";
$c = new $b;
$c->demo();
複製代碼
//動態調用命名空間
<?php

namespace A\B;

function demo()
{
    echo "demo\n";
}

namespace A;

demo(); // 會報錯, 由於當前命名空間下, 沒有demo()
複製代碼<?php

namespace A\B;

function demo()
{
    echo "demo\n";
}

namespace A;

\A\B\demo(); // 這就會正常了
複製代碼
<?php

namespace A\B;

function demo()
{
    echo "demo\n";
}

namespace A;
$a = '\A\B\demo'; // 效果同樣, 由於都是徹底限定名稱
$a = 'A\B\demo';
$a(); 
複製代碼
<?php

namespace A\B;

function demo()
{
    echo "demo\n";
}

namespace A;
$a = 'B\demo'; // 報錯, 不支持相對路徑
$a();
複製代碼

異常處理

異常

  • PHP錯誤:是屬於php程序自身的問題,通常是由非法的語法,環境問題致使的,使得編譯器沒法經過檢查,甚至沒法運行的狀況。
  • PHP異常:通常是業務邏輯上出現的不合預期、與正常流程不一樣的情況,不是語法錯誤。
  • 異常處理是一種可擴展、易維護的錯誤處理統一機制,並提供了一種新的面向對象的錯誤處理方式,用於在指定異常發生時改變腳本的正常流程。和編寫程序的流程控制類似。

異常處理的實現

try{  		//全部須要進行異常處理的代碼都必須放入這個代碼塊內
     ...		// 在這裏可使用throw語句拋出一個異常對象
 }catch(異常對象參數){	//使用該代碼塊捕獲一個異常,並進行處理
      ...		//在這裏作異常處理。也能夠再次拋出異常
 } [catch(,,){
     .. .. ..		
  }]

複製代碼

工做原理

  • 試着去執行try中代碼,若是沒有問題則跳過catch執行catch以後的代碼
  • Exception 是系統的類
  • 若try中代碼有異常,則須要手動拋出一個異常對象給了catch中的參數,try中拋出異常以後的代碼再也不執行,直接跳到catch中,catch中執行完成之後,再繼續執行catch以後的代碼

細節

  • 在catch中能夠提示錯誤信息,可是最重要的是解決異常,實在解決不了的時候再提示錯誤
  • Catch中也能夠再嵌套try…catch
  • 每一個try至少要有一個與之對應的catch,不能出現單獨的catch。另外try和catch 之間也不能有任何的代碼出現。
  • throw 關鍵字將觸發一次處理機制,是個語言結構不是函數,但必須給它傳遞一個對象做爲值

實例

<?php
   try {
   	$error = 'Always throw this error';
   	throw new Exception($error);   
   	//建立一個異常對象,經過throw語句拋出
   	echo 'Never executed';         
   	//從這裏開始,try代碼塊內的代碼將不會再被執行
   } catch (Exception $e) {
   	echo 'Caught exception:'.$e->getMessage()."\n";  
   	//輸出捕獲的異常消息
   }
   echo 'Hello World';       //程序沒有崩潰繼續向下執行

複製代碼

系統自帶的異常處理類

自定義異常

  • 自定義和內置的異常處理類在使用稅沒有太大的區別,只不過在自定義的異常處理類中,能夠調用爲具體的異常專門編寫的處理方法

捕獲多個異常

  • 在try代碼以後,必須至少給出一個catch代碼塊,也能夠將多個catch代碼塊與一個try代碼塊關聯使用。那麼使用多個catch就能夠捕獲不一樣的類所產生的異常。若是有多個catch代碼塊,傳遞給每個catch代碼塊的對象必須具備不一樣的類型,這樣PHP能夠找到須要進入哪個catch代碼塊。注意順序。

MYSQLI

mysqli優點及其簡介

  • 什麼是php的MySQLi擴展
    • php的MySQLi擴展又稱爲MySQL加強擴展。從PHP5.0開始可使用MySQLi, 是一個面嚮對象的技術(新加功能都會以對象形式添加)i:表示improve(改進)
  • MySQLi擴展相對於MySQL擴展的優點
    • MySQLi使用面向對象技術,但也支持過程化的使用方式
    • 功能增長了,支持事物,支持預處理語句等一些高級操做
    • Mysqli擴展支持mysql數據庫發佈的新特性,即便再發布新的功能,也能很好支持。
    • 效率更高,更穩定,更安全性

開啓mysqli擴展

  • 使用MySQLi,須要加載MySQLi擴展庫。
  • 請肯定 php.ini 開啓MySQLi庫擴展:
  • 檢測MySQLi庫擴展是否開啓
    • Phpinfo()
    • 使用 extension_loaded() 函數

bool extension_loaded('mysqli');

  • 檢測函數是否存在 function_exists('mysqli_connect')
  • 獲得當前已經開啓的擴展:get_loaded_extensions() 返回一個數組包含全部新開啓的擴展

MySQLi擴展面向對象數據庫的使用

  • 1 鏈接Mysqli數據庫服務器
    • 有兩種鏈接方式

判斷是否鏈接成功

3 設置字符集

$mysqli->set_charset("utf8")

設置數據庫編碼

4 執行SQL語句 執行查詢(select)語句

  • 錯誤號和錯誤信息
    • $mysqli->errno獲得上一部操做產生的錯誤信息
    • $mysqli-error的道上一步操做產生的額錯誤信息

執行非查詢語句

5 處理資源結果集

6-7 釋放結果集,關閉數據庫鏈接

  • $result->free_result() 釋放結果集
  • $mysqli->close()關閉鏈接

mysqli_stmt預處理類(推薦你使用的類)

和mysqli和mysqli_result相比的優勢

  • mysqli和mysqli_result類完成的功能,均可以使用mysqli_stmt完成
  • 效率上:高, 就是若是執行屢次相同的語句,只有語句數據不一樣, 由於將一條語句在服務器端準備好,而後將不一樣的值傳給服務器,再讓這條語句執行編譯一次,使用屢次
  • 安全上:SQL注入(? 佔位) ,後期傳的值不會當成SQL語句

效率高,安全,這是咱們使用mysqli_stmt的緣由,因此推薦你使用它

mysqli_stmt預處理類的成員方法

mysqli_stmt預處理類成員屬性

拓展 預處理機制(防止SQL語句惡意注入)

mysqli_stmt處理過程

  • 獲取預處理語句對象

    • 方式1:使用mysqli對象中的prepare()方法準備要執行的SQL語句,得到一個mysqli_stmt對象。但要將準備的SQL語句中,各有關參數替換爲佔位符號,一般使用問號(?)做爲佔位符號。
    $stmt=$mysqli->prepare(「insert into tableName values(?,?,?)」);
    複製代碼
    • 方式2:mysqli對象中的stmt_init()方法獲取一個mysqli_stmt對象。但獲取mysqli_stmt對象以後,還要經過該對象中的prepare()方法去準備一個要執行的SQL語句
    $stmt->prepare(「insert into tableName values(?,?,?)」);
    複製代碼
  • 綁定參數

    • 在bind_param()方法中,第一個參數是必需的,表示該方法中其後多個可選參數變量的數據類型。每一個參數的數據類型必須用相應的字符明確給出,表示綁定變量的數據類型字符
    • 類型有i-整型,d-浮點型,s-字符串,b-二進制
    • $stmt->bind_param(‘類型’,分別對應?的變量名);
  • 給綁定的變量賦值

  • 執行準備好的sql語句,成功時返回 TRUE , 或者在失敗時返回 FALSE 。

    • $stmt->execte($sql);
  • 處理操做的sql語句

    • $stmt->insert_id; //最後一次插入的id
    • $stmt->affected_rows; //最後一次操做影響的行數
  • 使用預處理語句處理SELECT查詢結果

$stmt->bind_result($result);
while($stmt->fetch()){綁定的變量}
//bool mysqli_stmt::fetch(void)
複製代碼
  • 釋放預處理結果$stmt->close();
  • 關閉mysql $mysqli->close();

使用預處理語句處理SELECT查詢結果

<?php
//獲取受影響行數 	
bool $stmt->store_result();//一次性將結果所有取出
$stmt->num_rows;//結果條數(先運行store_result)

// 處理查詢結果方式2	
$resObj=$stmt->get_result();//獲取結果集
$arr=$resObj->fetch_all(MYSQL_ASSOC);//取出全部記錄

// 指針移動到n(先運行store_result)
	$stmt->data_seek(n);
	$stmt->fetch();
?>
複製代碼

使用mysqli執行多條語句

  • bool mysqli::multi_query ( string $sql)

<?php
$sql ="select id,goodsname,price from yhshop_goods;";
$sql .=" select * from yhshop_admin;";
$res=$mysqli->multi_query($sql);
if($res){
     do{
	if($mysqli_result=$mysqli->store_result()){
	$row[]=$mysqli_result->fetch_all(MYSQLI_ASSOC);
                 }
    }while($mysqli->more_results()&&$mysqli->next_result());
    print_r($row);
}else{
       echo $mysqli->error; 
}

?>
複製代碼

使用MYSQLI完成事務處理

  • 事務處理 (多個SQL要完成的任務看爲是一個事務)一件事(有任何一個環節出錯,都整個事務撤消, 若是都成功纔去提交)

  • 目前只有InnoDB和BDB支持事務

  • 默認表都是自動提交的(autocommit)

  • 步驟

    • 1.關閉自動提交
    • 2.set autocommit=0
    • 3.開啓事務
    • 4.start transaction sql執行 commit/rollback

PDO

  • PDO的做用

    • PHP能夠處理各類數據庫系統,訪問不一樣的數據庫系統,其使用的PHP擴展函數也是不一樣的。這樣比較麻煩,更重要的是使得數據庫間的移植難以實現。
    • PDO(php data object)提供了一個數據庫訪問抽象層,爲php訪問數據庫定義了輕量級的、一致性的接口,不管你使用什麼數據庫,均可以經過一致的函數執行查詢和獲取數據,大大簡化了數據庫的操做,並可以屏蔽不一樣數據庫之間的差別,使用 PDO能夠很方便地進行跨數據庫程序的開發,以及不一樣數據庫間的移植
    • PDO能夠支持mysql,oracle,mssql,SQL Server等多種數據庫
  • 開啓PDO 擴展

    • 使用pdo,須要加載pdo擴展庫。請肯定 php.ini 開啓MySQLi庫擴展:
      • extension_dir = "F:/wamp/php-5.4.45/ext"
      • extension=php_pdo.dll
      • extension=php_pdo_mysql.dll
    • 重啓apache服務
    • 使用 extension_loaded() 函數能夠檢測MySQLi庫擴展是否開啓
      • bool extension_loaded('pdo_mysql');
  • 使用PDO操做數據庫

<?php
try {
    $dsn = "mysql:host=localhost;dbname=shop";
    // 用戶名
    $user = "root";
    // 數據庫密碼
    $pass = "root";
    // pdo 對象
    $options = array(
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
        PDO::ATTR_DEFAULT_FETCH_MODE => 2
    );
    $pdo = new PDO($dsn, $user, $pass, $options);


}
catch (PDOException $e){
    echo $e->getMessage();
}

複製代碼
  • PDO對象的成員方法

  • 與PDO鏈接有關的選項

  • 設置使用異常的錯誤模式

  • 設置編碼格式
    • 設置數據庫編碼$pdo->exec('set names utf8');
  • 執行SQL語句

  • 處理非查詢SQL語句

    • 在插入記錄時,返回最後插入記錄的主鍵id$pdo->lastinsertid()
  • PDOStatement對象

    • PDOStatement對象不是經過new關鍵字實例化出來的,而是經過執行PDO對象中prepare()方法,在數據庫服務器中準備好一個預處理的SQL語句後直接返回的。
    • 若是經過PDO對象的query()方法返回的PDOStatement 對象只表明是一個結果集對象。而經過prepare()方法產生的PDOStatement對象則爲一個查詢對象,能定義和執行參數化的SQL命令
  • PDOStatement對象成員方法

  • 處理資源結果集

PDO預處理

  • 執行預處理方式2

  • bindColumn()方法

防止SQL注入

  • 方式一:quote()方法防止sql注入
    • PDO對象中quote方法返回帶引號的字符串,能夠過濾來自輸入中的特殊字符(用反斜線轉移)
<?php
   
   $username = $_POST['username'];
   $username=$pdo->quote($username);//自動爲字符串加上引號<br>
   $sql='select * from uesr where username={$username}'//這裏$username就不用加引號了
   $stmt=$pdo->query($sql);//PDOStatement對象的方法:rowCount():對於select操做返回的結果集中記錄的條數,對於INSERT、UPDATE、DELETE返回受影響的記錄的條數
   echo $stmt->rowCount();


   
   ?>
複製代碼
  • 方式二:使用prepare()和execute()預處理sql注入(推薦)
$pdo=new PDO('mysql:host=localhost;dbname=phptest','root','123456');	
$sql="INSERT stu(name,classid) VALUES(:username,:classid)";
$stmt=$pdo->prepare($sql);	//返回stmt對象
$stmt->bindParam(":username",$username,PDO::PARAM_STR);
$stmt->bindParam(":classid",$class,PDO::PARAM_STR);//將變量$class的引用綁定到查詢的名字參數‘:class’中
$username=king;$class='php05';$stmt->execute();

$pdo=new PDO('mysql:host=localhost;dbname=phptest','root','123456');	
$sql="INSERT stu(name,classid) VALUES(?,?)";//一個(沒有傳值的)SQL語句
$stmt=$pdo->prepare($sql);//準備查詢語句	
$stmt->bindParam(1,$username,PDO::PARAM_STR);
$stmt->bindParam(2,$class,PDO::PARAM_STR);//將變量$class綁定到查詢的第二個問號參數中
$username='lily';$class='php03';  //爲變量賦值
$stmt->execute();  //執行參數綁定值後的準備語句
複製代碼

PDO事務處理

  • 事務
    • 事務:就是把不少事情當作一件事情來作,要麼就都成功,要麼就都失敗
    • 以保證數據的一致性和完整性
    • 將多條sql操做(增刪改)做爲一個操做單元,要麼都成功,要麼都失敗。
  • 被操做的表必須是innoDB類型
  • 事務處理
Mysql>set autocommit=0;//關閉自動提交
Mysql>start transaction;//開啓事務
Mysql>commit;//提交
Mysql>rollback;//回滾

複製代碼
//1.關閉自動提交
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0);
//2.開啓事務:
$pdo->beginTransaction();
//提交一個事務:
$pdo->commit();
//回滾一個事務:
$pdo->rollback();
//檢測是否在一個事務內:
inTransaction()

複製代碼
try{
$dsn='mysql:host=localhost;dbname=phptest';
$username='root';$passwd='123456';
$options=array(PDO::ATTR_AUTOCOMMIT=>0);
$pdo=new PDO($dsn, $username, $passwd, $options);		
$pdo->beginTransaction();//開啓事務
 $sql='UPDATE userAccount SET money=money-2000 WHERE username="zs"';
$res1=$pdo->exec($sql);
if($res1==0){throw new PDOException(zs轉帳失敗'); } $res2=$pdo->exec('UPDATE userAccount SET money=money+2000 WHERE username="king"'); if($res2==0){throw new PDOException('king 接收失敗');} $pdo->commit();//提交事務 }catch(PDOException $e){ $pdo->rollBack(); //回滾事務 echo $e->getMessage(); } 複製代碼

memcache

memcache簡介

  • Memcache是一個高性能的分佈式的內存對象緩存系統。是個開源的軟件,能夠經過簡單的方法,管理數據庫在內存中的存取。簡單的說就是緩存數據庫查詢結果(數據)到內存中,而後從內存中讀取,從而大大提升讀取速度,減小數據庫訪問次數,以提升動態web應用的速度,提升可擴展性

  • 怎麼理解memcache?====> Memcache 是隻有一張表的數據庫,這張表有兩個字段分別是主鍵key 和value,value就是咱們要保存的數據,key就是這個數據的id,用來保證咱們查找時候的惟一性

memcache使用場景

  • 非持久化存儲:對數據存儲要求不高,服務中止後,裏面的數據就會丟失
  • 分佈式存儲:單臺數據的內存容量有限,能夠在多個電腦上安裝memcache 服務
  • Key/Value存儲:須要緩存的對象或數據以「key/value」對的形式保存在服務器端

Memcache在WEB中的應用

  • MemCache緩存系統最主要的就是爲了提升動態網頁應用,分擔數據庫檢索的壓力。對於網站流量比較大的,可使用memcache緩解數據庫的壓力,主要的焦點集中在如下兩個方面:
    1. 使用MemCache做爲中間緩存層減小數據庫的壓力。
    2. MemCache分佈式的應用

memcache運行圖

  • memcache下載安裝
// memcache 屬於一種非關係型數據庫 mysql 關係型數據庫
// memcache 屬於nosql的一種 not only sql      redis  ,mongodb

// 安裝memcache 完整過程
// 1.下載memcache windows 安裝包 下載地址: http://static.runoob.com/download/memcached-1.4.5-amd64.zip

// 2.安裝包解壓到任意磁盤下,個人位置 在E:/phpstudy/memcached.exe .dll

// 3. cmd 安裝 memcached.exe -d install /uninstall  memcached.exe -d start  /stop

// 4. 使用客戶端管理工具來鏈接memcache  telnet(windows 命令) 127.0.0.1(服務器地址 localhost) 11211 (端口)

// 5. windows 裏開啓telnet 客戶端的命令

// 6. 開啓步驟  計算-->控制面板-->程序-->打開/關閉windows功能-->telnet 客戶端 勾選開啓

// 7.add 鍵名 標識  有效期(秒數,0表示永不過時) 長度  /  add name 0 0 8   xiaoming
複製代碼
  • 利用telnet鏈接到memcache
    • telnet 127.0.0.1 //鏈接
    • quit //退出
    • 輸入stats狀態信息

  • 數據管理命令
    • 格式: <命令> <鍵> <標記> <有效期> <數據長度> 值

stats items   查看標記
stats cachedump 1 0


複製代碼

PHP操做memcache

  • 在php中安裝memcache拓展詳情點擊 blog.csdn.net/ad132126/ar…

  • 實例化memcache類 $memcache=new memcache;

  • 鏈接memcache服務器

參數1:主機(必寫);
參數2:Memcached服務的端口號,默認11211(可選)
複製代碼
  • 關閉服務器鏈接 $memcache->close()

向memcache服務中添加和重置數據

memcache->add("test1","This is a test",false,0);
$memcache->add("test2",array("one","two"),MEMCACHE_COMPRESSED,60*60*24*30);
$memcache->add("test3",new Test(),MEMCACHE_COMPRESSED,time()+60*60*24*31);

複製代碼

向memcache服務中獲取與刪除數據

demo memcache在開發中的實際應用

  • 在項目了最多見的Memcache應用就是緩存從數據庫中查詢的數據結果,以及保存回話控制信息(session)
  • 設計的原則,這要數據庫中的記錄沒有被改變,就不須要從新連接數據庫反覆執行查詢語句,相同的查詢結果都應該從緩存服務器中獲取
function select($sql,Memcache $memcache){
	$key=md5($sql);  //md5 Sql命令做爲memcache 的惟一標識符
	$data=$memcache->get($key);
	if(!$data){
		try{
$pdo=new PDO("mysql:host=localhost;dbname=php","root","root");
		}catch(PDOException $e){
		die('鏈接失敗');
		}
		$stmt=$pdo->prepare($sql);
		$stmt->execute();

		$data=$stmt->fetchAll(PDO::FETCH_ASSOC);
		$memcache->add($key,$data,MEMCACHE_COMPRESSED,0);
	}
	return $data;
}
$memcache=new Memcache;
$memcache->connect('127.0.0.1',11211);
$data=select("select * from stu",$memcache);
var_dump($data);

![](https://user-gold-cdn.xitu.io/2019/9/16/16d3a6f3a5b8b9ed?w=507&h=438&f=png&s=4769)

複製代碼
  • 分佈式memcache
    • 若是有多臺memcache服務器最好使用Memcache::addServer()方法來連接服務器端,不能用Memcache::connect()方法進行連接
    • 建立分佈式memcache服務器鏈接池
$memcache = new Memcache;
$memcache->addServer('172.16.1.1', 11211);
$memcache->addServer('172.16.1.2', 11211);
$memcache->addServer('172.16.1.3', 11211);
複製代碼
  • memcache實例
//1. 建立對象 
	$mem = new Memcache();
 //2. 添加服務 
$mem->addServer("192.168.150.250",11211);
 $mem->addServer("192.168.150.138",11211);
 $mem->addServer("192.168.112.128",11211); 
//3. 放置信息 
$mem->add("mystr","hello memcache!",MEMCACHE_COMPRESSED,0); 
$mem->add("myarray",array(10,20,30,40),MEMCACHE_COMPRESSED,0); 
$mem->add("myob",new Stu(),MEMCACHE_COMPRESSED,0); 
//4. 獲取信息
 echo $mem->get("mystr")."<br/>";
 var_dump($mem->get('myarray')); 
echo "<br/>"; 
$mem->get("myob")->getinfo();


複製代碼

高級SESSION

  • session的存儲方式
    • session默認是存在文件裏的,文件的讀取速度相對來講比較慢,而且文件多的時候會形成文件操做的嚴重滯後.並且自己session機制不能跨機,而訪問量大的系統一般都是多臺web服務器進行併發處理,若是每臺web服務器都各自獨立的處理session,就不可能達到跟蹤用戶的目的
    • 解決方法:自定義Session的存儲方式。
      • 將session信息使用NFS和SAMBA等共享技術保存到其餘服務中
      • 使用數據庫來保存Session 信息
      • 使用memcached 來進行Session 存儲.
  • 改變session的存儲方式
    • 在PHP.INI中給咱們提供了一個配置項
      • session.save_handler = files(保存在文件中)
      • session.save_handler = memcache(保存在memcache中)
      • session.save_handler = user(用戶自定義,結合函數一塊兒使用)
      • session_set_save_handler()

  • 自定義處理方式步驟
    • 1)php.ini中設置session.Save_handler=user
    • 2)瞭解session6個生命週期
    • 3)將這六個部分給php註冊上去
      • 自定義的方式:要求咱們根據session 的生命週期,自定義處理函數不然會報錯。須要告訴系統各個時期自定義的函數,就是須要註冊這些函數,經過session_set_save_handler()函數,讓php本身處理session時,按照這個函數指定的週期來完成。
    • 4)Session_start()以前註冊這六個部分。

session_set_save_handler()

bool session_set_save_handler ( callable $open , 
callable $close , callable $read , callable $write ,
callable $destroy , callable $gc [, callable $create_sid ] )
複製代碼
  • session_set_save_handler() 設置用戶自定義 會話存儲函數。 若是想使用 PHP 內置的會話存儲機制以外的方式, 可使用本函數。 例如,能夠自定義會話存儲函數來將會話數據存儲到數據庫。這個函數共須要6個回調函數做爲必選參數,分別表明了session生命週期中的6個過程,用戶經過自定義每一個函數,來設置session週期中每一個環節的信息處理

  • 參數

自定義session存入文件中

使用數據庫處理session信息

  • 使用數據包處理Session信息,至少包含三個字段(SessionId,修改時間,session 內容信息)
create table session(
sid char(32) not null default '',
update_time int not null default 0,
data text,
primary key(sid)
);

複製代碼
  • session自定義存入數據庫中

session自定義存入memcache中

相關文章
相關標籤/搜索