PHP基礎之與MySQL那些事

雪痕*發表於2021-02-05

前言

這篇文章會對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();
    ?>

當我們提交頁面後,查詢資料庫,發現資料沒有變化,說明回滾有效果,事務控制起了效果,事務控制就說到這裡。以上就是本篇文章的全部內容啦,如有錯誤,請斧正。

相關文章