PHP面向对象
创建类
<?php
class fei{
public $name='xiaoming';//类的属性
//类的方法
public function fly() {
echo "fly";
}
}
//类的调用
$ff = new fei();
echo $ff -> name;
$ff -> fly();
?>
- 类名不区分大小写,但必须认为区分(Linux严格区分),尽量使用大驼峰法命名
- 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
类和对象的关系
- new一个对象后,属性在内存中产生
- 方法只放方法名,不放方法体
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;
?>
对象何时被销毁:
- 存储对象的变量被赋值为其他值
- 变量被unset
- 页面结束时,程序执行到最后时
构造、析构方法时,若需要传递参数,直接在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
类名::方法
- 静态属性:不用实例化就可以调用该属性,使用
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
- self:表示类自己
- parent:表示父类
<?php
class Par{
public function __construct(){
echo rand(111,999999);
}
}
class Son extends Par{
public function __construct(){
parent::__construct();
echo 1;
}
}
new Son();
?>
魔术方法
魔术方法:在某种场景下能够自动调用的方法
不可见属性:未定义或者受保护(外部不能访问的)
- __construct()
- __destruct()
- __get(属性名):当读取对象的一个
不可见属性
时,自动调用,并返回值 - __set(属性名,属性值): 当对一个
不可见的属性
赋值时,自动调用 - __isset(属性名): 当用isset,或empty判断一个
不可见属性
时,自动调用 - __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
- 函数内声明静态变量用
function S1(){
//仅在局部中存在,但其值并不丢失,下次调用仍是上次结束时的值
static $a1=1;
$a1 ++;
}
- 声明类静态属性和静态方法
- 延迟绑定
封装数据库
所需函数知识点补充:
- 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);
?>