PHP基礎之與MySQL那些事

前言

這篇文章會對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','[email protected]',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,[email protected],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();
    ?>

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

Tags: