PHPからAccessDBに接続する


今どき・・・な感じですが、ある案件でPHPからAccessDBに接続して情報を取得する必要があったのでそのメモです。
ネットで調べてもあんまり情報がなかったので残します。
単にPHP-->Accessっていうパターンが少ないだけだとは思うのですが。

環境

PHP7.2 32bit
Apache 2.4 32bit
Access 2010(2017でもOK) 32bit

大事なところ

あまりないかもしれませんが、Accessが32bitならばPHP、Apacheも32bitで揃える。
64bitであれば64bitで揃えないと正しく動きません。(少なくとも私の環境では動かなかった)

接続

PDOで接続します。

db.php

define('ACCESS_DB_DRIVER',   '{Microsoft Access Driver (*.mdb, *.accdb)}');
define('ACCESS_DBQ',         'C:\\test\\test_be.accdb');
define('ACCESS_DB_USER',     '');
define('ACCESS_DB_PASSWORD', '');

$objPdo = new PDO("odbc:Driver=" . ACCESS_DB_DRIVER . ";Dbq=" . ACCESS_DBQ . "; Uid=" . ACCESS_DB_USER . "; Pwd=" . ACCESS_DB_PASSWORD . " ;");

Driver

データソースのドライバーの部分を指定します。

DBQ

AccessDB(***.accdb)のフルパスを指定します。
ここで指定するのはAccessで「データベースの分割」を行ったデータベースのみのファイルになります。

DB_USER、DB_PASSWORD

今回は使用していません。

クエリ実行

test.php
<?php

ini_set('INTERNAL_ENCODING', 'UTF-8');

define('ACCESS_DB_DRIVER',   '{Microsoft Access Driver (*.mdb, *.accdb)}');
define('ACCESS_DBQ',         'C:\\test\\test_be.accdb');
define('ACCESS_DB_USER',     '');
define('ACCESS_DB_PASSWORD', '');

$objPdo = new PDO("odbc:Driver=" . ACCESS_DB_DRIVER . ";Dbq=" . ACCESS_DBQ . "; Uid=" . ACCESS_DB_USER . "; Pwd=" . ACCESS_DB_PASSWORD . " ;");

$sql = "SELECT test_column FROM tbl_test WHERE column = 10;";
$sql = convertSJIS($sql); // 文字コード変換。AccessはSJIS-winなので変換する必要あり
$stmt = $objPdo->prepare($sql);
$result = $stmt->execute();
if ($result !== false) {
    $arrData = $stmt->fetchAll(PDO::FETCH_ASSOC);
    foreach ($arrData as $arrDetail) {
        $strValue = convertUTF8($arrDetail['test_column']); // SJIS-winからUTF-8に変換する
    }
}

/**
 * 文字コードを変換する
 * UTF-8 --> SJIS-win 
 */
function convertSJIS($strTmp) {
    return mb_convert_encoding($strTmp, "SJIS-win", "UTF-8");
}

/**
 * 文字コードを変換する
 * SJIS-win --> UTF-8
 */
function convertUTF8($strTmp) {
    return mb_convert_encoding($strTmp, "UTF-8", "SJIS-win");
}

ポイントとしてはAccessの文字コードがSJIS-winなので、クエリ発行時はUTF-8 --> SJIS-winへ、取得したデータはSJIS-win-->UTF-8に変換する必要があります。
取得するカラム名が日本語の場合はそれも変換する必要があるので、fetchAllしたあとにループですべて変換する必要がありますね。

おまけ

このコードをテストしていたときに気づいたのですが、mb_convert_encoding関数の第1引数に連想配列を渡すと、中身をすべて変換してくれるんですね。
PHP5.4ではエラーになったのでPHP7あたりからOKになったのかな?
公式にも配列OKとはなっていないので、正式なコードではないんだとは思います。

test.php
$arrData = $stmt->fetchAll(PDO::FETCH_ASSOC);
$arrData = convertUTF8($arrData);// これで配列の中身全部変換できる