『PHP学习笔记』系列十一:使用单例模式封装数据库操作类

版权声明:本文为博主原创文章,转载注明出处即可。 https://blog.csdn.net/SherlockHolmes_/article/details/84146534

了解设计模式:

定义:设计模式(Design pattern) 是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。 设计模式有很多,在PHP中通常只用两种设计模式

  • 单例模式

  • 工厂模式

单例模式:

有这么一种需求,希望一个类有且仅有一个对象,这样可以保证对象的完整性,我们将这种一个类最多只有一个对象称之为单例。 而通过代码实现这种单例的设计思路,我们称之为单例模式。    

数据表结构:

数据表部分数据:

封装数据库操作类: 

    目的:

                1,封装数据库操作类,是其成为通用工具类

                2,使用单例模式,让这个工具类在同一个的脚本中最多只能实例化一个对象

<?php
/**
 * 封装数据库操作类
 * 利用mysqli扩展实现数据库操作类
 * 封装成为通用工具类
 * 设计模式:单例模式-->一个类仅有一个对象,以保持对象的完整性
 * 注意:出现Using $this when not in object context错误信息的原因是在静态方法中使用$this来调用本类的方法,在php中,静态方法调用使用self。
 */
class Mysql
{
    //定义属性:私有属性->只能在数据库操作类中使用
    private static $link;
    private static $host;
    private static $port;
    private static $username;
    private static $password;
    private static $dbname;
    private static $charset;
    public static $instance = null;
    /**
     * 构造方法完成初始化
     * @param array $dbinfo = array(),数据参数传递(下标->为属性名->对应的值为属性的值)
     * 私有化构造方法:为了防止在类的外部无限实例化
     */
    private function __construct($dbinfo = array())
    {
        self::$host     = $dbinfo['host'] ?? 'localhost';
        self::$port     = $dbinfo['port'] ?? '3306';
        self::$username = $dbinfo['username'] ?? 'root';
        self::$password = $dbinfo['password'] ?? 'root';
        self::$dbname   = $dbinfo['dbname'] ?? 'chaldea';
        self::$charset  = $dbinfo['charset'] ?? 'utf8';
        //实现初始化
        self::dbInfo();
    }
    //私有化克隆方法:为了防止在类的外部无限克隆对象
    private function __clone()
    {}
    //定义函数getInstance()控制产生对象:不能无限new
    public static function getInstance()
    {
        //判定self::$instance是否是当前子类的对象
        if (is_null(self::$instance)) {
            //instanceof是Java、php的一个二元操作符(运算符),和==,>,<是同一类东西。
            //如果 $instance 是 self 的一个实例,则 instanceof 运算符返回 true。如果 $instance 不是指定类 self 的一个实例,或者 $instance 是 null,则返回 false。
            //没有对象:产生对象,保存到当前类的静态属性
            self::$instance = new Mysql;
        }
        //返回对象
        return self::$instance;
    }
    //连接认证:连接数据库
    public static function dbInfo()
    {
        self::$link = @mysqli_connect(self::$host, self::$username, self::$password, self::$dbname);
        //判定连接是否成功
        if (!self::$link) {
            //数据库连接失败->返回错误提示和错误信息
            echo 'Connect error:' . mysqli_connect_error(self::$link);
        }
    }
    //设定字符集
    public static function Setname()
    {
        $sql = "set names self::$charset";
        $res = @mysqli_query(self::$link, $sql);
        //判定
        if (!$res) {
            //SQL语句有误,返回错误信息,并终止执行
            echo "SQL指令有错误";
            echo "错误编号:" . mysqli_query_errno($res) . '<br/>';
            echo "错误信息:" . mysqli_query_error($res) . '<br/>';
            die();
        }
    }
    //优化函数:提取SQL执行和判定-->内部使用:私有化
    private static function dbExec($sql)
    {
        //利用mysqli_query执行SQL语句,并判断错误
        $res = @mysqli_query(self::$link, $sql);
        //判定
        if (!$res) {
            //SQL语句有误,返回错误信息,并终止执行
            echo "SQL指令有错误";
            echo "错误编号:" . mysqli_query_errno($res) . '<br/>';
            echo "错误信息:" . mysqli_query_error($res) . '<br/>';
            die();
        }
        //正确则返回结果
        return $res;
    }
    /**
     * 写入操作
     * @param string $sql,要执行的SQL命令->通过上面定义的优化函数实现
     * @return mysqli_affected_row() 返回受影响的行数
     */
    public static function dbWrite($sql)
    {
        $res = self::dbExec($sql);
        return mysqli_affected_rows(self::$link);
    }
    //获取自增长Id
    public static function dbInsertId()
    {
        //利用mysqli_insert_id()取出自增长Id
        return mysqli_insert_id(self::$link);
    }
    /**
     * 查询操作->查询单条数据
     * @param string $sql,要执行的SQL命令->通过上面定义的优化函数实现
     * @return mysqli_fetch_assoc()返回一个一维数组(NULL)
     */
    public static function dbGetOne($sql)
    {
        $res = self::dbExec($sql);
        return mysqli_fetch_assoc($res);
    }
    /**
     * 查询操作->查询全部数据
     * @param string $sql,要执行的SQL命令->通过上面定义的优化函数实现
     * @return mysqli_fetch_all()返回一个二维数组
     */
    public static function dbGetAll($sql)
    {
        $res = self::dbExec($sql);
        return mysqli_fetch_all($res, MYSQLI_ASSOC);
    }
    /**
     * 输出查询到的全部数据->foreach遍历输出
     * @param array $arr,查询全部数据返回的二维数组->自定义
     * @return echo输出遍历后的数组各项->表格的形式
     */
    public static function getForeach($arr)
    {
        //表格样式
        echo "<table border='2' bordercolor='#66ccff' align='center'>";
        foreach ($arr as $key => $value) {
            // echo $value['name'] . ' ';
            // echo $value['rank'] . '<br/>';
            echo "<tr>";
            echo "<td>id:" . $value["id"] . "</td>
            	  <td>职阶:" . $value["rank"] . "</td>
            	  <td>真名:" . $value["name"] . "</td>
            	  <td>性别:" . $value["sex"] . "</td>
            	  <td>属性:" . $value["attribute"] . "</td>
            	  <td>地域:" . $value["region"] . "</td>
            	  <td>出处:" . $value["source"] . "</td>
            	  <td>最大ATK:" . $value["ATK"] . "</td>
            	  <td>最大HP:" . $value["HP"] . "</td>";
            echo "</tr>";
        }
        echo "</table>";
    }
}
//测试代码
//实例化对象
$s1  = Mysql::getInstance();
$sql = 'select * from servant where id=34';
$arr = $s1::dbGetOne($sql);
//查询全部数据
// $s1::getForeach($arr);
// 查询单条数据
echo '<pre>';
var_dump($arr);
echo '</pre>';
//当第二次实例化时报错==>Notice: Undefined variable: s2 in D:\PHPBuilder\class\Mysql.php on line 160
$s2 == Mysql::getInstance();

查询全部数据时的运行结果: 

 查询单条数据时的运行结果:

 红圈部分:在单例模式下,一个类只能进行一次实例化,当进行第二次实例化是,系统会报错!

总结: 

1,单例模式就是设计的类最多只能得到一个对象

2,单例模式的设计规范就是“三私一公”

  • 私有化构造方法:禁止在类外无限实例化对象

  • 私有化克隆方法:禁止对象无限克隆对象

  • 私有化静态属性:保存类内部实例化得到的对象

  • 公有化静态方法:允许外部通过调用类内部方法获取对象,

3,单例模式如果还有其他功能诉求,可以在类中增加相应的其他类成员

4,单例模式的目的是为了保护资源的唯一性

猜你喜欢

转载自blog.csdn.net/SherlockHolmes_/article/details/84146534