PHP面向对象

创建类

<?php
class fei{
    public $name='xiaoming';//类的属性
    //类的方法
    public function fly() {
        echo "fly";
    }
}

//类的调用
$ff = new fei();
echo $ff -> name;
$ff -> fly();
?>
  1. 类名不区分大小写,但必须认为区分(Linux严格区分),尽量使用大驼峰法命名
  2. php5.6以后属性可以使用表达式

知识点补充:数组

定义数组使用array('key'=>'value',...)

打印出数组:print_r()

取数组的某个值,用echo $arr['003']

<?php
 //声明一个数组
 $arr = array('001'=>'aaa','002'=>'bbb','003'=>'cccc');
 
 print_r($arr);
 echo $arr['003'];
?>

数组的key可以是字符串,此时数组为关联数组

$arr2 = array(‘name’=>’aaa’,’age’=>’15’,…);

二维数组,多维数组

$arr=array('name'=>'aaa','hobby'=>array('football','badminton','season'=>array('春','夏','秋','冬'));

var_dump():用于显示对象内部数据结构,如果变量存在但值为空,返回false,没有变量返回NULL

类和对象的关系

  1. new一个对象后,属性在内存中产生
  2. 方法只放方法名,不放方法体

this的使用

this用于调用对象中的变量,谁调用this就代表该对象

<?php
class Ren{
    public $name="小铭";
    public $work="6666";

    public function code(){
        echo $this ->name.'写php';
    }
}

$ren = new Ren();
$ren ->name ='梓铭';
$ren->code();
?>

封装MySQL类

知识点补充:mysql_fetch_assoc()函数

该函数用于从结果集取得一行作为关联数组,返回一个数组,用关键字索引取值

MySQL的封装

<?php
class Mysql{
    public $link;
    public function connect(){
        $cfg = array(
        'host'=>'localhost',
        'user'=>'xiao_ming',
        'ps'=>'zm19980225',
        'db'=>'oo',
        'charset'=>'utf-8'
        );
        $this->link = mysqli_connect($cfg['host'],$cfg['user'],$cfg['ps'],$cfg['db']);
    }
    
    //构造方法
    public function __construct(){
        $this ->connect();
    }
    
    public function query($sql){
        return mysqli_query($this->link,$sql);
    }
    
    public function getAll($sql){
        $data=array();
        $res=$this->query($sql);
        while($row = mysqli_fetch_assoc($res)){
            $data[]=$row;
        }
        return $data;
    }
}

$mysql = new Mysql();
$a = $mysql->getAll('select * from object_oriented');
var_dump($a);
?>

构造方法:类一旦被实例化,就会被调用

使用__construct()作为函数名

<?php
class Human{
    //构造方法
    class function __construct(){
        echo 'aaa';
    }
}
new Human;
?>

析构方法:对象被销毁时,才会被调用

总是会被最后才调用,不管在什么位置,使用__destruct()作为函数名

<?php
class Human{
    //析构方法
    class function __destruct(){
        echo 'bbb';
    }
}
new Human;
?>

对象何时被销毁:

  1. 存储对象的变量被赋值为其他值
  2. 变量被unset
  3. 页面结束时,程序执行到最后时

构造、析构方法时,若需要传递参数,直接在new对象的时候传

<?php
class Human{
    public function __construct($a,$b){
        echo $a,$b;
    }
}

new Human('aaa','bbb');
?>

类的封装性

封装:即不允许外部调用,要调用封装函数,只能开放一个接口,使用protected

类的继承

继承:子类可以继承父类的属性及方法,并允许覆盖父类的方法或新增方法

继承的语法:使用extends

class ParClass{
   ...
}
class SubClass extends ParClass {
    ...
}

final类不能被继承,final方法不能被重写

使用final的时候直接在前面加上final

三种权限:

public: 外部、自身、子类都可以调用

protected:不允许外部调用,自身和子类可以调用

private: 只能够自身调用,外部和子类都不可以调用

静态属性和静态方法

1.静态方法:可以不用实例化就可以调用该方法,使用static

类名::方法

  1. 静态属性:不用实例化就可以调用该属性,使用static

    类名::属性

类常量

在类中定义常量时,使用const,在类中引用该变量时,使用类名::常量名

单例模式

只能造出一个对象

<?PHP
//单例模式
class Single{
    public $rand;
    static public $oc=null;

    //使用final防止被子类更改
    final protected function __construct(){
        $this->rand = mt_rand(100000,99999999);
    }

    /*使用static是方便外部调用,引用如果外部new一个新的对象,
    会导致外部自动调用有protected的__construct函数失败*/
    static public function GetIns(){

        //使用条件判断使其最终只能产生一个随机数
        if(Single::$oc ` null){
            Single::$oc = new Single();
        }
        return Single::$oc;
    }
}

class Test extends Single{};
var_dump(Test::GetIns());
var_dump(Test::GetIns());
?>

self和parent

  1. self:表示类自己
  2. parent:表示父类
<?php
class Par{
    public function __construct(){
        echo rand(111,999999);
    }
}

class Son extends Par{
    public function __construct(){
        parent::__construct();
        echo 1;
    }
}
new Son();
?>

魔术方法

魔术方法:在某种场景下能够自动调用的方法

不可见属性:未定义或者受保护(外部不能访问的)

  1. __construct()
  2. __destruct()
  3. __get(属性名):当读取对象的一个不可见属性时,自动调用,并返回值
  4. __set(属性名,属性值): 当对一个不可见的属性赋值时,自动调用
  5. __isset(属性名): 当用isset,或empty判断一个不可见属性时,自动调用
  6. __unset(属性名): 当unset一个不可见属性时,自动调用

自动加载

某个场景下自动调用某个函数即为自动加载

spl_autoload_register('自动调用的函数名'):该函数把某个函数注册为自动加载函数,当程序调用的类不存在时,会自动调用参数函数

?php
function myload($class){
    include './'.$class.'class.php';
}

//把一个函数注册为自动触发函数
spl_autoload_register('myload');//当new的类不存在时,触发参数函数

new Mysql();
?>

抽象类

abstract:用于声明这是一个抽象类、抽象方法(抽象方法不需要方法体)

  • 类继承抽象类时必须对类中的抽象方法一一加以实现
  • 抽象类不能被实例化
  • 抽象类中可以有已经实现的方法,但只有一个抽象方法,就是抽象类
<?php
abstract class aDB{
   abstract public function getAll($sql);

   abstract public function putAll($sql);
}

//继承抽象类并实现抽象方法
class Mysql extends aDB{
   public function getAll($sql){

   }
   public function putAll($sql){
       
   }
}
?>

接口

  • 接口用于定义抽象的方法
  • 使用interface表示接口
  • 使用implements表示实现接口
  • 接口本身就是抽象的,方法前不用加abstract
  • 接口里的方法,只能是public
  • 类可以同时实现多个接口
<?php
interface flyer {
    public function fly($oil,$height);
}

interface runer {
    public function run($cicle,$dir);
}

interface water {
    public function swim($dir);
}

class Super implements flyer,runer{
    public function fly($oil,$height){
        echo "I am flying.";
    }
    public function run($circle,$dir){
        echo "I am running.";
    }
}

$a = new Super;
$a ->fly('a','b');
$a ->run('a','b');
?>

异常

  • 抛出异常:使用throw new Exception(“自定义语句”,数字)
  • 处理异常:使用try{ } catch(Exception $a) { }

知识点补充

获取文件位置:使用getFlie()函数

获取位置行数:使用getLine()函数

<?php
function t1(){
    if (rand(1,10) > 5){
    //抛出错误
        throw new Exception('凉凉',1); 
    }
    else{
        return t2();
    }
}

function t2(){
    if(rand(1,10)>5){
        throw new Exception('暖暖',2);
    }
    else{
        return t3();
    }
}

function t3(){
    if(rand(1,10)>5){
        throw new Exception('高考加油',3);
    }
    else{
        return true;
    }
}

try{
    var_dump(t1());
}
//获取错误
catch (Exception $e){
    echo '文件:'.$e->getFile();
    echo '行数:'.$e->getLine();
    echo $e->getMessage();
}
?>

命名空间

namespace创建一个命名空间,其下面类就在这个命名空间下,在某个命名空间下使用同名类,优先使用本类。要用别的命名空间的同名类的时候,要先require/include然后使用路径或用use,然后起个别名

  • namespace的声明必须在执行代码第一行
  • 声明后,其后的类、函数,都被封锁在命名空间下
  • require/include其他带有命名空间的页面,自身的空间,并没有受干扰
  • 如果想明确的使用某空间下的类, 可以从根空间,逐步寻找,如\zixueit\Class();
  • 如果频繁用某个空间下的类,可以先use声明
  • 自动加载函数的参数,包含 “空间路径\类名”
//26.php

//开创命名空间
namespace flower;
include '26_1.php';//包含别的文件
class Leaf{
    public function __construct(){
        echo 11;
    }
}

//使用别的命名空间里的同名类,先起个别名
use tree\Leaf as t;
new t();





//26_1.php

//namespace tree;
class Leaf{
    public function __construct(){
        echo 22;
    }
}

延迟绑定

<?php
class Parents{
    public static function a(){
        echo "我是傅雷";
    }
    public static function b(){
        self::a();//此处打印傅雷
        static ::a();//延迟绑定,直到调用才知道是哪个类调用
    }
}

class Son extends Parents{
    public static function a(){
        echo "我是傅聪";
    }
}

Son::b();//此处会打印傅雷
?>

超载的static

  1. 函数内声明静态变量用
function S1(){

    //仅在局部中存在,但其值并不丢失,下次调用仍是上次结束时的值
    static $a1=1;
    $a1 ++;
}
  1. 声明类静态属性和静态方法
  2. 延迟绑定

封装数据库

所需函数知识点补充:

  • array_key($data):用于获取数组的键的内容
  • array_values($data):用于获取数组的值的内容
  • trim(数组,去掉的内容):两个参数,去掉数组中指定的内容,可以使用ltrim和rtrim分别表示去掉最左边和最后边的指定内容
/*conflig.php*/
<?php
$cfg = array(
    'host'=>'localhost',
    'user'=>'xiao_ming',
    'pwd'=>'zm19980225',
    'db'=>'oo',
    'charset'=>'utf-8'
    );
    return $cfg;
?>




/* Mysql.php */
<?php
abstract class aDB {
    
    /**
    *连接数据库,从配置文件读取配置信息
    */
    abstract public function conn();
    
    /**
    *发送query查询
    *@return mixed
    */
    abstract public function query($sql);
    
    /**
    *查询多行数据
    *@return array
    */
    abstract public function getAll($sql);
        
    /**
    *单行数据
    *@return array
    */
    abstract public function getRow($sql);
        
    /**
    *查询单个数据 如count(*)
    *@return mixed
    */
    abstract public function getOne($sql);
        
    /**
    *自动创建sql并执行
    *@param array $data 关联数组 键/值与表的列/值相对应
    *@param string $table 表名字
    *@param string $act 动作/update/insert
    *@param string $where 条件,用于update
    *@return int 新插入的行的主键值或影响行数
    */
    abstract public function Exce($data,$table,$act='insert',$where='0');

    /**
    * 返回上一条insert语句产生的主键值
    */
    abstract public function LastId();

    /**
    *返回上一条语句影响的行数
    */
    abstract public function affectRows();
}

class Mysql extends aDB{
    public $link;
    //自动连接
    public function __construct(){
        $this->conn();
    }

    /**
    *连接数据库,从配置文件读取配置信息
    */
    public function conn(){
        $cfg = include './conflig.php';
        //连接数据库的面向对象风格
        $this->link = new Mysqli($cfg['host'],$cfg['user'],$cfg['pwd'],$cfg['db']);
        $this->query('set name' . $cfg['charset']);

    }
    
    /**
    *发送query查询
    *@return mixed
    */
    public function query($sql){
        //面向对象的风格,直接使用上面new的mysqli类的query()
        return $this->link->query($sql);//只需要一个参数,不用$link
    }
    
    /**
    *查询多行数据
    *@return array
    */
    public function getAll($sql){
        $data=[];
        $result = $this->query($sql);//query()会返回一个对象
        //面向对象风格,直接调用query返回类里的方法
        while ($row = $result->fetch_assoc()){
            $data[]=$row;
        }
        return $data;
    }
        
    /**
    *单行数据
    *@return array
    */
    public function getRow($sql){
        $result = $this->query($sql);
        $row = $result->fetch_assoc();
        return $row;
    }
        
    /**
    *查询单个数据 如count(*)
    *@return mixed
    */
    public function getOne($sql){
        $result = $this->query($sql);
        //fetch_row()每次取一行的内容放入数组
        $row = $result->fetch_row()[1];
        return $row;
    }
        
    /**
    *自动创建sql并执行
    *@param array $data 关联数组 键/值与表的列/值相对应
    *@param string $table 表名字
    *@param string $act 动作/update/insert
    *@param string $where 条件,用于update
    *@return int 新插入的行的主键值或影响行数
    */
    public function Exce($data,$table,$act='insert',$where='0'){
        if($act ` 'insert'){
            //插入语句
            $sql = 'insert into ' . $table .' (';
            //拆分数组
            $sql .= implode(',',array_keys($data)).') ';//函数获取数组的键
            $sql .= "values ('";
            $sql .= implode("','",array_values($data))."')"; //函数获取数组的值
            $this ->query($sql);
            return $this->LastId(); 
        }else{
            //update
            $sql = 'update '. $table . ' set  ';
            foreach ($data as $k =>$v) {
                $sql.= $k . "='".$v."',";
            }
            $sql = rtrim($sql,',');//去掉最后的逗号
            $sql .= " where $where";
            $this ->query($sql);
            return $this->affectRows();
        }
    }

    /**
    * 返回上一条insert语句产生的主键值
    */
    public function LastId(){
        //直接调用insert_id即可得到插入的主键的值
        return  $this->link->insert_id;
    }

    /**
    *返回上一条语句影响的行数
    */
    public function affectRows(){
        //直接调用affected_rows即可得到影响的行数
        return $this->link->affected_rows;
    }
}

$mysql = new Mysql();
$a = $mysql->Exce(['name'=>'原始'],'object_oriented','update','id>3');
var_dump($a);
$b = $mysql->getAll("select * from object_oriented");
$c = $mysql->getOne("select * from object_oriented");
$d = $mysql->getRow("select * from object_oriented");
var_dump($b);
var_dump($c);
var_dump($d);
?>