SQLの窓

2019年02月02日


PHP で ODBC 関数を使って MS Access( データベース )にアクセスして結果を JSON 文字列として出力する



db.php は簡単なクラスですが、MS Access を使用する為に SHIFT_JIS でSQL を作成する必要があります。また、戻された結果も SHIFT_JIS なので UTF-8 に変換しています。利用者は、UTF-8 ベースのソースコードから SHIFT_JIS を意識せずに処理する事が可能になります。
db.php(クラス)
<?php
// ***************************
// データベースクラス
// (このソースは UTF-8N)
//
// UTF-8 => SHIFT_JIS
// ***************************
class DB {
 
	public $connect;
	public $result;
 
// ***************************
// コンストラクタ
// ***************************
	function DB( $connect ) {

		$this->connect = odbc_connect($connect, "", "");

	}
 
// ***************************
// 接続解除
// ***************************
	function close( ) {

		odbc_close( $this->connect );

	}
 
// ***************************
// 単純クエリー( 実行 )
// ***************************
	function query( $sql_query ) {

		// SHIFT_JIS に変換
		$sql_query = mb_convert_encoding( $sql_query, "cp932", "utf-8" );

		$ret = @odbc_exec( $this->connect, $sql_query );
		return $ret;
	}
 
// ***************************
// フェッチ
// ***************************
	function fetch( $result=null ) {

		// 引数が無い場合は前回実行された 
		// $this->result を使用する
		if ( $result == null ) {
			$result = $this->result;
		}

		// ※ Invalid argument supplied for foreach()
		$error = error_reporting(E_ALL & ~E_WARNING);

		// SHIFT_JIS のデータ
		$ret1 = odbc_fetch_array( $result );
		// 空の配列
		$ret2 = array();

		// 数字をインデックスとする配列を作成する
		foreach ($ret1 as $key => $value) {
			// UTF-8 で使えるようにする
			$ret2[] = mb_convert_encoding( $value, "utf-8", "cp932" );
		}
		// 連想配列を作成する
		foreach ($ret1 as $key => $value) {
			// UTF-8 で使えるようにする
			$key = mb_convert_encoding( $key, "utf-8", "cp932" );
			$ret2[$key] = mb_convert_encoding( $value, "utf-8", "cp932" );
		}

		// 関数内での設定以前に戻す
		error_reporting($error);

		// 数字インデックスと文字列インデックスの連想配列
		return $ret2;
	}
 
// ***************************
// クエリーとフェッチ
// ***************************
	function query_ex( $sql_query='' ) {

		// 引数がある場合は、query and fetch
		if ( $sql_query != '' ) {
			$this->result = $this->query( $sql_query );
			if ( !$this->result ) {
				return false;
			}
			return $this->fetch( );
		}
		// 引数が無い場合は fetch のみ
		else {
			return $this->fetch( );
		}
 
	}

// ***************************
// 実行 : query と同じ
// ***************************
	function execute( $sql_exec ) {

		// SHIFT_JIS に変換
		$sql_exec = mb_convert_encoding( $sql_exec, "cp932", "utf-8" );

		$ret = odbc_exec( $this->connect, $sql_exec );
		return $ret;

	}
 
 
}
?>


以下は、accdb を使って( mdb でも可 )データを JSON として出力しています。

ms-access-json.php
<?php
// ***************************
// このソースは UTF-8N
// ***************************
header( "Content-Type: text/plain; Charset=utf-8" );

// ***************************
// キャッシュを使用しない
// ***************************
header( "Expires: Thu, 19 Nov 1981 08:52:00 GMT" );
header( "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" );
header( "Pragma: no-cache" );

// ***************************
// データベースアクセスクラス
// ***************************
require_once("db.php");

// ***************************
// PHP 設定
// ***************************
mb_language( "ja" );
mb_internal_encoding("UTF-8");

// ***************************
// MS Acceess ファイル
// ***************************
$dbfile = "販売管理B.accdb";
//$dbfile = "販売管理B.mdb";

// ***************************
// ファイル名を SHIFT_JIS に変換
// ***************************
$dbfile = mb_convert_encoding( $dbfile, "cp932", "utf-8" );


// ***************************
// 接続文字列
// ODBC ドライバ名( 32ビット )
// のある場所 ▼
// HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI
// ***************************
$connect_string = "Provider=MSDASQL;";
$connect_string .= "Driver={Microsoft Access Driver (*.mdb, *.accdb)};";
$dbpath = realpath($dbfile);
$connect_string .= "dbq={$dbpath};";

// ***************************
// クラスのインスタンス
// ***************************
$db = new DB( $connect_string );
if ( $db->connect === false ) {
	print "接続に失敗しました : " . mb_convert_encoding( odbc_errormsg(), "utf-8", "cp932" );
	exit();
}

// ***************************
// 1) UTF-8 で SQL を作成
// ***************************
$query = <<<SQL
	select
		[社員マスタ].*,
		[社員マスタ].[社員コード] as scode
	from [社員マスタ]
	where [社員コード] in('0001','0002','0003')
SQL;

// ***************************
// データ全体用の配列
// ***************************
$json = array();

// ***************************
// クラスでクエリの実行
// ※ 初回
// ***************************
$column = $db->query_ex( $query );
if ( $column === false ) {
	print "SQLの実行に失敗しました : " . mb_convert_encoding( odbc_errormsg( $db->connect ), "utf-8", "cp932" );
	$db->close();
	exit();
}

// ***************************
// 全ての行を取得
// ***************************
while ( $column ) {

	// ***************************
	// 行単位で結果の連想配列をセット
	// ***************************
	$json['items'][] = $column;
	$column = $db->query_ex( );

};

// ***************************
// 接続解除
// ***************************
$db->close();

// ***************************
// php.exe の確認
// ***************************
if( PHP_INT_SIZE == 4 ) {
	print "PHPは 32ビットです\n";
}

// ***************************
// テストの為、見やすいオプション
// 1) 日本語をエスケープしない
// 2) 整形する
// ***************************
print json_encode( $json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);

?>


関連する Microsoft ドキュメント( 接続文字列 )

Microsoft OLE DB Provider for ODBC の概要

データ ソースにアクセスする( 接続文字列を作成する )


出力結果
PHPは 32ビットです
{
    "items": [
        {
            "0": "0001",
            "1": "浦岡 友也",
            "2": "ウラオカ トモヤ",
            "3": "0003",
            "4": "0",
            "5": "2005-09-12 00:00:00",
            "6": "2005-11-28 00:00:00",
            "7": "270000",
            "8": "9000",
            "9": "",
            "10": "0001",
            "社員コード": "0001",
            "氏名": "浦岡 友也",
            "フリガナ": "ウラオカ トモヤ",
            "所属": "0003",
            "性別": "0",
            "作成日": "2005-09-12 00:00:00",
            "更新日": "2005-11-28 00:00:00",
            "給与": "270000",
            "手当": "9000",
            "管理者": "",
            "scode": "0001"
        },
        {
            "0": "0002",
            "1": "山村 洋代",
            "2": "ヤマムラ ヒロヨ",
            "3": "0003",
            "4": "1",
            "5": "2005-06-17 00:00:00",
            "6": "2005-09-18 00:00:00",
            "7": "300000",
            "8": "",
            "9": "",
            "10": "0002",
            "社員コード": "0002",
            "氏名": "山村 洋代",
            "フリガナ": "ヤマムラ ヒロヨ",
            "所属": "0003",
            "性別": "1",
            "作成日": "2005-06-17 00:00:00",
            "更新日": "2005-09-18 00:00:00",
            "給与": "300000",
            "手当": "",
            "管理者": "",
            "scode": "0002"
        },
        {
            "0": "0003",
            "1": "多岡 冬行",
            "2": "タオカ フユユキ",
            "3": "0002",
            "4": "0",
            "5": "2005-08-14 00:00:00",
            "6": "2005-11-14 00:00:00",
            "7": "250000",
            "8": "",
            "9": "",
            "10": "0003",
            "社員コード": "0003",
            "氏名": "多岡 冬行",
            "フリガナ": "タオカ フユユキ",
            "所属": "0002",
            "性別": "0",
            "作成日": "2005-08-14 00:00:00",
            "更新日": "2005-11-14 00:00:00",
            "給与": "250000",
            "手当": "",
            "管理者": "",
            "scode": "0003"
        }
    ]
}

32 ビット ODBC の一覧をレジストリエディタで開く

strParam = "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI"

' レジストリ書き込み用
Set WshShell = CreateObject( "WScript.Shell" )
' WMI用
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")

' レジストリエディタが最後に開いていたキーの登録を行います
strPath = "Software\Microsoft\Windows\CurrentVersion\Applets\Regedit\LastKey"
if GetOSVersion() >= 6 then
	strRegPath = "コンピューター\" & strParam
else
	strRegPath = "マイ コンピュータ\" & strParam
end if

' 既に regedit が実行中の場合はいったん終了させます
Set colProcessList = objWMIService.ExecQuery _ 
	("Select * from Win32_Process Where Name = 'regedit.exe'") 
For Each objProcess in colProcessList
	' 最後のウインドウの位置とサイズを保存する為の終わらせ方
	WshShell.AppActivate("レジストリ エディタ")
	Wscript.Sleep(500)
	WshShell.SendKeys ("%{F4}")
	Wscript.Sleep(500)
	' 上記終わらせ方が失敗した時の強制終了
	on error resume next
	objProcess.Terminate() 
	on error goto 0
Next 

WshShell.RegWrite "HKCU\" & strPath, strRegPath, "REG_SZ"

' レジストリエディタを起動します
Call WshShell.Run( "regedit.exe" )
' レジストリエディタが終わるまで待つ場合は以下のようにします
' Call WshShell.Run( "regedit.exe", , True )

REM **********************************************************
REM OS バージョンの取得
REM **********************************************************
Function GetOSVersion()

	Dim colTarget,str,aData,I,nTarget

	Set colTarget = objWMIService.ExecQuery( _
		 "select Version from Win32_OperatingSystem" _
	)
	For Each objRow in colTarget
		str = objRow.Version
	Next

	aData = Split( str, "." )
	For I = 0 to Ubound( aData )
		if I > 1 then
			Exit For
		end if
		if I > 0 then
			nTarget = nTarget & "."
		end if
		nTarget = nTarget & aData(I)
	Next

	GetOSVersion = CDbl( nTarget )

End Function




【PHP + データベースの最新記事】
posted by lightbox at 2019-02-02 17:52 | PHP + データベース | このブログの読者になる | 更新情報をチェックする
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり