[PHP] mysqli使い方まとめ(MySQL接続~SELECT実行まで)

  • 114
    Like
  • 4
    Comment

PHP5.5から mysql_connect()mysql_query() など、mysql_***系の関数は非推奨となりました。新方式の1つである mysqli の使い方をまとめておきます。(他にはPDO方式があります)

churippu_s.png 手続き型とオブジェクト型

mysqli の書き方には大きく2通りあります。
 ◎手続き型:従来とよく似た mysqli_***() という書き方(インスタンス生成不要)
 ◎オブジェクト型:オブジェクト指向的な書き方(インスタンス生成必要)

例)DBへの接続

手続き型
// DB接続例:mysqli_xxx関数を使う
$link = mysqli_connect("Host or IP", "User", "Pass", "DBName");
オブジェクト型
// DB接続例:mysqliクラスをオブジェクト化してから使う
$mysqli = new mysqli('Host or IP', 'User', 'Pass', 'DBName');

本ページでは、主に後者のオブジェクト型の書き方について記載します。

churippu_s.png DBへの接続〜切断

PHP
<?php
// mysqliクラスのオブジェクトを作成
$mysqli = new mysqli('Host or IP', 'User', 'Pass', 'DBName');
if ($mysqli->connect_error) {
    echo $mysqli->connect_error;
    exit();
} else {
    $mysqli->set_charset("utf8");
}

// ここにDB処理いろいろ書く(後述)

// DB接続を閉じる
$mysqli->close();
?>

churippu_s.png SELECT(簡易方式)

完成しているSQLをqueryメソッドでそのまま実行する方式です。

PHP
// 完成済みのSELECT文を実行する
$sql = "SELECT user_id, name FROM user_table";
if ($result = $mysqli->query($sql)) {
    // 連想配列を取得
    while ($row = $result->fetch_assoc()) {
        echo $row["user_id"] . $row["name"] . "<br>";
    }
    // 結果セットを閉じる
    $result->close();
}

SELECT件数の取得:

PHP
// オブジェクト型
echo "rows=" . $result->num_rows;

// 手続き型
echo "rows=" . mysqli_num_rows($result);

churippu_s.png SELECT(バインド方式)

SQLの一部を「?」としておき、あとから変数の値で補う(バインドする)方式です。

PHP
// SELECT文のひな型をもとにステートメントハンドルを取得する
$sql = "SELECT user_id, name FROM user_table WHERE user_id=? AND name=?";
if ($stmt = $mysqli->prepare($sql)) {
    // 条件値をSQLにバインドする(補足参照)
    $user_id = 123;
    $name = "hanako";
    $stmt->bind_param("is", $user_id, $name);

    // 実行
    $stmt->execute();

    // 取得結果を変数にバインドする
    $stmt->bind_result($user_id, $name);
    while ($stmt->fetch()) {
        echo "ID=$user_id, NAME=$name<br>"; 
    }
    $stmt->close();
}

SELECT件数の取得:

PHP
$stmt->store_result(); // これ忘れるとnum_rowsは0
echo "rows=" . $stmt->num_rows;

バインド式の補足:

$stmt->bind_param("is", $user_id, $name);の第1引数 "is" は後続のデータ型を表します。i=integer、s=string、d=double、b=blob など。DATE型は s で良いみたいです。
また下記のように値を引数内に直書きすることはできません。
誤)$stmt->bind_param("is", 123, "hanako");

churippu_s.png 応用例

使いやすいようにクラス化してみる。(DB接続情報は適宜変更して下さい)

MyDB.class.php
<?php
/*
 * MyDBクラス
 */
class MyDB
{
    public $mysqli; // mysqliオブジェクト
    public $mode;   // 戻り値の形式:"json" or "array"(連想配列)
    public $count;  // SQLによって取得した行数 or 影響した行数

    // コンストラクタ
    function __construct($mode = "json") 
    {
        $this->mode = $mode;

        // DB接続
        $this->mysqli = new mysqli('localhost', 'DB-USER', 'DB-PASS', 'DB-NAME');
        if ($this->mysqli->connect_error) {
            echo $this->mysqli->connect_error;
            exit;
        } else {
            $this->mysqli->set_charset("utf8");
        }
    }

    // デストラクタ
    function __destruct()
    {
        // DB接続を閉じる
        $this->mysqli->close();
    }

    // SQL実行(SELECT/INSERT/UPDATE/DELETE に対応)
    function query($sql)
    {
        // SQL実行
        $result = $this->mysqli->query($sql);
        // エラー
        if ($result === FALSE) {
            // エラー内容
            $error = $this->mysqli->errno.": ".$this->mysqli->error;
            // 戻り値
            $rtn = array(
                'status' => FALSE,
                'count'  => 0,
                'result' => "",
                'error'  => $error
            );
            if($this->mode == "array")
                return $rtn;
            else
                return json_encode($rtn); // JSON形式で返す(デフォルト)
        }

        // SELECT文以外
        if($result === TRUE) {
            // 影響のあった行数を格納
            $this->count = $this->mysqli->affected_rows;
            // 戻り値
            $rtn = array(
                'status' => TRUE,
                'count'  => $this->count,
                'result' => "",
                'error'  => ""
            );
            if($this->mode == "array")
                return $rtn;
            else
                return json_encode($rtn); // JSON形式で返す(デフォルト)
        } 
        // SELECT文
        else {
            // SELECTした行数を格納
            $this->count = $result->num_rows;
            // 連想配列に格納
            $data = array();
            while ($row = $result->fetch_assoc()) {
                $data[] = $row;
            }
            // 結果セットを閉じる
            $result->close();
            // 戻り値
            $rtn = array(
                'status' => TRUE,
                'count'  => $this->count,
                'result' => $data,
                'error'  => ""
            );
            if($this->mode == "array")
                return $rtn;
            else
                return json_encode($rtn); // JSON形式で返す(デフォルト)
        }
    }

    // 文字列をエスケープする
    function escape($str)
    {
        return $this->mysqli->real_escape_string($str);
    }
}
?>

使い方

php
$db = new MyDB();
echo $db->query("SELECT * FROM USERTABLE");

結果(JSON形式の文字列)

json
{
    "status": true,
    "count" : 2,
    "result": [
        {"UserID":"aaa", "Name":"AppleMan"},
        {"UserID":"bbb", "Name":"BananaMan"}
    ],
    "error" : ""
}

補足

JSON形式の文字列に変換する json_encode($ary) は、通常だと日本語が \uXXXX 形式(Unicodeエスケープシーケンス)になってしまいます。PHP5.4以降では、
json_encode($ary, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
とすることで、日本語のまま扱えます。

(・o・ゞ いじょー。

churippu_s.png 参考URL

mysqli_result::fetch_assoc: 結果の行を連想配列で取得する
http://www.phppro.jp/phpmanual/php/mysqli-result.fetch-assoc.html

mysqli - プリペアドステートメント
http://blog.livedoor.jp/nakamura_tech/archives/51311243.html

【PHP】mysqliとプリペアドステートメントについて|Furudateのブログ
http://furudate.hatenablog.com/entry/2013/10/04/211422

PHPでデータベースに接続するときのまとめ
http://qiita.com/mpyw/items/b00b72c5c95aac573b71

MySQL 改良版拡張モジュール|PHP: MySQLi - Manual
http://php.net/manual/ja/book.mysqli.php