类
创建类
<meta charset="utf-8">
<?php
//创建类 命名 大写 驼峰命名法
class Student{
// public 公共权限
// protected 只能在本类和子类中访问
// private 私有的 只能本类使用 类外 子类无权访问
//定义属性
public $name = "小明";
public $age = 18;
//定义方法
public function show ($name = "小明",$age = 18) {
return "{$name}的年龄为{$age}";
}
public function showThis(){
//php中 this 通过 $this 来使用 $this只能在成员方法中使用
echo "{$this->name}的年龄为{$this->age}";
}
}
实例化 创建对象
$a = new Student();
调用方法
echo $a->show("小红",24);
echo "<br/>";
$a->showThis();
echo "<br/>";
输出变量
echo $a->name;
echo "<br/>";
新增属性
$a->newData = "巴拉巴拉巴拉";
//打印查看
var_dump($a);
删除属性
unset($a->name);
var_dump($a);
定义类长量
- 常量 值永远不会变
- 常量就是类的常量与对象无关
- 常量在内存中只有一份 不会随着对象的增加而增加
- 常量可以被所有对象共享
- 常量必须大写
- 访问常量 类名:常量名
- :: 静态化调用方式
echo "<hr/>";
class Log{
const DB_LOCALHOST = "127.0.0.1";
const DB_USERNAME = "root";
const DB_PASSWORD = "root";
public function show() {
echo "主机名称:".Log::DB_LOCALHOST."<br/>";
echo "用户名称:".Log::DB_USERNAME."<br/>";
echo "用户密码:".Log::DB_PASSWORD."<br/>";
echo "<hr/>";
}
}
$b = new Log();
$b->show();
//常量无需实例化后才能调用
//直接 类名::常量名 即可调用
echo "主机名称:".Log::DB_LOCALHOST."<br/>";
echo "用户名称:".Log::DB_USERNAME."<br/>";
echo "用户密码:".Log::DB_PASSWORD."<br/>";
echo "<hr/>";
静态属性和静态方法
echo "静态属性与静态方法";
class Data{
//公共静态属性
public static $title = '18计算机三班';
//私有的静态方法
private static function showTitle() {
return "<hr/>";
}
public function show($name,$age) {
$text = $name."今年".$age."岁了";
$text.= Data::showTitle();
echo $text;
}
}
$c = new Data();
echo "<br/>";
$c->show("小明",18);
$d = new Data();
echo "<br/>";
$d->show("小红",24);
slef
关键字
- self 代表当前类 相当于$this代表当前对象
- $this通过->调用属性和方法
- self通过::调用常量、静态属性、静态方法
- $this只能用在成员方法中:self可以用在成员方法、静态方法中
class Data{
//公共静态属性
public static $title = '18计算机三班';
//私有的静态方法
private static function showTitle() {
return "<br/>";
}
public function show($name,$age) {
$text= self::$title;
$text.= self::showTitle();
$text.= $name."今年".$age."岁了";
echo $text;
}
}
$c = new Data();
echo "<hr/>";
$c->show("小明",18);
$d = new Data();
echo "<hr/>";
$d->show("小红",24);
构造方法
- 构造方法在new 的时候自动运行
public function __construct(){}
- 构造函数没有返回值 不支持参数返回
// 创建手机类
class Modile{
//在项目中 成员属性一般不设值
public $name; //名称
public $pinpai; //品牌
public $pirce; //价格
public $city; //产地 这里是形参 不是 成员属性
public function __construct($name,$pinpai,$pirce,$city){
$this->name = $name;
$this->pinpai = $pinpai;
$this->pirce = $pirce;
$this->city = $city;
}
public function show(){
$text = "手机名称:{$this->name}";
$text .= "<br/>手机品牌:{$this->pinpai}";
$text .= "<br/>手机价格:{$this->pirce}";
$text .= "<br/>手机产地:{$this->city}";
return $text;
}
}
$e = new Modile('华为P30','华为',8888.88,"深圳");
echo $e->show();
析构方法
- 当销毁一个对象前 自动调用
- 名称是固定的: __destruct()
- 析构方法没有参数 是成员方法
- 作用: 垃圾回收。列如:可以断开数据库的链接
//析构方法 代码结束自动销毁
class ClassA {
public function __destruct(){
echo "<br/>对象即将销毁";
}
}
$f = new ClassA();
echo "<br/>最后一行代码执行完毕";
// 销毁对象后
class ClassB{
public function __destruct(){
echo "对象即将销毁0.2";
}
}
$f = new ClassA();
echo "<hr/>";
unset($f);
echo "<br/>最后一行代码执行完毕0.2";
在线人数案例
- 构造人数加一 析构人数减一
//在线人数案例
class User{
//私有静态num
private static $num = 0;
public function __construct(){
self::$num++;
}
public function showNum(){
return self::$num;
}
public function __destruct(){
self::$num--;
}
}
$g = new User();
$h = new User();
$i = new User();
$j = new User();
$k = new User();
echo "<br/>当前在线人数为:".$g->showNum()."人";
&引用传地址:将数组变成引用传地址
//引用传地址:将数组变成引用传地址
$arr = array('10010','小明',18);
$school = "计算机三班";
//参数要引用传地址时(内存中的地址),&要加在形参前
function addElement(&$arr,$school){
$arr[] = $school;
}
addElement($arr,$school);
var_dump($arr);
类的三大特性
- 封装性
- 继承性
- 多态性
- (抽象性)
封装一个图书类
<meta charset="utf-8">
<?php
class Books{
const BOOKS_TITLE = "XXX图书馆";
private $name;
private $author; //作者名
private $price; //价格
private $publish; //出版社
public function __construct($name,$author,$price,$publish){
$this->name = $name;
$this->author = $author;
$this->price = $price;
$this->publish = $publish;
}
private function showHr(){
return "<hr/>";
}
public function show(){
$text = self::BOOKS_TITLE;
$text.= $this->showHr();
$text.= "<br/>{$this->name}";
$text.= "<br/>作者:{$this->author}";
$text.= "<br/>价格:{$this->price}";
$text.= "<br/>出版社:{$this->publish}";
return $text;
}
}
$bokk = new Books("XXX教科书","XXX主任","999","人民出版社");
$bokk2 = new Books("XXX教科书2","XXX主任2","9992","人民出版社2");
echo $bokk->show();
echo "<br/>";
echo "<br/>";
echo $bokk2->show();
继承extends
- 单继承:只能从一个父类来继承功能,列如:PHP java
- 多继承:可以同时从多个父类来继承功能,列如:C++
- 继承不是复制 相当于 把地址(内存地址)传过去了
<meta charset="utf-8">
<?php
class Father{
private $name;
private $age;
public function __construct($name,$age){
$this->name = $name;
$this->age = $age;
}
public function show(){
return "{$this->name}今年{$this->age}岁了";
}
}
class Childer extends Father{
}
$abc = new Childer("小明",18);
echo $abc->show();
parent 关键字
- self 代表当前类 ,parent代表父类
- self可以调用本类的内容:类常量、静态属性、静态方法、成员方法
- parent可以调用父类的内容:类常量、静态属性、静态方法、成员方法
- 用法: parent::常量名 …
类的多态
-
类的多态就是类的多种状态
-
主要指方法的重载和方法重写
-
函数重载:在一个脚本文件中,定义两个同名函数,PHP不支持
-
方法重载:在同一个类中定两个同名方法
-
方法重写:父类有一个方法,在子类用同样的名字再定义一次
-
功能升级,父类有的功能子类的功能比它完善,通过功能重写来实践。
-
如果不需要升级,也不需要扩展,继承就没有意义
-
方法重写的要求
方法重写
class A{
public static function showInFo($a,$b){
return "我是父类方法接收了\$a的值{$a}和\$b的值{$b}";
}
}
class AChildren extends A {
//重写父类方法
public static function showInFo($a,$b){
$text = "<h1>我是子类方法</h1>";
$text.= parent::showInFo($a,$b);
return $text;
}
}
echo AChildren::showInFo("aa","bb");
构造方法重写
- 所有方法都可以重写,但是构造方法重写,没有参数个数要求,也就是说参数个数可以不对等
小案例
//创建商品类 (继承类)
class Shop{
//私有商品属性
private $name;
private $price;
//受保护的工构造方法
protected function __construct($name,$price){
$this->name = $name;
$this->price = $price;
}
//受保护的方法
protected function showInFo(){
$text = "商品名称:".$this->name;
$text.= "<br/>商品价格:".$this->price;
return $text;
}
}
// 定义手机类 并继承父类
class Mobile extends Shop{
//私有的手机属性
private $pinpai;
private $city;
//公共的构造方法 重写
public function __construct ($name,$price,$pinpai,$city){
//调用父类构造方法
parent::__construct($name,$price);
$this->pinpai = $pinpai;
$this->city = $city;
}// 继承并重写
public function showInFo(){
$text = parent::showInFo();
$text.= "<br/>手机品牌:".$this->pinpai;
$text.= "<br/>手机产地:".$this->city;
return $text;
}
}
$obj = new Mobile("华为P20","9999.99","华为","深圳");
echo $obj->showInFo();
最后类和最终方法
- Final关键字修饰的类,就是最终类
- Final关键字修饰的方法,就是最终方法
- 最终类:该方法不能被继承,该类以及十分完善了无需升级kuoz
- 最终方法:该方法不能重写,直接调用即可。
- 例如:数据库制作类,也可以定义最终类
- 最终类和最终方法不能同时添加Final关键字
抽象类与抽象方法
- abstract 关键字修饰的类,就是抽象类
- abstract关键字修饰的方法,就是抽象方法
- 抽象类,该类只能继承,不能直接实例化,长用于“基础类”
- 抽象方法:该方法没有方块体{} ,抽象方法必须先继承后重写
- 如果有一个类中有一个方法为抽象类,该类就必须申明成抽象类
<?php
//定义抽象的商品基础类
abstract class Shop{
//定义抽象方法
abstract protected function showInFo($name,$age);
abstract protected function renMe();
}
final class Moblic extends Shop{
//重写showInFo() 方法
public function showInFo($name,$age){
echo "{$name}今年{$age}岁了";
}
//重写renMe() 方法
public function renMe(){
echo "我是成员方法:".__METHOD__;
}
}
$obj = new Moblic();
$obj->showInFo("小明",18);
echo "<br/>";
$obj->renMe();
global
<meta charset="utf-8">
<?php
echo "global";
$a1 = 10;
function show(){
//将全局变量的地址,引入到还是中
global $a1;
$a1 = 55;
echo "函数内部的\$a1:".$a1;
//删除函数内部的全局变量,断开到函数外的连接;
unset($a1);
}
show();
echo "<br/>函数内外的\$a1:".$a1;
<?php
$a1 = 10;
$a2 = 20;
function show(){
global $a1,$a2;
$a1 = &$a2; //$a1的地址指向了$a2 因此函数内没有$a1 了 $a1就是$a2
$a1 = 55;
echo "<br>".$a1."--".$a2;
}
show();
echo "<br>".$a1."--".$a2;
接口技术
-
为什么需要接口
- php只支持单接口,只能从一个父类来继承功能
- 接口也是子类中方法的命名规范
- 接口就是特殊的抽象类
-
接口的定义和实现要点
- interface 关键字 ,用来申明一个接口。接口就是一种特殊类
- implements关键字,创建子类,来实现接口
- 同类的东西,使用extends关键字:不同的类的东西,使用implements关键字
- 接口中只能存在两中东西:类常量,抽象方法(方法可以是成员方法和静态方法)
- 接口中的方法 ,默认都是抽象方法,所以不需要加abstract关键字
- 接口中方法的权限必须是public
- 接口中所有方法,在子类中全部要重写
- 接口中的常量只能继承不能重写
<?php
//定义一个接口
interface Inter1{
const TITLE = "计算机三班";
//定义抽象方法
public function showInfo($a,$b);
}
//定义一个接口
interface Inter2{
public static function redMe($a,$b);
}
//创建抽象的学生类,并实现多个接口(继承上面的接口)
abstract class Student implements Inter1,Inter2{
//重写接口中的showInfo
public function showInfo($a,$b){
//代码>.....
}
//重写接口中的redMe
public static function redMe($a,$b){
//代码>.....
}
}
//创建城建学生类,并继承抽象学生类
final class CJCCStudent extends Student{
//功能代码....
}
$obj = new CJCCStudent();
小demo
<meta charset="utf-8">
<?php
interface Telephone{
//打电话
public function call();
}
interface Mp3{
//听音乐
public function music();
}
interface Mp4 extends Mp3{
//看电影
public function rideo();
}
class HUAWEI implements Telephone,Mp4{
public function showInfo(){
echo "<h1>HUAWEI P30</h1>";
}
public function call(){
echo "再打电话<br/>";
}
public function music(){
echo "在听音乐<br/>";
}
public function rideo(){
echo "看电影<br/>";
}
}
$phone = new HUAWEI();
$phone->showInfo();
$phone->call();
$phone->music();
$phone->rideo();
类的自动加载
-
常规的自动加载类函数—》
__autoload()
-
类文件的命名规则
-
将每一个功能,单独定义成一个文件
-
每个类文件,尽量以
.class.php
结尾 列如 Student.class.php -
类文件主名要与类名一致 列如 Student{}
-
命名->驼峰命名法
-
-
__autoload()
函数的语法- __autoload()s是系统函数,不是方法
- 有唯一的参数,就是类名参数
- 当使用一个不存在的类时,__autoload($className)会自动调用
- 函数的内容包含两个方面
- 构造类文件的真实路径
- 判断并包含类文件代码
小案例
目录
Student.class.php
<?php
//final 此类不能被继承
final class Student {
private $naem = "小明";
public function __construct(){
echo "学生".$this->naem."是18计算机的<br/>";
}
}
Teacher.class.php
<?php
final class Teacher{
private $name = "刘老师";
public function __construct() {
echo $this->name."是18计算机的班主任";
}
}
app.php
不使用类的自动加载
<?php
header("content-type:text/html;charset=utf-8");
require_once("./libs/Student.class.php");
require_once("./libs/Teacher.class.php");
$obj1 = new Student();
$obj2 = new Teacher();
使用类的自动加载
<?php
header("content-type:text/html;charset=utf-8");
//类的自动加载
function __autoload($className){
echo "当前\$className值为:".$className."<br/>";
//构建物理真实物理路径
$className = "./libs/$className.class.php";
//如果文件包含就引用
if (file_exists($className)) require_once($className);
}
$obj1 = new Student();
$obj2 = new Teacher();
自定义类文件加载函数(spl_autoload_register)
-
__autoload()
有局限性 ,如果类文件路径不相同,命名方式等 -
spl_autoload_register
主要用于项目中,可以应用于不同情况 -
spl_autoload_register
注册多个类文件的加载函数 -
形成一个类文件的队列,依次执行,哪个文件存在就引用哪个文件
-
每个函数就是一种类文件的加载规则
-
语法格式
- 推荐使用匿名函数写法
spl_autoload_register(function($classNamea){
echo $classNamea;
//创建类文件路径数组
$arr = array(
"./libs/$classNamea.class.php",
"./public/$classNamea.class.php",
);
// 循环判断路径是否存在
foreach($arr as $flieName){
if (file_exists($flieName)) require_once($flieName);
}
});
$obj1 = new Student();
$obj2 = new Teacher2();
对象克隆
- 克隆使用
clone
关键字 - 克隆出来的是新对象
- 当克隆成功时 ,魔术方法
__clone()
会自动调用 - 克隆的类权限必须是
public
<?php
//关键字 clone 克隆对象
header("content-type:text/html;charset=utf-8");
class Student{
private $name = "小明";
private $age = 18;
//当克隆对象要改变里面的数据时使用 __clone()
// 当克隆成功时 ,魔术方法 `__clone()` 会自动调用
function __clone() {
$this->name = "小红";
$this->age = 16;
}
}
$obj1 = new Student();
//克隆对象$obj1 赋给$obj2
$obj2 = clone $obj1;
var_dump($obj1,$obj2);
遍历对象属性
__toString()
描述:将对象转成字符串时,魔术方法, __toString()
__invoke()
- 当对象当成函数调用时,魔术方法__invoke() 自动调用
<?php
header("content-type:text/html;charset=utf-8");
class Student{
//当对象别转成字符串的时候 自动调用
public function __toString(){
return "对不起,对象不能转成字符串";
}
}
$obj = new Student();
//将对象转成字符串 然后输出
echo $obj;
class Teacher{
public function __invoke(){
echo "对不起,对象不能当函数使用";
}
}
echo "<br/>";
$obj2 = new Teacher();
$obj2();
面向对象设计模式
- 常用设计模式
- 单列模式:一个类只能创建一个对象,不管用什么方法,都无法创建第2个类
- 工厂模式:根据传递不同类名,来创建不同的对象对象的工厂
- 单列模式设计要求(三私一公)
- 一私:私有的静态的用来保存对象的属性
- 二私:私有的构造方法,阻止类外new 对象
- 三私:私有的克隆方法,阻止类外clone 对象
- 一公:公共的静态的创建创建对象的方法
<?php
//单列模式创建对象
class Db{
private static $obj = null;
//私有的构造方法 :阻止类外创建对象 new
private function __construct(){
}
//私有的克隆方法 :阻止类外clone 对象
private function __clone(){}
//公共的静态的创建对象的方法
public static function getInstance(){
//判断当前对象是否存在
if (!self::$obj instanceof self ) {
//如果对象不存在就创建他
self::$obj = new self;
}
//返回当前对象
return self::$obj;
}
}
$a = Db::getInstance();
$b = Db::getInstance();
var_dump($a,$b);
- 创建出来的都是同一个对象 同一个地址
单列设计模式案例
Db.class.php
<?php
class Db{
private static $obj = null;
//私有的构造方法 防止类外创建对象
private $db_host; //主机名
private $db_user; //用户名
private $bd_pass; //密码
private $bd_name; //数据库名
private $charset; //字符集
private function __construct($config)
{
$this->db_host = $config['db_host'];
$this->db_user = $config['db_user'];
$this->bd_pass = $config['bd_pass'];
$this->bd_name = $config['bd_name'];
$this->charset = $config['charset'];
//连接数据库
$this->connectDb();
//设置字符集
$this->setCharset();
}
//私有的克隆方法 阻止类外克隆 clone clone clone
private function __clone(){}
//公共的创建对象的方法
public static function getInstance($config)
{
//判断对象是否存在 不存在就new
if (!self::$obj instanceof self){
self::$obj = new self($config);
}
//如果对象存在返回对象
return self::$obj;
}
//私有的 连接数据库
private function connectDb()
{
$conn = mysqli_connect($this->db_host,$this->db_user,$this->bd_pass,$this->bd_name);
if(!@$conn){
dei("数据库连接失败!!");
}
return $conn;
}
//私有的设置字符集
private function setCharset()
{
$conn = $this->connectDb();
mysqli_query($conn,"set names {$this->charset};");
}
//公共的执行sql语句的方法
public function exec($sql)
{
//转小写
$sql = strtolower($sql);
//判断是不是select语句
$conn = $this->connectDb();
if (substr($sql,0,6) == "select"){
die ('该方法不能执行select语句!');
}
//非select语句正常执行 并返回布尔值
return mysqli_query($conn,$sql);
}
//私有的执行sql语句的方法
private function query($sql)
{
//转小写
$sql = strtolower($sql);
//判断是不是select语句
if (substr($sql,0,6) != "select"){
die ('该方法不能执行非select语句!');
}
//是select语句正常执行 并返回结果集
$conn = $this->connectDb();
return mysqli_query($conn,$sql);
}
//公共的获取单条数据
public function fetchNoe($sql,$stype=3)
{
//执行sql语句 返回结果集
$result = $this->query($sql);
//定义返回的数组类型
$types = array(
1 => MYSQLI_NUM,
2 => MYSQLI_BOTH,
3 => MYSQLI_ASSOC,
);
//返回一条记录
return mysqli_fetch_array($result,$types[$stype]);
}
//公共的获取多条记录的方法(return二维数组)
public function fetchArr($sql,$type=3)
{
$result = $this->query($sql);
$types = array(
1 => MYSQLI_NUM,
2 => MYSQLI_BOTH,
3 => MYSQLI_ASSOC,
);
//循环从结果集里的每一条数据 存到一个新数组中
while($row = mysqli_fetch_array($result,$types[$type])){
$arrs[] = $row;
}
//return $arrs;
return $arrs;
}
//公共的获取记录数
public function roeCount($sql)
{
//执行查询
$conn = $this->connectDb();
$resul = $this->query($sql);
//返回记录数
return mysqli_num_rows($resul);
}
}
分页类
<?php
final class Pages{
//私有成员属性
private $page ;//当前页
private $pages; //总页数
public function __construct($page,$pages){
$this->page = $page;
$this->pages = $pages;
}
public function showPage(){
//计算开始页和结束页
$start = $this->page - 5;
$end = $this->page + 4;
if ($this->page < 6) {
$start = 1;
$end = $end + 6 - $this->page;
}
if ($end>$this->pages){
$start = $this->pages - 10 + 1;
$end = $this->pages;
}
if ($this->pages<=10) {
$start = 1;
$end = $this->pages;
}
//循环显示所有代码
for ($i = $start;$i <= $end;$i++) {
//如果是当前页不加载连接
if ($i == $this->page){
echo "<span class='current'>$i</span>";
} else {
echo "<a href='?page=$i'>$i</a>";
}
}
}
}
conn.php
<meta charset="utf-8">
<?php
//自动加载
spl_autoload_register(function($className){
$arr = array(
"./$className.class.php"
);
foreach ($arr as $value ) {
if (file_exists($value)) require_once($value);
};
});
$arr = array(
"db_host" => "127.0.0.1",
"db_user" => "root",
"bd_pass" => "root",
"bd_name" => "test",
"charset" => "utf8",
);
// var_dump($arr);
//创建db对象
$db = Db::getInstance($arr);
var_dump($db);
index.php
<?php
require_once('./libs/conn.php');
// var_dump($obj1);
$sql = "select * from student ";
//查询所有数据 获取到总页数
//查询数据条数
$rowData = $db->roeCount($sql);
//开始分页
//页数
$pagesize = 5;
//当前页
$page = isset($_GET['page']) ? $_GET['page'] : 1 ;
//获取每页的开头页数
$startrow = ($page - 1) * $pagesize;
//获取分页数 (向上取整)
$pages = ceil($rowData/$pagesize);
//获取分页数据
$sql.= "order by id desc limit {$startrow},{$pagesize}";
$arrData = $db->fetchArr($sql);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>学生管理系统</title>
<style type="text/css">
a{
text-decoration: none;
}
.pagelist{
height: 50px;
line-height: 50px;
text-align: center;
}
.pagelist a{
padding: 6px 10px;
border: 1px solid #e8e8e8;
margin: 0 3px;
}
.pagelist a:link,
.pagelist a:visited{
}
.pagelist a:hover{
background-color: #555;
color: white;
font-weight: bold;
border: none;
}
.pagelist .current{
background-color: #555;
color: white;
font-weight: bold;
padding: 6px 10px;
border: 1px solid #e8e8e8;
}
</style>
</head>
<body>
<h1 style="width: 100%; text-align: center;">学生管理系统</h1>
<div style="margin: 0 auto; width: 100%;">
<span style="margin-bottom: 10px;display: block; margin-left: 20%;">总人数:<?php echo $rowData;?>人</span>
<a href="./add.php" style="margin-bottom: 10px;display: block; margin-left: 20%;">添加</a>
<table border="1" style="margin: 0 auto; width: 60%;">
<tr bgcolor="whitesmoke">
<th>id</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>学历</th>
<th>操作</th>
</tr>
<?php foreach($arrData as $key):?>
<tr style="text-align: center;">
<td><?php echo $key['Id']?></td>
<td><?php echo $key['name']?></td>
<td><?php echo $key['sex']?></td>
<td><?php echo $key['age']?></td>
<td><?php echo $key['education']?></td>
<td>
<a href="javascript:;" οnclick="goUpData(<?php echo $key['Id'];?>)">修改</a>
<a href="javascript:;" onClick="goConfirm(<?php echo $key['Id'];?>)" >删除</a>
</td>
</tr>
<?php endforeach;?>
<tr>
<td colspan="9" class="pagelist">
<?php
$page_obj = new Pages($page,$pages);
$page_obj->showPage();
?>
</td>
</tr>
</table>
</div>
</body>
<script type="text/javascript">
function goConfirm(id){
if(window.confirm("您确认要删除吗?")){
location.href="./delete.php?id=" + id;
} else {
alert("您取消了");
}
}
function goUpData(id){
location.href="./upData.php?id="+id;
}
</script>
</html>
add.php
<?php
require_once("./libs/conn.php");
//判断是否是表单提交
if (isset($_POST['ac']) && $_POST['ac'] == "add"){
foreach ($_POST as $k => $v) {
$$k = $v;
};
$sql = "INSERT INTO student VALUES (null,'$name','$sex','$age','$education');";
if ($db->exec($sql)){
echo "<h1>添加成功!正在跳转...</h1>";
header("refresh:2;url=./index.php");
die();
}
}
?>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>添加学生信息</title>
</head>
<body>
<h1 style="width: 100%; text-align: center;">添加学生信息</h1>
<a href="index.php" style="margin-bottom: 10px;display: block; margin-left: 20%;">返回学生列表</a>
<form action="" method="post" style="margin: 0 auto; width: 60%;">
<table border="1" style="margin: 0 auto ; width: 60%;">
<tr>
<td>姓名:</td>
<td><input type="text" name="name" value="" placeholder="请输入姓名" />
<input type="hidden" name="ac" value="add"></td>
</tr>
<tr>
<td>性别:</td>
<td>
<input type="radio" name="sex" value="男" checked="checked" />男
<input type="radio" name="sex" value="女" />女
</td>
</tr>
<tr>
<td>年龄:</td>
<td><input type="text" name="age" size="2" maxlength="2" value="" placeholder="" /></td>
</tr>
<tr>
<td>学历:</td>
<td>
<select name="education">
<option value ="初中">初中</option>
<option value ="高中" selected="selected">高中</option>
<option value ="本科">本科</option>
</select>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="提交" />
</td>
</tr>
</table>
</form>
</body>
</html>
delete.php
<meta charset="utf8">
<?php
require_once('./libs/conn.php');
$id = $_GET['id'];
$sql = "delete from student where id=$id";
if($db->exec($sql)){
echo "<h1>删除成功!正在跳转》。。。<h1/>";
//2秒后跳转
header("refresh:2;url=./index.php");
}
upData.php
<?php
require_once("./libs/conn.php");
if ($_SERVER['REQUEST_METHOD'] == "GET"){
$id = $_GET['id'];
$sql = "select * from student where Id = ".$id;
$get_student_data = $db->fetchNoe($sql);
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
foreach($_POST as $k => $v) {
$$k = $v;
};
$sql = " update student set name = '$name',`sex` = '$sex' ,`age` = $age,`education` = '$education' where Id = $id";
$db->exec($sql);
header("refresh:2;url=./index.php");
die("修改成功!正在跳转中.....");
}
?>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>修改学生信息</title>
</head>
<body>
<h1 style="width: 100%; text-align: center;">修改学生信息</h1>
<a href="index.php" style="margin-bottom: 10px;display: block; margin-left: 20%;">返回学生列表</a>
<form action="" method="post" style="margin: 0 auto; width: 60%;">
<table border="1" style="margin: 0 auto ; width: 60%;">
<tr>
<td>姓名:</td>
<td><input type="text" name="name" value="<?php echo $get_student_data['name'] ; ?>" placeholder="请输入姓名" />
<input type="hidden" name="id" value="<?php echo $get_student_data['Id'] ; ?>"></td>
</tr>
<tr>
<td>性别:</td>
<td>
<input type="radio" name="sex" value="男" <?php echo $get_student_data['sex'] == "男" ? "checked='checked'" : "" ;?> />男
<input type="radio" name="sex" value="男" <?php echo $get_student_data['sex'] == "女" ? "checked='checked'" : "" ;?> />女
</td>
</tr>
<tr>
<td>年龄:</td>
<td><input type="text" name="age" size="2" maxlength="2" value="<?php echo $get_student_data['age'] ; ?>" placeholder="" /></td>
</tr>
<tr>
<td>学历:</td>
<td>
<select name="education">
<option value ="初中" <?php echo $get_student_data['education'] == "初中" ? "selected='selected'" : "" ;?>>初中</option>
<option value ="高中" <?php echo $get_student_data['education'] == "高中" ? "selected='selected'" : "" ;?>>高中</option>
<option value ="本科" <?php echo $get_student_data['education'] == "本科" ? "selected='selected'" : "" ;?>>本科</option>
</select>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="提交" />
</td>
</tr>
</table>
</form>
</body>
</html>
数据库
# Host: localhost (Version: 5.5.53)
# Date: 2019-11-10 11:39:56
# Generator: MySQL-Front 5.3 (Build 4.234)
/*!40101 SET NAMES utf8 */;
#
# Structure for table "student"
#
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sex` enum('男','女') DEFAULT '男',
`age` int(11) DEFAULT NULL,
`education` enum('初中','高中','本科') DEFAULT '高中',
PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=35 DEFAULT CHARSET=utf8 COMMENT='php类DB单列设计模式练习数据';
#
# Data for table "student"
#
/*!40000 ALTER TABLE `student` DISABLE KEYS */;
INSERT INTO `student` VALUES (1,'小明','男',18,'高中'),(2,'小红','男',17,'高中'),(3,'小乔','男',22,'高中'),(7,'周瑜','男',24,'高中'),(8,'诸葛亮','男',24,'高中'),(9,'王昭君','女',26,'高中'),(10,'阿达','男',22,'高中'),(11,'墨子','男',24,'高中'),(12,'诸葛亮','男',24,'高中'),(13,'王昭君','女',26,'高中'),(14,'阿达','男',22,'本科'),(15,'墨子','男',24,'本科'),(16,'阿达是','男',24,'本科'),(17,'韩信','男',24,'本科'),(18,'韩信','男',24,'初中'),(19,'诸葛亮','男',24,'初中'),(20,'王昭君','女',26,'高中'),(21,'阿达','男',22,'高中'),(22,'墨子','男',24,'高中'),(23,'阿达是','男',24,'初中'),(24,'韩信','男',24,'高中'),(25,'诸葛亮','男',24,'高中'),(26,'王昭君','女',26,'高中'),(27,'阿达','男',22,'高中'),(28,'墨子','男',24,'高中'),(29,'阿达是','男',24,'高中'),(30,'啊啊啊','男',11,'初中'),(31,'修改测试222','男',18,'高中'),(32,'添加测试','女',26,'本科'),(33,'测试55','男',18,'本科'),(34,'啊啊修改1','男',11,'高中');
/*!40000 ALTER TABLE `student` ENABLE KEYS */;
工厂模式
- 工厂模式,中只有一个私有的静态属性,用来存储不同类的对象
- 工厂模式中有一个公共的的静态的创建对象的方法
- 静态方法的功能代码:判断当前的对象是否存在,? 直接放回 : 创建一个对象,在返回
单列工厂模式
./libs/Student.class.php
<?php
//最终的学生类
final class Student {
private $name = "小明";
private $age = 18;
public function __construct(){
echo $this->name."今年".$this->age."岁了"."<br/>";
}
}
./libs/Teacher.class.php
<?php
//最终的老师类
final class Teacher {
private $name = "王老师";
private $age = 8;
public function __construct(){
echo $this->name."今年任职".$this->age."年了"."<br/>";
}
}
./libs/Fortory.class.php
<?php
final class Fortory {
//私有的静态的存储多个对象的数组
private static $arr = array();
//公共的创建对象的静态方法
public static function getObj($className){
//判断数组中有没有这个对象
if (!isset( self::$arr[$className])) {
//没有就创建
self::$arr[$className] = new $className();
}
//否则return对象
return self::$arr[$className];
}
}
./app.php
<meta charset="utf-8">
<?php
//类的自动加载
spl_autoload_register(function ($className){
$arr = array(
"./libs/$className.class.php",
);
foreach ($arr as $filename ) {
if (file_exists($filename)) require_once($filename);
}
});
//创建对象
//学生对象
$stuObj = Fortory::getObj("Student");
//老师对象
$teaObj = Fortory::getObj("Teacher");
//再学生对象
$stuObj2 = Fortory::getObj("Student");
//再老师对象
$teaObj2 = Fortory::getObj("Teacher");
//创建出来的都是同一个学生对象和老师对象 内存地址是都是同一个
var_dump($stuObj,$teaObj,$stuObj2,$teaObj2);
浏览器查看结果
<meta charset="utf-8">
小明今年18岁了<br/>王老师今年任职8年了<br/>object(Student)#2 (2) {
["name":"Student":private]=>
string(6) "小明"
["age":"Student":private]=>
int(18)
}
object(Teacher)#3 (2) {
["name":"Teacher":private]=>
string(9) "王老师"
["age":"Teacher":private]=>
int(8)
}
object(Student)#2 (2) {
["name":"Student":private]=>
string(6) "小明"
["age":"Student":private]=>
int(18)
}
object(Teacher)#3 (2) {
["name":"Teacher":private]=>
string(9) "王老师"
["age":"Teacher":private]=>
int(8)
}
重载
-
属性重载
__set()
- 在给不可访问属性值时
__set()
会自动调用
- 在给不可访问属性值时
<meta charset="utf-8"> <?php class A { private $naem; // 在给不可访问属性值时 `__set()` 会自动调用 public function __set($name,$value){ $this->$name = $value; } } $obj = new A(); //给私有属性赋值 $obj->name = "雄安"; var_dump($obj);
__get()
- 当获取不可访问属性值时
__get()
会自动调用
- 当获取不可访问属性值时
<meta charset="utf-8"> <?php class A { private $name = "小明"; //当获取不可访问属性值时 `__get()` 会自动调用 public function __get($name){ return $this->$name ; } } $obj = new A(); //给私有属性赋值 echo $obj->name."今年成年了";
__isset()
- 当对私有属性使用isset()或empty()操作时
isset()
会自动调用
- 当对私有属性使用isset()或empty()操作时
<meta charset="utf-8"> <?php class A { private $name = "小明"; //当对私有属性使用isset()或empty()操作时 `isset()`会自动调用 public function __isset($name){ echo "不能对私有属性使用isset()和empty()!"; } } $obj = new A(); isset($obj->name);
__unset()
- 当对私有属性使用unset()操作时
__unset()
会自动调用
- 当对私有属性使用unset()操作时
<meta charset="utf-8"> <?php class A { private $name = "小明"; //当对私有属性使用unset()操作时 `__unset()`会自动调用 public function __unset($name){ echo "不能对私有属性使用unset()!"; } } $obj = new A(); unset($obj->name);
-
重载方法
__callstatuc()
- 用静态方法调用一个不可访问方法时,
__callstatuc()
会自动调用
- 用静态方法调用一个不可访问方法时,
__call
- 当调用不可访问的方法时,
call()
会自动调用
- 当调用不可访问的方法时,
静态绑定
当只有一个类时 self static 都代表当前类
<meta charset="utf-8">
<?php
class A {
const TITLE = "计算机三班";
public function showInfo(){
echo "班级为:".self::TITLE."<br/>";
echo "班级为:".static::TITLE;
}
}
$obj = new A();
$obj->showInfo();
在继承环境下,self永远代表本类,而static代表最后执行的类
<meta charset="utf-8">
<?php
class A {
const TITLE = "计算机三班";
public function showInfo(){
echo "班级为:".self::TITLE."<br/>";
echo "班级为:".static::TITLE;
}
}
class B extends A {
const TITLE = "18 计算机三班";
}
$obj = new B();
$obj->showInfo();
类型约束
- java属于强类型语言,变量在程序过程中,类型不可以改变。
- php与javascript属于弱类型语言,变量在程序过程中,类型可以改变。
- PHP5.3以后,才有了类型约束,主要指方法的参数或函数参数,其他地方还不行
- PHP的类型约束有三种:数组约束,对象约束,接口约束
<?php
//类型约束
function show($a,array $b,Student $c,inter2 $d){
//参数 $a 可以为任意类型
//参数 $b 必须为数组
//参数 $c 必须是Student 实例的对象
//参数 $d 必须是inter2 接口的实例对象
}
$a = 100;
$b = array(1,2,3); //为数组
interface inter2{}; //定义接口
class Student implements inter2 {};
$obj = new Student();
show($a,$b,$obj,$obj);
常用的魔术常量
__LINE__
、当前行号__FILE__
、当前文件名__DIR
、当前目录名__FUNCTION__
、当前函数名__CLASS__
、当前类名__METHOD
、当前方法__NAMESPACE__
、当前空间名
<meta charset="utf-8">
<?php
//魔术常量方法
echo "魔术常量方法"."<br/>";
class A{
//公共的静态的创建对象的方法
public static function getObj(){
$self = __CLASS__;
return new $self();
}
public function showInfo(){
echo "当前行数:".__LINE__."<br/>";
echo "当前文件:".__FILE__."<br/>";
echo "当前目录:".__DIR__."<br/>";
echo "当前函数名:".__FUNCTION__."<br/>";
echo "当前类名:".__CLASS__."<br/>";
echo "当前方法名:".__METHOD__."<br/>";
}
}
$a_obj = A::getObj();
$a_obj->showInfo();
序列化
- 变量序列化:将变量转成可存储或传输的字符串,会保留变量的类型和结果
- 变量反序列化:将序列化的字符串,再还原成原始变量
- 除了资源变量,其它变量都可以序列化
- 序列化
serialize()
<meta charset="utf-8">
<?php
echo "序列化<br/>";
$array = array(
"name" => "小明",
"age" => 18
);
//序列化
$arr = serialize($array);
echo "\$arr = ".$arr;
//序列化后存到文件中
file_put_contents("1.txt",$arr);
?>
- 反序列化
unserialize()
//反序列化
//获取序列化后的字符串文件
$file = file_get_contents("1.txt");
$newStxt = unserialize($file);
echo "<br/>\$file = ".$file."<br/>";
var_dump($newStxt);
对象序列化和反序列化
-
对象序列化
- 对象序列化的过程,与其它变量数据一样
- 当序列化对象时,PHP 将试图在序列化动作之前调用对象的成员方法
__sleep()
,这样就允许对象在被序列化之前做然后清除操作 __sleep()
魔术方法功能:此功能可以用于清理对象,并返回一个包含对象中所有被序列化的变量名的数据- 对象序列化的内容只能包含成员属性:不能包含常量、静态方法、成员方法、静态方法
-
对象方序列化
__wakeup()
<meta charset="utf-8">
<?php
//构建最终的数据库工具类
final class DB {
private $host;
private $user;
private $pass;
private $name;
public function __construct($arr){
$this->host = $arr['host'];
$this->user = $arr['user'];
$this->pass = $arr['pass'];
$this->name = $arr['name'];
$this->connentDb();
}
//在对象商量好之前 自动调用
public function __sleep(){ //!!!!!!!!!!!!!!!!!!!!!!!
//返回要实例化的对象属性,不需要的不写
return array('host','user','name');
}
//在对象重新重构后 __wakeup()会自动调用
//对象初始化
public function __wakeup(){ //!!!!!!!!!!!!!!!!!!!!!!!!
//重新赋值密码 (因为实例化的时候没有保存密码)
$this->pass = "root";
//手动连接数据库 (因为这里不会走构造方法)
$this->connentDb();
}
private function connentDb() {
if (!@mysqli_connect($this->host,$this->user,$this->pass,$this->name))
die("数据库连接失败!");
}
}
$arr =array(
"host" => "127.0.0.1",
"user" => "root",
"pass" => "root",
"name" => "test",
);
$db = new DB($arr);
var_dump($db);
//序列化$db (条件 不把数据库密码保存进去 使用__sleep())
$text_db = serialize($db);
echo "序列化后-->".$text_db;
//保存 到文件中
file_put_contents("2.txt",$text_db);
//开始反序列化
//获取到已经序列化的字符串文件
$txtData = file_get_contents("2.txt");
$newDb = unserialize($txtData);
echo "||||| 反序列化后-------->";
var_dump($newDb);
常用类和对象的操作函数
- 判断类、接口、方法、属性是否存在
class_exists()
判断类是否存在interfacte_exists
判断接口是否存在method_exists
判断方法是否存在propety_exists
判断属性是否存在
<meta charset="utf-8">
<?php
class A {
public function __construct(){
echo "对象以创建成功";
}
};
//判断类是否存在
if (class_exists("A")) {
//有则创建对象
$obj = new A();
} else {
echo "没有找到该类";
}
- 获取类名
get_class()
根据对象返回类名get_parent_class
返回父类名
class Student {
}
class B extends Student{
}
$obj2 = new B();
echo "<br/>类名为:".get_class($obj2);
echo "<br/>类名为:".get_parent_class($obj2);