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);
?>