SQLの窓

2018年02月06日


Windows 環境の MySQL + PHP で、ODBC ドライバを使用してデータを取得する場合の3パターン

MySQL ドキュメント : 5.2 Connector/ODBC Connection Parameterscharset パラメータがあります。

'character_set' の環境が全て utf8 という環境(character_set_results は空)が前提で、PHP のコードを SHIFT_JIS にすると何も問題無く処理できます。しかし、今では一般的な UTF-8(UTF8N) で PHP のコードを使用して、charset を utf8 にしても、戻されるデータはのみが正しく UTF-8 で取得できるだけで、渡す SQL が SHIFT_JIS である必要があるのと、戻る列名も SHIFT_JIS なので2箇所を変換する必要があります。

詳細は良く解りませんが、古い32ビットのソフトウェアで charset を cp932 にして正常に動作している環境でデータをエクスポートすると 列データと insert されたデータのキャラクタセットが違うという結果になります。この事から、日本語用の ODBC ドライバは SHIFT_JIS に特化した処理を行っているのかもしれません。

そもそも、MySQL を Windows で使用するにしても、mysqli を使用すれば PHP サイドからすると事は単純になりますが、テーブルの作成等を PHP ベースで行う事はめったにないので詳しい検証はできていません。

最後のパターン

charset を cp932 にして PHP を UTF-8 で作成する方法です。UTF-8 の環境の中に無理やり shift_jis の環境をねじ込むようなやり方になっていますが(列もデータも変換する)、Microsoft Access を対象とした ODBC 経由の処理と同じになり、これはこれでいろいろ有効な方法です。

PHP:shift_jis ODBC:cp932
<?php
header( "Content-Type: text/plain; charset=shift_jis" );

$host = "localhost";$db = "lightbox";$user = "root";$pass="pass";
$connect_string = "Driver={MySQL ODBC 5.3 Unicode Driver};server={$host};database={$db};charset=cp932";
$odbc = odbc_connect($connect_string, $user, $pass);

$query = "select * from 社員マスタ";

if ($result = odbc_exec( $odbc, $query) ) {

	while( $row = odbc_fetch_array( $result ) ) {
		$rows[] = $row;
	}
	odbc_free_result($result);
}

odbc_close( $odbc );

print_r($rows);

?>


PHP:utf-8 ODBC:utf8
<?php
header( "Content-Type: text/plain; charset=utf-8" );

$host = "localhost";$db = "lightbox";$user = "root";$pass="pass";
$connect_string = "Driver={MySQL ODBC 5.3 Unicode Driver};server={$host};database={$db};charset=utf8";
$odbc = odbc_connect($connect_string, $user, $pass);

$query = "select * from 社員マスタ";
$query = mb_convert_encoding($query,"MS932","utf-8");

if ($result = odbc_exec( $odbc, $query) ) {

	while( $row = odbc_fetch_array( $result ) ) {

		$new_row = array();
		foreach( $row as $k => $v ) {
			$new_row[mb_convert_encoding($k,"utf-8","MS932")] = $v;
		}
		$row = $new_row;

		$rows[] = $row;

	}
	odbc_free_result($result);
}

odbc_close( $odbc );

print_r($rows);

?>


PHP:utf-8 ODBC:cp932
<?php
header( "Content-Type: text/plain; charset=utf-8" );

$host = "localhost";$db = "lightbox";$user = "root";$pass="pass";
$connect_string = "Driver={MySQL ODBC 5.3 Unicode Driver};server={$host};database={$db};charset=cp932";
$odbc = odbc_connect($connect_string, $user, $pass);

$query = "select * from 社員マスタ";
$query = mb_convert_encoding($query,"MS932","utf-8");

if ($result = odbc_exec( $odbc, $query) ) {

	while( $row = odbc_fetch_array( $result ) ) {

		$new_row = array();
		foreach( $row as $k => $v ) {
			$new_row[mb_convert_encoding($k,"utf-8","MS932")] = mb_convert_encoding($v,"utf-8","MS932");
		}
		$row = $new_row;

		$rows[] = $row;

	}
	odbc_free_result($result);
}

odbc_close( $odbc );

print_r($rows);

?>



posted by lightbox at 2018-02-06 23:26 | PHP + データベース | このブログの読者になる | 更新情報をチェックする

2017年06月09日


PHP : SQLインジェクション対策付きの、MySQL のデータを JSON で返す自家製 API テスト用のテンプレート3パターン

特記事項

1) ブラウザの JavaScript からドメイン違いでも呼び出せるように、Access-Control-Allow-Origin を使用
2) pretty=no で、整形しません。escape=no で、日本語はそのまま返します(デバッグ優先)

real_escape_string で SQLインジェクション対策

SQL の実行に query メソッドを使用します。その為、SQL は単純に文字列で作成するので、real_escape_string で条件内の値を $_GET より $get に変換して使用します。
<?php
error_reporting( E_ALL & ~E_NOTICE );

session_cache_limiter('nocache');
session_start();

// 取得対象列
$list = "社員コード,氏名,フリガナ,所属,性別,作成日,更新日,給与,手当,管理者";
// json encode オプション
$flg = 0;

// JavaScript ajax 用
header( "Access-Control-Allow-Origin: *" );
header( "Content-Type: application/json; charset=utf-8" );

// DB 接続
$mysqli = new mysqli('サーバ', 'ユーザ', 'パスワード', 'データベース');
if ( $mysqli->connect_error ) {
	// 接続失敗
	$json = array( "error" => "Connect Error ({$mysqli->connect_errno}) {$mysqli->connect_error}" );
}
else {
	// SQL インジェクション用
	foreach( $_GET as $key => $value ) {
		// $_GET を $get で代替
		$get[$key] = $mysqli->real_escape_string( $value );
	}
	// json encode オプション
	if ( $get["pretty"] != "no" ) {
		$flg = $flg | JSON_PRETTY_PRINT;
	}
	if ( $get["escape"] != "no" ) {
		$flg = $flg | JSON_UNESCAPED_UNICODE;
	}

	$mysqli->set_charset("utf8");

	// ~E_NOTICE なので、単純化
	if ( $_GET["name"] == "" ) {
		$query = "select {$list} from 社員マスタ";
	}
	else {
		$query = "select {$list} from 社員マスタ";
		// 条件オプション
		$query .= " where 氏名 like '%{$get["name"]}%'";
	}

	$result = $mysqli->query($query);
	if ( $result === false ) {
		// SQL 失敗
		$json = array( "error" => "$mysqli->error : {$query}" );
	}
	else {
		// DB 読み出し成功
		$json = $result->fetch_all( MYSQLI_ASSOC );
	}
}

print json_encode( $json, $flg );

?>


bind_param で SQLインジェクション対策

prepare メソッドを使用すると、bind_param メソッドを使用して入力値から SQL を作成する事ができます。そして、結果として get_result メソッド を使用する事によって mysqli_result を取得できるので、その後は パターン(1) と同じになります
<?php
error_reporting( E_ALL & ~E_NOTICE );

session_cache_limiter('nocache');
session_start();

// 取得対象列
$list = "社員コード,氏名,フリガナ,所属,性別,作成日,更新日,給与,手当,管理者";
// json encode オプション
$flg = 0;

// JavaScript ajax 用
header( "Access-Control-Allow-Origin: *" );
header( "Content-Type: application/json; charset=utf-8" );

// DB 接続
$mysqli = new mysqli('サーバ', 'ユーザ', 'パスワード', 'データベース');
if ( $mysqli->connect_error ) {
	// 接続失敗
	$json = array( "error" => "Connect Error ({$mysqli->connect_errno}) {$mysqli->connect_error}" );
}
else {
	// json encode オプション
	if ( $_GET["pretty"] != "no" ) {
		$flg = $flg | JSON_PRETTY_PRINT;
	}
	if ( $_GET["escape"] != "no" ) {
		$flg = $flg | JSON_UNESCAPED_UNICODE;
	}

	$mysqli->set_charset("utf8");

	// ~E_NOTICE なので、単純化
	if ( $_GET["name"] == "" ) {
		$query = "select {$list} from 社員マスタ";
	}
	else {
		$query = "select {$list} from 社員マスタ";
		// 条件オプション
		$query .= " where 氏名 like ?";
	}

	// SQL 準備
	$stmt = $mysqli->prepare($query);
	if ( $stmt === false ) {
		// SQL 失敗
		$json = array( "error1" => "$mysqli->error : {$query}" );
	}
	else {
		// バインドは変数で
		$param = "%{$_GET["name"]}%";

		// パラメータの数が一致しない場合の warning を出さない為の @ 抑制
		@$stmt->bind_param('s', $param );
		if ( false === $stmt->execute() ) {
			$json = array( "error2" => "$mysqli->error" );
		}
		else {
			// MySQL ネイティブドライバ限定(PHP 5.3.0 以降)
			$result = $stmt->get_result();
			if ( $result === false ) {
				$json = array( "error3" => "$mysqli->error" );
			}
			else {
				// DB 読み出し成功
				$json = $result->fetch_all( MYSQLI_ASSOC );
			}
		}
	}
}

print json_encode( $json, $flg );

?>


get_result メソッド を使え無い場合の方法

get_result メソッドは、MySQL ネイティブドライバ限定(PHP 5.3.0 以降)なので、代替方法です。$stmt->store_result() => $stmt->bind_result => $stmt->fetch という流れになります。
<?php
error_reporting( E_ALL & ~E_NOTICE );

session_cache_limiter('nocache');
session_start();

// 取得対象列
$list = "社員コード,氏名,フリガナ,所属,性別,作成日,更新日,給与,手当,管理者";
// json encode オプション
$flg = 0;

// JavaScript ajax 用
header( "Access-Control-Allow-Origin: *" );
header( "Content-Type: application/json; charset=utf-8" );

// DB 接続
$mysqli = new mysqli('サーバ', 'ユーザ', 'パスワード', 'データベース');
if ( $mysqli->connect_error ) {
	// 接続失敗
	$json = array( "error" => "Connect Error ({$mysqli->connect_errno}) {$mysqli->connect_error}" );
}
else {
	// json encode オプション
	if ( $_GET["pretty"] != "no" ) {
		$flg = $flg | JSON_PRETTY_PRINT;
	}
	if ( $_GET["escape"] != "no" ) {
		$flg = $flg | JSON_UNESCAPED_UNICODE;
	}

	$mysqli->set_charset("utf8");

	// ~E_NOTICE なので、単純化
	if ( $_GET["name"] == "" ) {
		$query = "select {$list} from 社員マスタ";
	}
	else {
		$query = "select {$list} from 社員マスタ";
		// 条件オプション
		$query .= " where 氏名 like ?";
	}

	// SQL 準備
	$stmt = $mysqli->prepare($query);
	if ( $stmt === false ) {
		// SQL 失敗
		$json = array( "error1" => "$mysqli->error : {$query}" );
	}
	else {
		// バインドは変数で
		$param = "%{$_GET["name"]}%";

		// パラメータの数が一致しない場合の warning を出さない為の @ 抑制
		@$stmt->bind_param('s', $param );
		if ( false === $stmt->execute() ) {
			$json = array( "error2" => "$mysqli->error" );
		}
		else {
			// get_result() を使わない方法
			$stmt->store_result();
			$row_data = new StdClass;
			$stmt->bind_result(
				$row_data->{"社員コード"},
				$row_data->{"氏名"},
				$row_data->{"フリガナ"},
				$row_data->{"所属"},
				$row_data->{"性別"},
				$row_data->{"作成日"},
				$row_data->{"更新日"},
				$row_data->{"給与"},
				$row_data->{"手当"},
				$row_data->{"管理者"}
			);
			$json = array();
			while ($stmt->fetch()) {
				$json[] = $row_data;
			}
		}
	}
}

print json_encode( $json, $flg );

?>




posted by lightbox at 2017-06-09 20:43 | PHP + データベース | このブログの読者になる | 更新情報をチェックする

2017年04月15日


PHP で MySQLをテストする為のソースコード


※ $_GET['text'] で入力された SQL が引き渡されます。
※ GET コマンドなので、内容はアドレスバーで確認する事ができます
※ Form を使わずにアドレスバーから直接 SQL を実行できます。

MySQL 改良版拡張モジュール
<?php
session_cache_limiter('nocache');
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SQL実行結果</title> 
</head>
<body style='white-space:pre;'>
<?php
print $_GET['text'] . "\n";

$server = 'localhost';
$dbname = 'lightbox';
$user = 'root';
$password = 'パスワード';

// ***************************
// 接続
// ***************************
$mysqli = @ new mysqli($server, $user, $password, $dbname);
if ($mysqli->connect_error) {
	print "接続エラーです : ({$mysqli->connect_errno}) ({$mysqli->connect_error})";
	exit();
}

// ***************************
// クライアントの文字セット
// ***************************
$mysqli->set_charset("utf8"); 

// ***************************
// クエリ
// ***************************
$result = $mysqli->query($_GET['text']);
if ( !$result ) {
	print "\n";
	print "<span style='color:#f00'>" . $mysqli->error . "</span>";
}

// ***************************
// 列数
// ***************************
$nfield = $result->field_count;
if ( $nfield ) {
	$ncount = 0;
	print "<table style='border:solid 1px #000;border-collapse:collapse;'>\n";

	print "\t<th style='border:solid 1px #000;padding:5px;'></th>\n";

	$field = $result->fetch_fields( );
	for( $i = 0; $i < $nfield; $i++ ) {
		print "\t<th style='border:solid 1px #000;padding:5px;'>{$field[$i]->name}</th>\n";
	}

	while ($row = $result->fetch_row()) {
		print "<tr>\n";
		print "\t<td style='border:solid 1px #000;padding:5px;'>" . ($ncount + 1) . "</td>\n";
		for( $i = 0; $i < $nfield; $i++ ) {

			print "\t<td style='border:solid 1px #000;padding:5px;'>{$row[$i]}</td>\n";
		}
		print "</tr>\n";
		$ncount++;
	}
	print "</table>";
}

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

</body>
</html>


PHP 5.5.0 で非推奨になり、PHP 7.0.0 で削除
<?php
session_cache_limiter('nocache');
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SQL実行結果</title> 
</head>
<body style='white-space:pre;'>
<?php
print $_GET['text'] . "\n";

$server = 'localhost';
$dbname = 'lightbox';
$user = 'root';
$password = 'パスワード';

// ***************************
// 接続
// ***************************
$connect = @mysql_connect( $server, $user, $password );
if ( !$connect ) {
	print "接続エラーです";
	exit();
}

// ***************************
// DB選択
// ***************************
mysql_select_db( $dbname, $connect );
mysql_set_charset("utf8", $connect); 

// ***************************
// クエリ
// ***************************
$result = mysql_query($_GET['text'], $connect);
if ( !$result ) {
	print "\n";
	print "<span style='color:#f00'>" . mysql_error() . "</span>";
}

// ***************************
// 列数
// ***************************
$nfield = @mysql_num_fields( $result );
if ( $nfield ) {
	$ncount = 0;
	print "<table style='border:solid 1px #000;border-collapse:collapse;'>\n";

	print "\t<th style='border:solid 1px #000;padding:5px;'></th>\n";
	for( $i = 0; $i < $nfield; $i++ ) {
		$field = mysql_fetch_field( $result, $i );

		print "\t<th style='border:solid 1px #000;padding:5px;'>{$field->name}</th>\n";
	}

	while ($row = mysql_fetch_row($result)) {
		print "<tr>\n";
		print "\t<td style='border:solid 1px #000;padding:5px;'>" . ($ncount + 1) . "</td>\n";
		for( $i = 0; $i < $nfield; $i++ ) {
			print "\t<td style='border:solid 1px #000;padding:5px;'>{$row[$i]}</td>\n";
		}
		print "</tr>\n";
		$ncount++;
	}
	print "</table>";
}

// ***************************
// 接続解除
// ***************************
mysql_close($connect);
?>

</body>
</html>

※ このコードではセキュリティ上の考慮はされていません。



posted by lightbox at 2017-04-15 19:47 | PHP + データベース | このブログの読者になる | 更新情報をチェックする

2016年05月30日


PHP で 自家製 API を作成して jQuery の簡単なコードで更新処理を行うサンプル

以下のような『社員マスタ』を使って、まず PHP のコードを用意します。
create table `社員マスタ` (
	`社員コード` varchar(4)
	,`氏名` varchar(50)
	,`フリガナ` varchar(50)
	,`所属` varchar(4)
	,`性別` int
	,`作成日` datetime
	,`更新日` datetime
	,`給与` int
	,`手当` int
	,`管理者` varchar(4)
	,`生年月日` datetime
	,primary key(`社員コード`)
)


全てのデータが空でも、SQL 的にはエラーは起こりません。但し、エラーが発生した場合は、kj にエラーメッセージをセットし、furi に 更新 SQL をセットします。

dbdata_update_json.php
<?php
header( "Content-Type: application/json; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );
header( "Access-Control-Allow-Origin: *" );

// ***********************************************
// 初期設定
// ***********************************************
if ( $_GET["sdata"] == "" ) {
	$_GET["sdata"] = "{}";
}
$data = json_decode($_GET["sdata"]);
$data->type = "UPDATE";

// ***********************************************
// 利用変数設定
// ***********************************************
$json_type =  JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT;
$db_data_type = MYSQLI_ASSOC;
$_GET["sdata"] = str_replace("'","''",$_GET["sdata"]);
// -----------------------------------------------


// ***********************************************
// 接続情報
// ***********************************************
$server = 'localhost';
$db_name = 'lightbox';
$user = 'root';
$password = 'trustno1';
// -----------------------------------------------


// ***********************************************
// 接続
// ***********************************************
$connect = @ new mysqli($server, $user, $password, $db_name);
if ($connect->connect_error) {
	$data->status = "ERROR";
	$data->kj = "接続エラーです";
	print json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
	exit();
}
$connect->set_charset("utf8"); 
// -----------------------------------------------


// ***********************************************
// NULL 項目の対応
// ***********************************************
if ($data->kyuyo == '') {
	$data->kyuyo = "null";
}
if ($data->teate == '') {
	$data->teate = "null";
}
if ($data->seibetu == '') {
	$data->seibetu = "0";
}
if ($data->birth == '') {
	$data->birth = "null";
}
else {
	$data->birth = "'{$data->birth}'";
}
// -----------------------------------------------


// ***********************************************
// 更新 SQL
// ***********************************************
$query = <<< QUERY
update `社員マスタ` set 
	`氏名` = '{$data->kj}'
	,`フリガナ` = '{$data->furi}'
	,`性別` = {$data->seibetu}
	,`給与` = {$data->kyuyo}
	,`手当` = {$data->teate}
	,`所属` = '{$data->syozoku}'
	,`管理者` = '{$data->kanri}'
	,`生年月日` = $data->birth
 where
 `社員コード` = '{$data->scode}'
QUERY;
// -----------------------------------------------


// ***********************************************
// クエリ実行
// ***********************************************
$result = $connect->query($query); 
if ( !$result ) {
	$data->status = "ERROR";
	$data->kj = "クエリに誤りがあります";
	$data->furi = $query;
	print json_encode( $data, $json_type );
	exit();
}
else {
	$data->status = "SUCCESS";
}
// -----------------------------------------------


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


// ***********************************************
// 結果
// ***********************************************
print json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);

// -----------------------------------------------

?>


PHP で Access-Control-Allow-Origin: * をセットしているので、どこに置いても JavaScript から呼び出し可能です。

以下のような簡単なコードで更新のテストが可能です。
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script>
$(function(){
	var sdata = {};
	$("#build").on("click", function(){
		$(".entry").find("input").each(function(idx){
			sdata[$(this).prop("id")] = $(this).val();
		});
		$("#result").text( JSON.stringify(sdata,null,"    ") );
	});
	$("#send").on("click", function(){
		var sdata = encodeURIComponent( $("#result").text() );
		$.get("http://localhost/log/easy_board/dbdata_update_json.php?sdata="+sdata ,function(data){
			console.dir(data);
		});
	});
});
</script>
<input id="build" type="button" value="JSON 文字列作成">
<input id="send" type="button" value="サーバ送信">
<pre class="entry">
<input id="scode"> scode
<input id="kj"> kj
<input id="furi"> furi
<input id="seibetu"> seibetu
<input id="kyuyo"> kyuyo
<input id="teate"> teate
<input id="syozoku"> syozoku
<input id="kanri"> kanri
<input id="birth"> birth
</pre>
<pre id="result">
</pre>



posted by lightbox at 2016-05-30 21:17 | PHP + データベース | このブログの読者になる | 更新情報をチェックする

2015年08月06日


PHP : PIPES_AS_CONCAT を使用して、CSV 作成処理をサーバの負荷にして高速に WrodPress のデータを Excel で読み込める CSV として保存する処理

まず、set sql_mode = 'PIPES_AS_CONCAT' を同一セッション内で実行しておく事によって、Oracle と同様に文字列連結に || を使用できるようになります。

そこで、CSV としての 文字列の仕様を SELECT 構文上でほぼ完成させておいて、クライアントでは一つの列を取得して、改行コードの処理のみを加えてファイルに出力するようにしています。ファイルの出力も、ここでは file_put_contents を使っている為、効率は良くありません。大量のデータを処理したい場合ならば、ファイルへの出力は一行単位で行うべきです。

この方法は十数年前の Oracle でレスポンスが顕著で、天と地ほどの処理時間の差が出ていました。現在では、クライアントの処理能力も上がったので差は無いかもしれませんが、一つのテクニックとして利用可能だと思います。

出来上がった SQL
select ID||','||post_author||','||'"'||replace(post_date,'"','""')||'"'||','||'"'||replace(post_date_gmt,'"','""')||'"'||','||'"'||replace(post_content,'"','""')||'"'||','||'"'||replace(post_title,'"','""')||'"'||','||'"'||replace(post_excerpt,'"','""')||'"'||','||'"'||replace(post_status,'"','""')||'"'||','||'"'||replace(comment_status,'"','""')||'"'||','||'"'||replace(ping_status,'"','""')||'"'||','||'"'||replace(post_password,'"','""')||'"'||','||'"'||replace(post_name,'"','""')||'"'||','||'"'||replace(to_ping,'"','""')||'"'||','||'"'||replace(pinged,'"','""')||'"'||','||'"'||replace(post_modified,'"','""')||'"'||','||'"'||replace(post_modified_gmt,'"','""')||'"'||','||'"'||replace(post_content_filtered,'"','""')||'"'||','||post_parent||','||'"'||replace(guid,'"','""')||'"'||','||menu_order||','||'"'||replace(post_type,'"','""')||'"'||','||'"'||replace(post_mime_type,'"','""')||'"'||','||comment_count from wp_posts

<?php
// **************************************
// MIME と キャラクタセットを設定
// **************************************
header( "Content-Type: text/html; Charset=utf-8" );

// **************************************
// キャッシュを無効にするヘッダ
// **************************************
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

// **************************************
// グローバル変数
// **************************************
$server = 'データベースサーバー';
$db_name = 'データーベース';
$user = 'ユーザー';
$password = 'パスワード';

print "処理開始<br>";
// **************************************
// データベース接続
// **************************************
$connect = @ new mysqli($server, $user, $password, $db_name);
if ($connect->connect_error) {
	die('Connect Error (' . $connect->connect_errno . ') '
	. $connect->connect_error);
}

// **************************************
// クライアントのキャラクタセット
// **************************************
$connect->set_charset("cp932");

// セッション(接続)中有効
$query = "set sql_mode = 'PIPES_AS_CONCAT'";
// クエリ
$result = $connect->query($query); 
if ( !$result ) {
	die('クエリーに誤りがあります : ' . $connect->error );
}

// **************************************
// WordPress の投稿データ
// **************************************
$query = "select * from wp_posts";
// クエリ
$result = $connect->query($query); 
if ( !$result ) {
	die('クエリーに誤りがあります : ' . $connect->error );
}

// **************************************
// 列名とデータ型を取得
// **************************************
$finfo = $result->fetch_fields();

$name = array();
$type = array();
foreach ($finfo as $val) {
	$name[] = $val->name;
	$type[] = $val->type;
}

// **************************************
// フィールド数
// **************************************
$field_count = $connect->field_count;

$csv = "";
for( $i = 0; $i < $field_count; $i++ ) {
	if ( $i != 0 ) {
		$csv .= "||','||";
	}
	// 数値型
	// TIMESTAMP型(7) を使用している場合は変更が必要です
	if ( $type[$i] < 10 || $type[$i] == 246 || $type[$i] == 16 ) {
		$csv .= $name[$i];
	}
	else {
		$csv .= "'\"'||replace({$name[$i]},'\"','\"\"')||'\"'";
	}

}

$query = "select {$csv} from wp_posts";
// クエリ
$result = $connect->query($query); 
if ( !$result ) {
	die('クエリーに誤りがあります : ' . $connect->error );
}

file_put_contents("query.txt", $query);

$file = "";
while ($row = $result->fetch_array(MYSQLI_BOTH)) {

	// データ内の改行コード
	$row[0] = str_replace("\r\n", "\\r\\n", $row[0]);
	$row[0] = str_replace("\r", "\\r", $row[0]);
	$row[0] = str_replace("\n", "\\n", $row[0]);

	// insert としての一行を追加
	$file .= "{$row[0]}\r\n";

}

// **************************************
// ファイルに出力
// **************************************
file_put_contents("easy.csv", $file);

?>

関連する記事



タグ:PHP MySQL WordPress
posted by lightbox at 2015-08-06 20:05 | PHP + データベース | このブログの読者になる | 更新情報をチェックする

2015年08月04日


PHP : WrodPress のデータを insert SQL で保存する処理

前回の Excel とは違い、SQL のクォートがシングルクォーテ−ションなので、データ中の '(シングルクォーテ−ション) は ''(シングルクォーテ−ション2個) に変換しています。キャラクタセットも本来の utf8 を指定していますがこれは省略してもいいでしょう。

実際にローカルの MySQL に wp_posts を作成して 作成された insert 文を2つ実行してみましたが、エラー無く登録されました。
<?php
// **************************************
// MIME と キャラクタセットを設定
// **************************************
header( "Content-Type: text/html; Charset=utf-8" );

// **************************************
// キャッシュを無効にするヘッダ
// **************************************
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

// **************************************
// グローバル変数
// **************************************
$server = 'データベースサーバー';
$db_name = 'データーベース';
$user = 'ユーザー';
$password = 'パスワード';

print "処理開始<br>";
// **************************************
// データベース接続
// **************************************
$connect = @ new mysqli($server, $user, $password, $db_name);
if ($connect->connect_error) {
	die('Connect Error (' . $connect->connect_errno . ') '
	. $connect->connect_error);
}

// **************************************
// クライアントのキャラクタセット
// **************************************
$connect->set_charset("utf8");

// **************************************
// WordPress の投稿データ
// **************************************
$query = "select * from wp_posts";
// クエリ
$result = $connect->query($query); 
if ( !$result ) {
	die('クエリーに誤りがあります : ' . $connect->error );
}

// **************************************
// 列名とデータ型を取得
// **************************************
$finfo = $result->fetch_fields();

$name = array();
$type = array();
foreach ($finfo as $val) {
	$name[] = $val->name;
	$type[] = $val->type;
}

// **************************************
// フィールド数
// **************************************
$field_count = $connect->field_count;

$fld_list = "(" . implode(",",$name ) . ")";

$file = "";

while ($row = $result->fetch_array(MYSQLI_BOTH)) {

	// CSV の一行の作成
	$insert = "insert into wp_posts {$fld_list} values(";
	for( $i = 0; $i < $field_count; $i++ ) {
		if ( $i != 0 ) {
			$insert .= ",";
		}
		// 数値型
		// TIMESTAMP型(7) を使用している場合は変更が必要です
		if ( $type[$i] < 10 || $type[$i] == 246 || $type[$i] == 16 ) {
			if ( $row[$i] == "" ) {
				$insert .= "0";
			}
			else {
				$insert .= $row[$i];
			}
		}
		else {
			// データ内のダブルクォートとフィールドを囲むダブルクォート
			if ( $row[$i] == "" ) {
				$insert .= "''";
			}
			else {
				$insert .= "'" . str_replace("'", "''","$row[$i]") . "'";
			}
		}
	}

	// データ内の改行コード
	$insert = str_replace("\r\n", "\\r\\n", $insert);
	$insert = str_replace("\r", "\\r", $insert);
	$insert = str_replace("\n", "\\n", $insert);

	// insert としての一行を追加
	$file .= "{$insert});\r\n";

}

// **************************************
// ファイルに出力
// **************************************
file_put_contents("insert.sql", $file);

?>


関連する記事

参考

MySQL TIMESTAMP / MySQLTutorial



posted by lightbox at 2015-08-04 20:30 | PHP + データベース | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり

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

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