PHP面向对象学习笔记 - JunMo博客

JunMo的博客

2019
记录生活
首页 » 学习笔记 » PHP面向对象学习笔记

PHP面向对象学习笔记

1.第一个类

//类的声明
class Test
{
	//类的方法
	function hello()
	{
		echo 'hello';
	}
}

//实例化对象
$test=new Test();

//调用对象中的方法
$test->hello();

2.属性和方法

//类的声明
class Test
{
	//属性
	public $name='JunMo';
	
	//类的方法
	function hello()
	{
		echo 'hello';
	}
}

//实例化对象
$test=new Test();

//获取属性值
echo $test->name;

//调用对象中的方法
$test->hello();

3.类的语法

//类的声明,不区分大小写
class Test
{
	//属性名,调用时不用加$
	public $name='JunMo';
	
	//类的方法
	function hello()
	{
		echo 'hello';
	}
}

//不区分大小写,人为区分大小写
$test=new Test();

//获取属性值
echo $test->name;

//调用对象中的方法
$test->hello();

4.类与对象的关系

//类的声明,不区分大小写
class Test
{
	//属性名,调用时不用加$
	public $name='JunMo';
	
	//类的方法
	function hello()
	{
		echo 'hello';
	}
}

//new一个对象时,内存会开放一块空间,存放属性
$L1=new Test();
$L2=new Test();

//给L1中的属性重新赋值,类中的属性值不变,改变的是新开辟空间的属性
$L1->name='Jun';
echo $L1->name;

//方法调用,执行类中的方法,但是PHP内部会记录是哪个对象在调用方法
$L2->hello();

5.this

谁调用就是谁,$this是一个虚拟变量,专门指当前调用的对象

class Test
{
	public $name='JunMo';
	
	public function im()
	{
		echo '我是'.$this->name;
	}
}
$test=new Test();

$test->im();

6.封装mysql类

class Mysql
{
	public function conn()
	{
		$config=array
		(
		'host'=>'localhost',
		'user'=>'root',
		'pass'=>'',
		'db'=>'test',
		'charset'=>'utf8'
		);
		
		return mysqli_connect($config['host'],$config['user'],$config['pass'],$config['db']);
	}
	
	public function query($sql)
	{
		mysqli_query($this->conn(),$sql);
	}	
	
	public function getrow($sql)
	{
		$re=mysqli_query($this->conn(),$sql);
		
		$data=array();
		
		while($row=mysqli_fetch_assoc($re))
		{
			$data[]=$row;
		}
		
		return $data;
	}
}

$db=new Mysql();

$row=$db->getrow('select * from goods');

var_dump($row);

7.构造方法与析构方法

构造方法 : __construct()

是指在new 对象时,自动触发的方法。

class Test
{
	public function __construct()
	{
		echo 'www.mo60.cn';
	}
}

$test=new Test();//打印www.mo60.cn

利用此方法可以完成一些初始化工作.

比如:mysql类中自动连接与选库

构造方法传参 在创建实例时,可以传递参数,如:

class Test
{
	public function __construct($name)
	{
		echo $name;
	}
}

$test=new Test('JunMo');

析构方法 :

__destruct() 在对象销毁时,自动触发

class Test
{
	public $name;
	public function __construct($name)
	{
		$this->name=$name;
		echo $name;
	}

	function __destruct() 
	{
	echo '<br/>'.$this->name , ' bye<br />';
	}
	
}

$test=new Test('JunMo');

对象什么时间被"销毁"?

存储对象的变量被赋值为其他值 ,

或变量被 unset,

或页面结束时 , 都会被销毁

构造方法的旧式声明

一个和类名同名的方法,被理解为构造方法; 老旧的PHP代码中会遇到;遇到时认识即可;

8.类的封装性

封装 : 即禁止某些方法/属性 , 不充许外部调用 .
并开放部分方法 , 来间接调用 .
比如 银行的 ATM, 你可以输入密码 " 检测 " 自己的密码是否正确 ,
但不能 " 查询 " 自己的密码 . 代码 :

class Login
{
	protected function getPass()
	{
		return 'JunMo';
	}
	public function checkPass($pass)
	{
		return $pass==$this->getPass();
	}
}

$test=new Login();

if($test->checkPass('JunMo'))
{
	echo 1;
}
else
{
	echo 0;
}

10.类的继承性

新浪 SAE 平台 , 给我们提供了 SaeMySQL 类 , 我们可以直接使用 .
但我如果觉得这个类的某个方法不好 , 或者缺少某个方法 , 怎么办 ?
我们不能定义同名函数来覆盖 , 因为 PHP 不允许函数重名

继承的好处 :
子类可以继承父类的属性及方法 , 并允许覆盖父类的方法或新增方法.
通过自然界的比喻就是,通过"进化"来获得新特性, 同时不影响旧物种.

//声明类A
class A
{
	//声明属性
	public $num1=10;
	public $num2=20;
	
	//声明方法
	public function test()
	{
		if($this->num1>$this->num2)
		{
			echo "num1大";
		}
		else
		{
			$this->error();
		}
	}

	public function error()
	{
		echo 'num2大';
	}
		
}

//B类继承A类
class B extends A
{
	//重写A类中的方法不影响其他方法
	public function error()
	{
		echo 'num小';
	}
}


//实例化B类
$Jun=new B();

//调用A类中的方法
$Jun->test();

PHP 是单继承的:子类只能继承一个父类

11.final类和final方法

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

//此类不能继承
final Class Test1
{
}

Class Test2
{
	//final 方法不能被子类重写,但是能调用
	final public function Jun()
	{
		echo '这个方法不能被重写';
	}
}

class Test3 extends Test2
{
	
}

$Test=new Test3();

//可以调用父类的方法但是不能重写
$Test->Jun();

12.3种权限详解

Class Test
{
	//公有外部内部都可以调用
	public $num1=1000;
	
	//受保护的只允许内部调用子类可以调用
	protected $num2=500;
	
	//私有的只允许自己调用
	private $num3=100;
}

Class Test2 extends Test
{
	public function T()
	{
		echo $this->num1;
		
		echo $this->num2;
		
		//私有的不允许子类调用
		//echo $this->num3;
		
	}
}

$Test=new Test2();


//公有属性外部可以调用
echo $Test->num1;

//受保护的外部不能调用
//echo $Test->$num2;

//私人的外部能不能调用
//echo $Test->$num3

$Test->T();
  public protected private
外部 Y N N
子类中 Y Y N
本类中 Y Y Y

 13.静态属性及方法

如果某个类 , 没有属性我们没有必要实例化对象.我们有什么必要再造对象。

Class Test
{
	//静态属性
	static public $name='JunMo';
	
	//静态方法
	static public function cheng($num1,$num2)
	{
		return $num1*$num2;
	}
}

//调用静态方法
echo Test::cheng(5,5);

//调用静态属性
echo Test::$name;

14.类常量

define('A',666);

Class Test
{

public function A()
{
	echo A;//调用常量
}
	
	//类常量,只在类内部起作用
	const A=777;
	
	public function cheng($num)
	{
		echo Test::A * $num;//调用类常量
	}
}

$test =new Test();

$test->A();

$test->cheng(5);

15.self与parent

$this 本对象

self 本类

parent 父类

Class Test
{
	//定义属性
	public static $num;
	public static $num2;
	
	public function printf()
	{
		//使用self输出变量
		echo self::$num=rand(1,9999).'<br/>';
	}
}

class Test2 extends Test
{
	public function printf()
	{
		parent::printf();//使用父类中的方法
		echo self::$num2=rand(1,100);
	}
	
}

$test=new Test2();

$test->printf();

16.单例模式

单个实例对象(只能造出一个对象)

Class Test
{
	
  private static $T=null;
  
  // 构造方法,设置为private,不允许通过new获得对象实例
  private final function __construct()
  {
	$this->rand=rand(1,99999999);
  }
  
  // 获取实例方法
	public static function getRand()
	{
		if(self::$T==null)
		{
			self::$T=new Test();
		}
		return self::$T;
	}
} 

$num=Test::getRand();


print_r($num);

17.魔术方法

魔术方法:某种场景下,能够自动调用的方法
如: __construct、 __destruct、__set、 __get、 __isset、__unset、__call
__construct(): 构造方法,new 实例时,自动调用
__destruct(): 析构方法,对象销毁时自动调用
__get(属性名): 当读取对象的一个不可见属性时,自动调用,并返回值
不可见: 未定义或无权访问时
__set(属性名,属性值): 当对一个不可见的属性赋值时,自动调用
__isset(属性名): 当用isset,或empty判断一个不可见属性时,自动调用
__unset(属性名): 当unset一个不可见属性时,自动调用

class Test
{
	//当读取一个不可及的属性,会把触发然后属性名打印出来
	public function __get($a)
	{
		echo $a;
	}
	
	//给不存在的属性赋值时会触发
	public function __set($a,$b)
	{
		echo '属性名'.$a.'属性值'.$b;
	}

	//当用isset,或empty判断一个不可见属性时,自动调用
	public function __isset($a)
	{
		echo $a;
	}

	// 当unset一个不可见属性时,自动调用
	public function __unset($a)
	{
		echo $a;
	}


}

$test=new Test();//实例化

$test->Test1;//调用不存在属性

$test->Test2=9999;//给不存在的属性赋值

isset($test->Test3);//isset判断不存在的属性

unset($test->Test4);//unset一个不存在的方法

18.自动加载

function DB($name)
{
	include './'.$name.'.php';
}

//把DB函数注册为自动加载函数,当调用不存在的类时会加载
spl_autoload_register('DB');


new Mysql();//实例化一个不存在的类

19.抽象类的意义

团队准备开发某网站,表建好了,页面设计好了.
A组负责开发底层数据库类(DB),上传类.
B级负责调用DB类.
A组发生了争执,MySQL? Oracle? DB2? sqlite?
B组.... 漫长等待.
能否让B组不等待?
解决:
A组和B组 先定1个数据库类的模板:
模板中对 方法名,参数,返回值,都做严格的规定
此时,不管A组选用什么数据库,对于B组来说,没有任何影响;

类前要加abstract,则为抽象类 方法前也可以加abstract ,则为抽象方法 抽象方法没有方法体 抽象类中也可以有已经实现的方法,但,只有要1个方法为抽象,则类仍是抽象的 抽象类不能实例化

//抽象类中也可以有已经实现的方法,但,只有要1个方法为抽象,则类仍是抽象的
//抽象类不能实例化
abstract class mDb()
{
	abstract public function getRow();//已实现的方法,没有方法体
	
	abstract public function getAll();
	
	
}

20.接口的概念

抽象类可以理解为"类的模板",接口则是"方法"的模板.
即,接口的粒度更小,用于描述通用的方法.
例:

interface flyer
{
	public function fly($a);
}

interface runer
{
	public function run($a);
}

interface water
{
	public function wate($a);
	
}

class Test implements flyer,runer,water
{
	public function fly($a)
	{
		echo '这是飞'.$a.'<br/>';
	}
	
	public function run($a)
	{
		echo '这是跑'.$a.'<br/>';
	}
	
	public function wate($a)
	{
		echo '这是水'.$a.'<br/>';
	}
}

$a=new Test();

$a->fly('lalal');

21.异常

function t1() {
 if(rand(1,10) > 5) {
 return false;
 } else {
 return t2();
 }
}
function t2() {
 if(rand(1,10) > 5) {
 return false;
 } else {
 return t3();
 }
}
function t3() {
 if(rand(1,10) > 5) {
 return false;
 } else {
 return true;
 }
}
var_dump(t1());

能否让我们只关心正确的逻辑,出错的部分能统一处理.

例:

function t1()
{
	if(rand(1,10)>5)
	{
		throw new Exception("T1错了",1);
	}
	else
	{
		return t2();
	}
}

function T2()
{
	if(rand(1,10)>5)
		{
			throw new Exception("T2错了",1);
		}
		else
		{
			return T3();
		}	
}

function T3()
{
	if(rand(1,10)>5)
	{
		throw new Exception("T3错了",1);
	}
	else
	{
		return true;
	}
	
}

try
{
var_dump(t1());
}
catch(Exception $e)
{
	echo '文件位置'.$e->getFile().'<br />';
	echo '行号:'.$e->getLine().'<br />';
	echo '错误信息'.$e->getMessage().'<br />';
}

什么时间用异常?
不该出错的地方,却有可能出错,就用异常.
如: 连接数据库,不应该出错.
如: 查询用户是否存在,可能返回true/false, 此时就用return

22.命名空间

多个人一起开发项目,函数名很容易重复.
用了类之后,类之间的方法名被类隔开,重名也没关系.
但如果项目更加大,类名也有可能重复,怎么办?
可以引入命名空间,声明某个空间,避免重名.

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

22.php

//声明一个命名空间
namespace Test;
include '22-1.php'; 
Class T1
{
	public function __construct()
	{
		echo '这里是命名空间Test1';
	}
	
}

new T1();

//使用Test2下的方法并且起别名
use Test2\T1 as s;

new s();

//实例化Test2命名空间下的T1
new \Test2\T1();

22-1.php

namespace Test2;

class T1
{
	public function __construct()
	{
		echo '这里是命名空间Test2';
	}
	
	
}

23.延时绑定

class Test
{
	public function A()
	{
		echo "这里是父类";
	}
	
	public function B()
	{
		self::A();
	}
}


class Test2 extends Test
{	
	public function A()
	{
		echo '这里是子类';
	}
	
}


$T=new Test2();

$T->b();//打印父类
class Test
{
	public function A()
	{
		echo "这里是父类";
	}
	
	public function B()
	{
		//此时,哪一个对象调用,static就是这个对象
		static::A();
	}
}


class Test2 extends Test
{	
	public function A()
	{
		echo '这里是子类';
	}
	
}


$T=new Test2();

$T->b();//打印子类

24.面向对象练习

根据以下抽象类和接口的提示,继承并实现数据库类

config.php

<?php

$config=array(
'host'=>'localhost',
'user'=>'root',
'passwd'=>'',
'dbname'=>'test',
'charset'=>'utf8'
);

return $config;

?>
<?php 

abstract class aDB {
 /**
 * 连接数据库
 */
 abstract public function conn();
 /**
 * query查询
 * @param string $sql sql语句
 * @return mixed
 */
 abstract public function query($sql);
 /**
 * 返回执行结果
 * @param string $sql sql语句
 * @return array
 */
 abstract public function getAll($sql);
 /**
返回一条语句
 * @param string $sql sql语句
 * @return array
 */
 abstract public function getRow($sql);
 /**
 * 返回一个数据
 * @param string $sql sql语句
 * @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 插入的id或者影响的行数
 */
 abstract public function Exec($data , $table , $act='insert' , $where='0');
 /**
 * 返回上一次insert产生主键id
 */
 abstract public function lastId();
 /**
返回上一条语句影响的行数
 */
 abstract public function affectRows();
}

class Mysql extends aDB
{
	public $mysqli;
	
	public function __construct()
	{
		$this->conn();
	}
	
	public function conn()
	{
		$cfg=include './config.php';
		
		$this->mysqli=new mysqli($cfg['host'],$cfg['user'],$cfg['passwd'],$cfg['dbname']);
		
		$this->query('set names '.$cfg['charset']);
		
	}
	
	public function query($sql)
	{
		return $this->mysqli->query($sql);
	}
	
	function getAll($sql)
	{	
		$res=$this->query($sql);

		$data=array();
	
		while($row=$res->fetch_assoc())
		{
			$data[]=$row;
		}
		
		return $data;
	}
	
	public function getRow($sql)
	{
		$res=$this->query($sql);
		
		return $res->fetch_assoc();
		
	}
	
	public function getOne($sql)
	{

		$res=$this->query($sql);
		
		return $res->fetch_array()[0];
		
	}
	
	public function Exec($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))."')";
			
		}
		else if($act=='update')
		{
			$sql='update '.$table.' set ';
			
			foreach($data as $v=>$k)
			{
				$sql.=$v.'='."'$k',";
			}
			
			$sql=rtrim($sql,',').' where '.$where;	
		}
		
		return $this->query($sql);
		
	}
	
	public function lastId()
	{
		return $this->mysqli->insert_id;
	}
	
	public function affectRows()
	{
		return $this->mysqli->affected_rows;
	}
}

文章如无特别注明均为原创!
本文作者: JunMo
转载或复制请带上本文地址 http://mo60.cn/post-47.html
并注明出处 JunMo博客
原文地址《 PHP面向对象学习笔记
发布于2019-7-27
收录状态: [百度已收录][360未收录]

分享到:


打赏

评论

游客

看不清楚?点图切换

切换注册

登录

您也可以使用第三方帐号快捷登录

切换登录

注册