当前位置 博文首页 > 雪痕*:PHP基础之与MySQL那些事

    雪痕*:PHP基础之与MySQL那些事

    作者:雪痕* 时间:2021-02-05 22:24

    前言

    这篇文章会对PHP的MySQL扩展库,MySQLI的扩展库,SQL批量执行,事务控制等等进行一些简单的讲解。

    MySQL扩展

    PHP中MySQL扩展,虽然因为安全的原因,在PHP5.6及往上不在支持MySQL扩展库,但是还是要学习的,通过编写案例的方式来讲解。

    案例

    先说下操作数据库的大体思路吧,就是先获取连接-》选择数据库-》设置操作编码-》发送sql指令-》对返回的结果进行处理-》释放资源,断开连接。案例是一个在线词典查询。下面是创建表的sql语句:

        create database worddb
        create table words(
             id int primary key auto_increment,
             enword varchar(32) not null,
             chword varchar(256) not null
             );
        insert into words(enword,chword) values ('boy','男孩')
        insert into words(enword,chword) values ('school','学校')
    

    因为是练习,所以就插入了两条数据。接下来就是编写SQL工具类,代码如下:

    
        <?php
        class SqlTool{
            private $conn;
            private $host="localhost";
            private $user="root";
            private $password="XFAICL1314";
            private $db="worddb";
        	//初始化
            function SqlTool(){
                $this->conn=mysql_connect($this->host,$this->user,$this->password);
                if (!$this->conn){
                    die("连接数据库失败!".mysql_error());
                }
                mysql_select_db($this->db,$this->conn);
                mysql_query("set names utf8");
            }
            //完成select
            function execute_dql($sql){
                $res=mysql_query($sql) or die(mysql_error());
                return $res;
            }
        	//完成insert,update,delete
            function execute_dml($sql){
                $b=mysql_query($sql,$this->conn);
                if (!$b){
                    return 0;
                }else{
        			//因为有些情况执行成功,但没有行数影响,所以在判断一下。
                    if (mysql_affected_rows($this->conn)>0){
                        return 1;
                    }else{
                        return 2;
                    }
                }
            }
        }
        ?>
    

    之后就是前端页面的编写了,代码如下,有点丑:

    
        <html>
        <head>
            <title>在线词典</title>
            <meta http-equiv="content-type" charset="UTF-8">
        </head>
        <body>
        <center><h1>字典</h1></center>
        <h2>查询英文</h2>
        <form action="wordprocess.php" method="post">
            请输入英文:<input type="text" name="yingyu">
        			<!--为了区分两个表单,这里选择用隐藏域的方式-->
                    <input type="hidden" value="search1" name="type">
                <input type="submit" value="提交">
        </form>
        <h2>查询中文</h2>
        <form action="wordprocess.php" method="post">
            请输入中文:<input type="text" name="hanyu">
        	<!--为了区分两个表单,这里选择用隐藏域的方式-->
            <input type="hidden" value="search2" name="type">
            <input type="submit" value="提交">
        </form>
        </body>
        </html>
    

    接下来就是后端逻辑代码了,如下:

    
        <?php
        //引入工具类
        require_once 'SqlTool.class.php';
        header("Content-type:text/html;charset=utf-8");
        if (isset($_POST['type'])){
            $type=$_POST['type'];
        }else{
            echo "查询失败<br>";
            echo "<a href='wordVeiw.php'>回到主页面</a>";
        }
        if ($type=="search1") {
            if (isset($_POST[yingyu])) {
                $en_word = $_POST[yingyu];
            } else {
                echo "请输入";
                echo "<a href='wordVeiw.php'>回到主页面</a>";
            }
            $sql = "select chword from words where enword='" . $en_word . "' limit 0,1";
            //查询,调用sql工具类
            $SqlTool = new SqlTool();
            $res = $SqlTool->execute_dql($sql);
            if ($row = mysql_fetch_assoc($res)) {
                echo $en_word . "对应的中文为" . $row['chword'];
            } else {
                echo "查询没有这个词条.<br>";
                echo "<a href='wordVeiw.php'>回到主页面</a>";
            }
        	//释放资源
            mysql_free_result($res);
        }else if($type == "search2") {
            if (isset($_POST[hanyu])) {
                $ch_word = $_POST[hanyu];
            } else {
                echo "请输入";
                echo "<a href='wordVeiw.php'>回到主页面</a>";
            }
            $sql = "select enword from words where chword like '%" . $ch_word . "%'";
        
            //查询,调用sql工具类
            $SqlTool = new SqlTool();
            $res = $SqlTool->execute_dql($sql);
            if (mysql_num_rows($res) != 0) {
                while ($row = mysql_fetch_assoc($res)) {
                    echo "<br>".$ch_word . "对应的英文为" . $row['enword'];
                }
            } else {
                echo "查询没有这个词条.<br>";
                echo "<a href='wordVeiw.php'>回到主页面</a>";
            }
        	//释放资源
            mysql_free_result($res);
        }
        ?>
    

    现在来测试一下吧,首先打开前端页面,如下图:

    接下来输入boy进行查询,结果如下,查询成功:

    因为是案例,所以直接将前端传过来的参数没有做任何处理直接拼接到SQL语句中,这样是非常危险的!!,存在SQL注入攻击,现在我来演示一下,在输入框中输入:
    boy' and updatexml(1,concat(0x7e,(select user()),0x7e),1)#
    结果如下图直接报出使用者!!

    所以在开发功能时,要秉持“外部参数皆不可信原则”进行开发

    MYSQLI扩展

    其实mysqli扩展是mysql扩展的加强版,因为历史原因,有一些老程序员擅长面向过程写法,所以PHP设计者为mysqli设计了两套方案,一套面向对象,一套面向过程,甚至一个聊本里可以混着用,不过那样很怪,下面的案例都是采用面向对象的那套方案。

    案例

    做一个小功能吧,向数据库中插入数据。先设计一下SQL表,语句如下:

    
        create database day1;
        use day1;
        create table user1 (
        id int(6) unsigned auto_increment primary key,
        name varchar(20) not null,
        password varchar(256) not null,
        email varchar(80)  not null,
        age int(128) not null
         );
        ?
        INSERT INTO user1(name,password,email,age) VALUES('Lucia','13568','12345@.com',30);
    

    因为一会儿要插入数据,所以先插入一条,构造好后,打开数据库,查询,发现没有问题

    接下来构造mysqli工具类代码如下:

    <?php
    class SqlTest{
        private $mysqli;
        private $host="localhost";
        private $user="root";
        private $pass="XFAICL1314";
        private $db="day1";
    	//初始话
        public function __construct(){
            $this->mysqli=new mysqli($this->host,$this->user,$this->pass,$this->db);
            if ($this->mysqli->connect_error){
                echo "连接失败";
            }
            $this->mysqli->query("set names utf8");
        }
    	//进行select
        public function execute_dql($sql){
            $res=$this->mysqli->query($sql) or die($this->mysqli->error);
            return $res;
        }
    	//进行update,insert,delete
        public function execute_dml($sql){
            $res=$this->mysqli->query($sql) or die($this->mysqli->error);
            if (!$res){
                return 0;
            }else{
                if ($this->mysqli->affected_rows>0){
                    return 1;//成功
                }else{
                    return 2;//没有行数收影响
                }
            }
        }
    }
    ?>
    

    下面就是前端页面了,这里我用表单向后端提交数据,代码如下:

    
        <html>
        <head>
            <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
            <center><title>添加联系人</title></center>
            <style type="text/css">
                div{
                    background-color: aqua;
                    width: 1250px;
                    height: 500px;
                }
                div{
                    text-align: center;
                }
            </style>
        </head>
        <body>
        <div>
            <div>
                <form action="addprocess.php" method="post">
                    <br><br><br><br><br>
                    姓名:<input type="text" name="user"><br><br>
                    密码:<input type="password" name="password"><br><br>
                    email:<input type="text" name="email"><br><br>
                    年龄:<input type="text" name="age"><br><br>
                    <input type="submit" value="提交" style="height: 36px;width: 60px;background-color: blue;color: azure;border: 0px">&nbsp;&nbsp;&nbsp;&nbsp;
                    <input type="reset" value="重置" style="height: 36px;width: 60px;background-color: blue;color: azure;border: 0px">
                </form>
            </div>
        </div>
        
        
        </body>
        </html>
    

    效果如下图:

    然后就是后端的逻辑设计了,代码如下:

    
        <?php
        //引入工具类
        require_once 'SqlTest.class.php';
        //创建实例
        $SqlTest=new SqlTest();
        $sql="insert into user1 (name,password,email,age) values ('$_POST[user]',md5('$_POST[password]'),'$_POST[email]','$_POST[age]')";
        $res=$SqlTest->execute_dml($sql);
        if ($res==1){
            echo "添加成功";
        }else{
            if ($res==0){
                echo '添加失败';
            }else{
                echo "行数没有变化";
            }
        }
        ?>
    

    现在测试一下,我们在表单页面输入 小明,12345678,123@qq.com,25 数据,如下图:

    然后提交表单,看看有没有插入到数据库中。
    我们发现成功插入到数据库中如下:

    关于mysqli扩展就说到这里。

    MySQL批量执行SQL语句

    上面简单介绍了MySQL扩展和MySQLI扩展,接下来说一说批量执行sql语句。
    先提一个需求,如果我们像数据库批量添加用户,如果按照之前的办法一条一条的发送sql语句来处理,这样很占用资源,并且效率低。所以采用批量执行sql语句的方式。接下来用两个案例来讲解,因为增加,修改,删除操作返回的是布尔值,而查询操作返回的是结果集,所以分来来处理比较好。

    批量执行dml语句

    因为dml返回的是布尔值,所以处理起来也比较好处理。先创建表,顺便插入一条数据如下:

    
        create database test;
        use test;
        create table users(
             id int(8) unsigned auto_increment primary key,
             name varchar(128) not null,
             password varchar(256) not null);
        insert into users(name,password) values('test','13579');
    

    下面就是批量执行dml操作的代码:

    
        <?php
        $mysqli=new mysqli("localhost","root","XFAICL1314","test");
        if ($mysqli->connect_error){
            echo "连接失败";
        }
        $sqli="insert into users(name,password) values ('小利',md5('13568'));";
        //批量执行dml操作时,注意上一级句的;和下一句的.两个符号
        $sqli.="insert into users(name,password) values ('小利',md5('13568'));";
        $sqli.="insert into users(name,password) values ('小利和小峰',md5('13568'))";
        
        $b=$mysqli->multi_query($sqli);
        if (!$b){
            echo "插入失败";
        }else{
            echo "ok!";
        }
        $mysqli->close();
        ?>
    

    然后访问页面,返回ok,说明插入到数据库了,现在打开数据库查看,果然插入进去了,如下图:

    批量执行dql操作

    批量执行dql操作的作用是一次性取回多个结果集,下面看案例代码:

    
        <?php
        header("Content-type:text/html;charset=utf-8");
        $mysqli=new mysqli("localhost","root","XFAICL1314","test");
        if ($mysqli->connect_error){
            echo "连接失败";
        }
        $sqli="select * from users;";
        $sqli.="select * from lsp";
        //因为multi_query这个函数比较傻,不会去判断有没有下一个结果集,所以最后再用more_results函数检查一下。
        if ($mysqli->multi_query($sqli)){
            do{     //从mysqli中取出第一个结果集
                $result=$mysqli->store_result();
                    //显示mysqli $res对象
                    while ($row=$result->fetch_row()){
                        foreach ($row as $key=>$val){
                            echo "--$val";
                        }
                        echo "<br>";
                    }
                        $result->free();
                    //判断有没有下一个结果集,如果没有退出循环
                    if (!$mysqli->more_results()){
                        break;
                    }
                    echo "<br>*************新得结果集<br/>";
            } while ($mysqli->next_result());
        }
        ?>
    

    结果如下图:

    关于MySQL的批量执行sql语句就说到这里。

    MySQL事务控制

    上面简单介绍了MySQL扩展库,MySQLI扩展库,批量执行SQL语句,接下来说一说MySQL事务控制。

    数据库配置

    说MySQL事务控制之前,先查看并修改数据库引擎,查看引擎的命令如下:

    show engines

    我们发现,只有InnoDB是支持事务的,所以先查看一下现在得数据库引擎:

    发现是MyISAM,我们将它修改为InnoDB,打开配置文件my.ini,将“default-storage-engine=MYISAM”改为你想设定的,然后重启即可。修改成功后,然后下一步就是代码实现。

    案例

    我们为什么需要事务控制呢?想一想,如果这是一个转账得场景,是不是需要同时控制住,必须我减金额得同时你加金额,任何一个出错都得转账失败。也就是说要保持一致。这也是要进行事务控制得必要性。下面看案例代码:

    
        <?php
        header("Content-type:text/html;charset=utf-8");
        $mysqli=new mysqli("localhost","root","XFAICL1314","test");
        if ($mysqli->connect_error){
            echo "连接失败";
        }
        //将提交设置为假,因为事物一旦提交就没有机会回滚
        $mysqli->autocommit(false);
        
        $sql1="update  person set money=money-3 where id=1";
        //这里第二条语句我故意写错表名
        $sql2="update  persons set money=money+3 where id=2";
        
        $b1=$mysqli->query($sql1);
        $b2=$mysqli->query($sql2);
        if (!$b1 || !$b2){
            echo "修改失败,回滚".$mysqli->error;
            $mysqli->rollback();
        }else{
            echo "修改成功!";
            $mysqli->commit();
        }
        $mysqli->close();
        ?>
    

    当我们提交页面后,查询数据库,发现数据没有变化,说明回滚有效果,事务控制起了效果,事务控制就说到这里。以上就是本篇文章的全部内容啦,如有错误,请斧正。

    bk
    下一篇:没有了