面向对象基础----封装数据库操作类

思考:现在掌握了很多面向对象相关的内容,但是什么时候封装类?怎么封装?如果使用类成员?

引入:其实类的封装没有多么复杂,但是需要一个熟练的过程来确定哪些东西可以放到类里,该用什么样的形式等。我们通过封装一个数据库的操作来综合练习下

封装数据库类 掌握

定义:封装数据库操作类,即根据数据库的操作需求,来确认数据库操作类该有什么样的功能,以及这些功能该如何实现。

1.一个类通常就是一个文件,所以要先确定文件的名字:通常类文件命名规范有两种。

  •   文件名字与类名一样,如Sql.php
  •   为了区分普通php文件,增加中间类描述,如Sql_class.php
  •   现在php几乎都是面向对象变成,所以通常采用第一种方式:因此当前命名规范数据类的文件为:Sql_php

2.确定类文件名字后其实也就是确定了类名字,因此可以创建一个Sql类。

<?php
//数据库操作类
class Sql{

}


?>

3.类的创建分两种:一是特定使用,即类里面的所有内容只为某次使用;二是通用,即工具类,以后很多地方可以用;

  特定使用,功能可以不同太灵活

  通用工具,功能应该大众化,数据的变化会比较多

数据库类以后凡是要操作数据库的地方都可以用得到,很多项目都会用到,所以应该是个通用类工具,因此要考虑其到处可用的特性,让其能够灵活。

4.数据库的错操最基本的特性不会改变,即需要连接认证  而连接认证的信息是灵活的,所以可以通过设定属性来控制,这些信息也都是不同使用这不同的

应该可以改变,所以可以通过__construct来实现数据传入

<?php
//数据库操作类
class Sql{

    //设置属性
    public $host;
    public $user;
    public $pwd;
    public $port;
    public $dbname;
    public $charset;
    //构造方法初始化数据,数据较多,应该使用数组来传递数据,关联数组,而绝大部分的开发者本意是用来测试,
    //所以基本都是本地,因此可以给默认数据

    public function __construct(array $info=array())
    {
        //这里的??表示为 $a=$c??$b 等同于 $a=isset($c)?$c:$b; 如果变量c存在就等于c否则等于b
        $this->host=$info['host']??'localhost';
        $this->user=$info['user']??'root';
        $this->pwd=$info['pwd']??'root';
        $this->port=$info['port']??'3306';
        $this->dbname=$info['dbname']??'t1';
        $this->charset=$info['charset']??'utf8';
    }
}

$info =array(0=>'sdfsdf',1=>'sdf',2=>'sdfsdf');
print_r($info);

?>

注意:方法设定的原则是一个方法只实现一个简单的功能,不要多个功能堆积到一个方法中。

5.数据库属性会在实例化sql对象的时候自动初始化

<?php
//数据库操作类
class Sql{

    //设置属性
    public $host;
    public $user;
    public $pwd;
    public $port;
    public $dbname;
    public $charset;

    //初始化构造方法
    public function __construct(array $info=array())
    {
        //这里的??表示为 $a=$c??$b 等同于 $a=isset($c)?$c:$b; 如果变量c存在就等于c否则等于b
        //以上功能只有php 版本7.0 以上可以用
        $this->host=$info['host'] ?? 'localhost';
        $this->user=$info['user'] ?? 'root';
        $this->pwd=$info['pwd'] ?? 'root';
        $this->port=$info['port'] ?? '3306';
        $this->dbname=$info['dbname'] ?? 't1';
        $this->charset=$info['charset'] ?? 'utf8';
    }
}


    $s1=new Sql();     //使用默认数据库信息
    $db=array(
        'host'=>'localhost',
        'user'=>'root',
        'pwd'=>'root',
        'dbname'=>'t1'
    );
    $s2=new Sql($db);
    var_dump($s1);
    var_dump($s2)

?>

6.数据库要操作的第一件事情就是要验证,所以需要一个连接认证的功能,这里可以使用mysqli面向对象的方法,但是需要建立一个方法来实现连接认证

连接是否成功?

  

<?php
//数据库操作类
class Sql{

    //设置属性
    public $host;
    public $user;
    public $pwd;
    public $port;
    public $dbname;
    public $charset;

    //初始化构造方法
    public function __construct(array $info=array()){
        //这里的??表示为 $a=$c??$b 等同于 $a=isset($c)?$c:$b; 如果变量c存在就等于c否则等于b
        //以上功能只有php 版本7.0 以上可以用
        $this->host=$info['host'] ?? 'localhost';
        $this->user=$info['user'] ?? 'root';
        $this->pwd=$info['pwd'] ?? 'root';
        $this->port=$info['port'] ?? '3306';
        $this->dbname=$info['dbname'] ?? 't1';
        $this->charset=$info['charset'] ?? 'utf8';
    }
    //认证数据库连接
    public function sql_connet(){
        //利用mysqli属性可以跨方法访问:5个参数分别为:主机,用户,密码,数据库,端口
        $link=new mysqli($this->host,$this->user,$this->pwd,$this->dbname,$this->port);
        if($link->connect_errno){
            die( $link->connect_error);
        }
    }
}

$s=new Sql();
$s->sql_connet();    //正常 没有错误

7.用户调用sql类的目的一定是为了操作数据库,那么用户在实例化之后就需要调用连接认证方法,为了方便用户操作,可以帮助用户省去调用这一步骤:在构造方法中调用该方法

<?php
//数据库操作类
class Sql{

    //设置属性
    public $host;
    public $user;
    public $pwd;
    public $port;
    public $dbname;
    public $charset;

    //初始化构造方法
    public function __construct(array $info=array()){
        //这里的??表示为 $a=$c??$b 等同于 $a=isset($c)?$c:$b; 如果变量c存在就等于c否则等于b
        //以上功能只有php 版本7.0 以上可以用
        $this->host=$info['host'] ?? 'localhost';
        $this->user=$info['user'] ?? 'root';
        $this->pwd=$info['pwd'] ?? 'root';
        $this->port=$info['port'] ?? '3306';
        $this->dbname=$info['dbname'] ?? 't1';
        $this->charset=$info['charset'] ?? 'utf8';
        $this->sql_connet();
    }
    //认证数据库连接
    public function sql_connet(){
        //利用mysqli属性可以跨方法访问:5个参数分别为:主机,用户,密码,数据库,端口
        $link=new mysqli($this->host,$this->user,$this->pwd,$this->dbname,$this->port);
        if($link->connect_errno){
            die( $link->connect_error);
        }
    }
}

$s=new Sql();
// $s->sql_connet();    //正常 没有错误




    
?>

8.至此,一旦实例化sql类对象,就可以实现数据库的连接,但是此时还存在一个细节问题,字符集,为了保证数据库连接正常操作,需要新增一个方法设定字符集

<?php
//数据库操作类
class Sql{

    //设置属性
    public $host;
    public $user;
    public $pwd;
    public $port;
    public $dbname;
    public $charset;
    //增加一个属性来保存mysqli返回的连接(对象),需要跨方法使用
    public $link;

    //初始化构造方法
    public function __construct(array $info=array()){
        //这里的??表示为 $a=$c??$b 等同于 $a=isset($c)?$c:$b; 如果变量c存在就等于c否则等于b
        //以上功能只有php 版本7.0 以上可以用
        $this->host=$info['host'] ?? 'localhost';
        $this->user=$info['user'] ?? 'root';
        $this->pwd=$info['pwd'] ?? 'root';
        $this->port=$info['port'] ?? '3306';
        $this->dbname=$info['dbname'] ?? 't1';
        $this->charset=$info['charset'] ?? 'utf8';
        //调用连接认证方法
        $this->sql_connet();
        //调用字符集方法
        $this->sql_charset();
    }
    //认证数据库连接
    public function sql_connet(){
        //利用mysqli属性可以跨方法访问:5个参数分别为:主机,用户,密码,数据库,端口
        $this->link=new mysqli($this->host,$this->user,$this->pwd,$this->dbname,$this->port);
        if($this->link->connect_errno){
            die( $this->link->connect_error);
        }
    }
    //设置字符集
    public function sql_charset(){
        $sql="set names {$this->charset}";
        //mysqli::query();
        $res=$this->link->query($sql);
        //有外部调用就会有错误,判断
        if(!$res){
            die('charset error'.$this->link->error);
        }
    }
}

$s=new Sql(array('charset'=>'utf-8'));    //会报错   应该是utf8
var_dump($s);

9.至此:数据库的初始化操作已经完成,此时要考虑的事情使用户调用数据库类是为了干什么?为了执行sql指令,也就是增删改查,在mysqli中所有的sql执行都是通过mysqli::query()方法执行

但是我们可以根据需求封装两个函数,写方法和查方法(包含一条和多条查询)。

<?php
//数据库操作类
class Sql{

    //设置属性
    public $host;
    public $user;
    public $pwd;
    public $port;
    public $dbname;
    public $charset;
    //增加一个属性来保存mysqli返回的连接(对象),需要跨方法使用
    public $link;

    //初始化构造方法
    public function __construct(array $info=array()){
        //这里的??表示为 $a=$c??$b 等同于 $a=isset($c)?$c:$b; 如果变量c存在就等于c否则等于b
        //以上功能只有php 版本7.0 以上可以用
        $this->host=$info['host'] ?? 'localhost';
        $this->user=$info['user'] ?? 'root';
        $this->pwd=$info['pwd'] ?? 'root';
        $this->port=$info['port'] ?? '3306';
        $this->dbname=$info['dbname'] ?? 't1';
        $this->charset=$info['charset'] ?? 'utf8';
        //调用连接认证方法
        $this->sql_connet();
        //调用字符集方法
        $this->link->set_charset($this->charset);

        // 调用字符集方法
        // $this->sql_charset();   //也是可以的
    }
    //认证数据库连接
    public function sql_connet(){
        //利用mysqli属性可以跨方法访问:5个参数分别为:主机,用户,密码,数据库,端口
        $this->link=new mysqli($this->host,$this->user,$this->pwd,$this->dbname,$this->port);
        if($this->link->connect_errno){
            die( $this->link->connect_error);
        }
    }
    // //设置字符集,这么写有点麻烦
    // public function sql_charset(){
    //     $sql="set names {$this->charset}";
    //     //mysqli::query();
    //     $res=$this->link->query($sql);
    //     //有外部调用就会有错误,判断
    //     if(!$res){
    //         die('charset error'.$this->link->error);
    //     }
    // }


    //写操作
    public function sql_insert($sql){
        $result=$this->link->query($sql);
        return $result;
    }
}

$s=new Sql();
$sql="insert into b1 (name,age,sex) values ('杜家铭',9,'男')";
$s->sql_insert($sql);
<?php
//数据库操作类
class Sql{

    //设置属性
    public $host;
    public $user;
    public $pwd;
    public $port;
    public $dbname;
    public $charset;
    //增加一个属性来保存mysqli返回的连接(对象),需要跨方法使用
    public $link;

    //初始化构造方法
    public function __construct(array $info=array()){
        //这里的??表示为 $a=$c??$b 等同于 $a=isset($c)?$c:$b; 如果变量c存在就等于c否则等于b
        //以上功能只有php 版本7.0 以上可以用
        $this->host=$info['host'] ?? 'localhost';
        $this->user=$info['user'] ?? 'root';
        $this->pwd=$info['pwd'] ?? 'root';
        $this->port=$info['port'] ?? '3306';
        $this->dbname=$info['dbname'] ?? 't1';
        $this->charset=$info['charset'] ?? 'utf8';
        //调用连接认证方法
        $this->sql_connet();
        //调用字符集方法
        $this->link->set_charset($this->charset);

        // 调用字符集方法
        // $this->sql_charset();   //也是可以的
    }
    //认证数据库连接
    public function sql_connet(){
        //利用mysqli属性可以跨方法访问:5个参数分别为:主机,用户,密码,数据库,端口
        $this->link=new mysqli($this->host,$this->user,$this->pwd,$this->dbname,$this->port);
        if($this->link->connect_errno){
            die( $this->link->connect_error);
        }
    }
    // //设置字符集,这么写有点麻烦
    // public function sql_charset(){
    //     $sql="set names {$this->charset}";
    //     //mysqli::query();
    //     $res=$this->link->query($sql);
    //     //有外部调用就会有错误,判断
    //     if(!$res){
    //         die('charset error'.$this->link->error);
    //     }
    // }


    //写操作
    public function sql_insert($sql){
        $result=$this->link->query($sql);
        return $result;
    }

    //  读操作sql_select() 第一个参数为sql语句,第二个参数表示返回单条还是多条默认单条
    public function sql_select($sql,$all=false){
        $result=$this->link->query($sql);     
        if(!$all){
            // 获取一个数据
            return $result->fetch_assoc();
        }else{
            //获取所有数据
            return $result->fetch_all(MYSQLI_ASSOC);
        }

    }
}

$s=new Sql();
$sql="select * from b1";
print_r($s->sql_select($sql,true));

10.上述已经完成了数据库类要实现的基本功能,实现sql指令的执行和结果返回,但是从功能细节的角度触发还需要进行完善,插入操作后,要获取自增长id,更新和删除操作受影响的行数,查询操作中

记录数量。这种使可以通过设置方式来实现获取(自增长id),也可以通过增加属性来实现(属性简单)

增加属性:受影响的行数,自增长id ,查询记录数

<?php
//数据库操作类
class Sql{

    //设置属性
    public $host;
    public $user;
    public $pwd;
    public $port;
    public $dbname;
    public $charset;
    //增加一个属性来保存mysqli返回的连接(对象),需要跨方法使用
    public $link;

    //初始化构造方法
    public function __construct(array $info=array()){
        //这里的??表示为 $a=$c??$b 等同于 $a=isset($c)?$c:$b; 如果变量c存在就等于c否则等于b
        //以上功能只有php 版本7.0 以上可以用
        $this->host=$info['host'] ?? 'localhost';
        $this->user=$info['user'] ?? 'root';
        $this->pwd=$info['pwd'] ?? 'root';
        $this->port=$info['port'] ?? '3306';
        $this->dbname=$info['dbname'] ?? 't1';
        $this->charset=$info['charset'] ?? 'utf8';
        //调用连接认证方法
        $this->sql_connet();
        //调用字符集方法
        $this->link->set_charset($this->charset);

        // 调用字符集方法
        // $this->sql_charset();   //也是可以的
    }
    //认证数据库连接
    public function sql_connet(){
        //利用mysqli属性可以跨方法访问:5个参数分别为:主机,用户,密码,数据库,端口
        $this->link=new mysqli($this->host,$this->user,$this->pwd,$this->dbname,$this->port);
        if($this->link->connect_errno){
            die( $this->link->connect_error);
        }
    }
    // //设置字符集,这么写有点麻烦
    // public function sql_charset(){
    //     $sql="set names {$this->charset}";
    //     //mysqli::query();
    //     $res=$this->link->query($sql);
    //     //有外部调用就会有错误,判断
    //     if(!$res){
    //         die('charset error'.$this->link->error);
    //     }
    // }


    //写操作
    //自增id
    public $auto_id;
    public function sql_insert($sql){
        $result=$this->link->query($sql);
        //赋值受影响的自增列id
        $this->auto_id=$this->link->insert_id;
        return $result;
    }

    //  读操作sql_select() 第一个参数为sql语句,第二个参数表示返回单条还是多条默认单条
    //受影响行数
    public $rows;
    public function sql_select($sql,$all=false){
        $result=$this->link->query($sql);   
        // 赋值受影响的行数
        $this->rows=$result->num_rows; 
        if(!$all){
            // 获取一个数据
            return $result->fetch_assoc();
            //赋值受影响行数
        }else{
            //获取所有数据
            return $result->fetch_all(MYSQLI_ASSOC);
            //赋值受影响行数
        }

    }
}

// $s=new Sql();
// $sql="insert into b1 (name,age,sex) values ('杜建',33,'女')";
// $s->sql_insert($sql);
// echo $s->auto_id;    //返回7   

$s=new Sql();
$sql="select * from b1 where id=7";
print_r($s->sql_select($sql));
echo '<hr>';
echo $s->rows;





    
?>

至此:数据库类的功能已经实现,接下里要考虑的定义规范:类对成员的控制性,

  属性如果不需要给外部访问   私有

  方法如果只是内部调用       私有

总结:

  类的封装是以功能驱动为前提,相关操作存放到一个类中

  一个类通常是一个独立的文件,文件名与类名相同(方便后期维护和自动加载)

  类中如果有数据需要管理,设定属性(固定可以使用类常量)

  类中如果有功能需要实现,(数据加工)  设定方法

  一个功能通常使用一个方法实现,方法的颗粒度应该尽可能小   方便复用

原文地址:https://www.cnblogs.com/xiaowie/p/12237747.html