1、MySQLDB.class.php
注意:数据库操作类用的是单例模式。
<?php
class MySQLDB
{
//数据库连接信息
private $dbConfig=array(
'host'=>'localhost',
'port'=>'3306',
'user'=>'',
'pwd'=>'',
'charset'=>'utf8',
'dbname'=>''
);
//数据库连接资源
private $link;
//单例对象引用
private static $instance;
/**
* 初始化属性
* @param array $params 数据库连接信息
*/
private function initAttr($params)
{ //初始化属性,使用array_marge()函数合并两个数组
$this->dbConfig=array_merge($this->dbConfig,$params);
}
/**
* 连接数据库
*/
private function connectServer()
{
$host=$this->dbConfig['host'];
$port=$this->dbConfig['port'];
$user=$this->dbConfig['user'];
$pwd=$this->dbConfig['pwd'];
//连接数据库服务器
if($link=mysql_connect("$host:$port",$user,$pwd)){
$this->link=$link;
}else{
die('数据库连接失败。'.mysql_error());
}
}
/**
* 设定字符集
*/
private function setCharset()
{
$sql="set names {$this->dbConfig['charset']}";
$this->query($sql);
}
/**
* 选择默认数据库
*/
private function selectDefaultDb()
{
//判断$this->dbConfig['dbname']是否为空。为空表示不需要选择数据库。
if($this->dbConfig['dbname']==''){
return;
}
$sql="use `{$this->dbConfig['dbname']}`";
$this->query($sql);
}
/**
* 构造方法
* @param array $params 数据库连接信息
*/
private function __construct($params=array())
{
//初始化属性
$this->initAttr($params);
//连接数据库
$this->connectServer();
//设定字符集
$this->setCharset();
//选择默认数据库
$this->selectDefaultDb();
}
/**
* 执行SQL语句,获取结果集
* @param string $sql 待执行的SQL
* @return resource
*/
public function query($sql)
{
if($result=mysql_query($sql,$this->link)){
//执行成功
return $result;
}else{
//执行失败
echo 'SQL执行失败:<br>';
echo '错误的SQL为:'.$sql.'<br>';
echo '错误的代码为:'.mysql_errno($this->link).'<br>';
echo '错误的信息为:'.mysql_error($this->link).'<br>';
die;
}
}
/**
* 查询单条记录
* @param string $sql
* @return array 一维数组
*/
public function fetchRow($sql){
if($result=$this->query($sql)){
$row=mysql_fetch_array($result,MYSQL_ASSOC);
return $row;
}else{
return false;
}
}
/**
* 处理多条数据
* @param string $sql
* @return array 二维数组
*/
public function fetchAll($sql){
if($result=$this->query($sql)){
$rows=array();
while($row=mysql_fetch_array($result,MYSQL_ASSOC)){
$rows[]=$row;
}
mysql_free_result($result);
return $rows;
}else{
return false;
}
}
/**
* mysql转义字符串
* @param $data 待转义的字符串
* @return string
*/
public function escapeString($data){
return mysql_real_escape_string($data,$this->link);
}
/**
* 获得单例对象的公共接口方法
* @param array $params 数据库连接信息
* @return object 单例的对象
*/
public static function getInstance($params=array())
{
/*
result = obj instanceof Class; 其中obj为一个对象,Class表示一个类或者一个接口。
当obj为Class的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result都返回true,否则返回false。
*/
//判断是否没有实例化过
if(!MySQLDB::$instance instanceof MySQLDB){
//实例化并保存
MySQLDB::$instance=new MySQLDB($params);
}
//返回对象
return MySQLDB::$instance;
}
/**
* 私有克隆
*/
private function __clone(){
}
}
2、init.php
<?php
header('content-type:text/html;charset=utf-8');
//数据库配置
$dbConfig=array(
'user'=>'root',
'pwd'=>'root',
'dbname'=>'users'
);
//使用__autoload()启动自动加载
function __autoload($className){
require "./$className.class.php";
}
//定义model函数用来实例化模型类
function model($tableName){
$model=$tableName.'Model';
return new $model($tableName);
}
3、model.class.php
注意:$info_Id=$this->db->lastInsertId(); 这句有问题。需要修改数据库操作类MySQLDB.class.php中函数的访问限制。
<?php
class model{
//成员属性$db,用来保存数据库操作类的实例
protected $db;
//表名
protected $tableName;
//构造方法,用来获取数据库连接资源
public function __construct($tableName){
//实例化数据库。使用$GLOBALS把init.php中保存数据库连接信息的数组$dbConfig变成全局变量
$this->db=MySQLDB::getInstance($GLOBALS['dbConfig']);
//获取表名
$this->tableName=$tableName;
}
/**
* 查询
*/
//查询字段信息(查询用)
protected $fields;
//指定待查询的字段
public function field($fields){
$this->fields=$fields;
return $this;
}
//解析字段(查询用)
//将$this->fields转换为逗号拼接的SQL字段部分
private function parseFields(){
//判断$fields属性的值是否是字符串
if(is_string($this->fields)){
//如果是字符串则把该字符串使用“逗号”分割成数组。
$this->fields=explode(',',$this->fields);
}
//使用foreach语句遍历数组,将数组信息按照select语句中查询字段的语法格式进行重新组合
foreach($this->fields as $k=>$v){
$this->fields[$k]="`$v`";
}
//把字段数组使用“逗号”连接成字符串并返回
return implode(',',$this->fields);
}
//查询数据
//如果没有指定$this->fields,则查询所有字段
public function select(){
//判断$fields属性是否为空,如果$fields属性为空说明并没有调用field()方法指定查询字段。
if(empty($this->fields)){
//拼接SQL语句
$sql="select * from $this->tableName";
}else{
//调用parseFields()方法对$fields的值进行解析并赋值给变量$fields
$fields=$this->parseFields();
$sql="select $fields from $this->tableName";
//清除本次的字段
$this->fields=null;
}
return $this->db->fetchAll($sql);
}
/**
* 添加
*/
//数据数组(添加、修改用)
protected $data=array();
//设置模型中的数据
public function __set($e_name,$value)
{
$this->data[$e_name]=$value;
}
//设置模型中的数据
public function __get($e_name)
{
return isset($this->data[$e_name])?$this->data[$e_name]:null;
}
//解析数据(添加用)
private function parseData()
{
$field=$value=array();
foreach($this->data as $k=>$v){
$field[]="`$k`";
$value[]="'".$this->db->escapeString($v)."'";
}
return array(
'field'=>implode(',',$field),
'value'=>implode(',',$value),
);
}
//添加数据,如果传递$data参数,则覆盖模型本身的数据
public function add($data=array())
{
//print_r($this->data);//Array ([e_name] => 阿锦 )
//print_r($data);//Array ([e_gender] => 女 [date_of_birthday] => 1998-05-21 )
//合并数组
$this->data=array_merge($this->data,$data);
//解析$data属性中的数据
$data=$this->parseData();
//清除模型中的数据
$this->data=array();
//拼接SQL
$sql="insert into $this->tableName ({$data['field']}) values ({$data['value']})";
//返回执行结果
if($this->db->query($sql)){
//当添加成功时,返回最后被添加的数据id
//Fatal error: Call to undefined method MySQLDB::lastInsertId() in ...
$info_Id=$this->db->lastInsertId();//应该是$数据库连接资源->lastInsertId()
//echo $info_Id;
return $info_Id;
}
return false;
}
}
4、emp_infoModel.class.php
<?php
//emp_infoModel类,用来对emp_info表进行数据操作
final class emp_infoModel extends model
{
//该方法会根据传递的ID获取相关数据
public function getById($id)
{
//编写根据id获取数据的SQL语句
$sql="select * from $this->tableName where id=$id";
//执行数据库操作类的fetchRow获取数据
if($data=$this->db->fetchRow($sql)){
//方法执行成功,返回数据
return $data;
}
//方法执行失败,返回false
return false;
}
}
5、index.php
<?php
//载入init.php文件
require './init.php';
//调用model()函数,传入要操作的数据表名以获取对应模型类对象
$emp_info=model('emp_info');
/**
* 查询
*/
//通过$emp_info对象调用field()方法指定查询的字段,调用select()方法执行查询
$data=$emp_info->field('e_name,date_of_birthday')->select();
//输出查询的数据结果
print_r($data);
/**
* 添加
*/
//以下演示两种创建数据的方式
$emp_info->e_name='阿锦';//通过对象属性保存员工数据(__get)
//通过传递数组保存员工数据
$info_Date=array(
'e_gender'=>'女',
'date_of_birthday'=>'1998-05-21'
);
//调用add()方法,并接收方法返回值
if($info_Id=$emp_info->add($info_Date)){
echo "111";
//如果返回了新添加的员工id,则根据id获取员工信息
$info=$emp_info->getById($info_Id);
echo '<pre>';
//打印输出员工信息
var_dump($info);
}
echo "222";
4、数据库
5、知识点
(1)继承
子类在继承父类时,会继承父类的所有公共成员和受保护的成员,而不会继承父类的私有成员。
class child extends parent
{
......
}
(2)多态
多态指的是同一操作作用于不同的对象,会产生不同的执行结果。在PHP中通过重写来实现多态效果。
重写:在子类中添加该方法,对方法重新实现即可。
方法重写需符合两个要求:(1)方法的参数数量必须一致。(2)子类中重写的方法的访问级别应该“等于或弱于”父类中的被重写的方法的访问级别。
//父类文件:parent.class.php
class parent
{
protected function call(){
echo "这里是父类";
}
}
//子类文件:child.class.php
class child extends parent
{
protected function call(){
echo "这里是子类";
}
}
(3)final关键字
如果不希望某个类被继承,只能被实例化。可以通过final关键字来声明。
//定义child类,继承parent类
final class child extends parent
{
//本类不能被继承,只能被实例化
}
当一个类被继承时,所包含的final方法不能被子类重写。
//定义parent类
class parent
{
final protected function call(){
echo "该方法使用final关键字声明,不能被子类重写。";
}
}
(4)魔法方法
魔法方法:两个下划线开头的方法。不需自动调用。如:__construct()、__autoload()、__get()、__set()
__get()
这个方法用来获取私有成员属性,通过参数传入需要获取的成员属性的名称,即可获取属性值。
该方法会在获取不存在的或被访问修饰符限制访问的成员属性时自动调用,因为私有属性已经被封装,不能直接获取值(如“echo $p->name” 这样直接获取是错误的。)如果定义了__get($name)方法,在获取“$p->name”时,会将属性名“name”传给参数$name,然后就可以在__get()方法中获取到该私有属性并返回。
__set()
这个方法用来为私有成员属性设置属性值。有两个参数,第1个参数为属性名,第2个参数是要给属性设置的值。
该方法同样也是自动调用的。当需要在外部设置私有成员属性的值时(如$p1->name='张三';)通过定义__set($name,$value)方法,可以获取属性名“name”和属性值“张三”,分别保存在参数$name和$value中。然后就可以通过__set()方法为私有属性设置属性值。