読者です 読者をやめる 読者になる 読者になる

$dbh -> query( 'SET NAMES utf8' );の引数の意味とか

PHPのPDOクラスでのデータベース接続で、

<?php
    $dsn = 'mysql:dbname=shop; host=localhost';
    $user = 'root';
    $password = ' ';

    $dbh = new PDO($dsn, $user, $password);
    $dbh->query('SET NAMES utf8');

みたいな記述が出てきて、『query('SET NAMES utf8');』の引数の意味を調べてみました。

結論として、『'SET NAMES utf8'』はSQLステートメントSQL文)で、

『'SELECT * FROM  mst_staff WHERE code = ?';』みたいに、データベースに対する命令文の一種らしいです。

「otukutunの日記」さんに載っていたんですが、『query('SET NAMES utf8')』を実行することで、MySQLのデータベースに情報を格納する時の文字化けを解消できるってことらしいです。

⇩  otukutunの日記(MySQLの文字化け対策に関して)は下記サイトへ

PDO使って、MySQLに日本語データ突っ込んだら、文字化けした。 - otukutunの日記

 

とりあえず、結論出てしまったんで、ここから先はもう読む必要ないと思いますが、時間のある方は読んでみてください。

PHP: PDO::query - Manual によるとquery( )メソッド(PDOクラス)の説明は、

PDO::query

(PHP 5 >= 5.1.0, PECL pdo >= 0.2.0)

PDO::querySQL ステートメントを実行し、結果セットを PDOStatement オブジェクトとして返す

説明

public PDOStatement PDO::query ( string $statement )

public PDOStatement PDO::query ( string $statement ,int $PDO::FETCH_COLUMN , int $colno )

public PDOStatement PDO::query ( string $statement ,int $PDO::FETCH_CLASS , string $classname , array$ctorargs )

public PDOStatement PDO::query ( string $statement ,int $PDO::FETCH_INTO , object $object )

PDO::query( ) は、一回の関数コールの中で SQL ステートメントを実行し、このステートメントにより返された 結果セット (ある場合) を PDOStatement オブジェクトとして返します。

複数回発行する必要があるステートメントの場合、 PDO::prepare( )で PDOStatement ステートメントを準備し、PDOStatement::execute( ) でそのステートメント複数回発行する方がより良いパフォーマンスを得られると実感するでしょう。

PDO::query( ) を次にコールする前に 結果セット内の全てのデータを取得しない場合、そのコールは失敗します。
PDOStatement::closeCursor( ) をコールし、 次に PDO::query( ) をコールする前に PDOStatement オブジェクトに関連付けられたリソースを解放してください。

注意:

この関数はパラメータをひとつだけしかとらないと記述されていますが、 追加のパラメータを渡すことも可能です。
これらのパラメータは、 返される結果のオブジェクトに対してPDOStatement::setFetchMode( ) をコールするのと同じような扱いになります。

パラメータ(引数) ¶

statement($statement)[データ型: string]

準備、発行する SQL ステートメント

クエリ内のデータは 適切にエスケープ する必要があります。 

返り値

PDO::query( ) は、PDOStatement オブジェクトを返します。 失敗した場合は FALSE を返します。

例1 PDO::query の例 

PDO::query( ) の優れた機能は、 実行に成功したSELECTステートメントにより返されたレコードセットで 反復処理が可能であることです。

<?php
function getFruit($conn) {
    
$sql 'SELECT name, color, calories FROM fruit ORDER BY name';
    foreach (
$conn->query($sql) as $row) {
        print 
$row['name'] . "\t";
        print 
$row['color'] . "\t";
        print 
$row['calories'] . "\n";
    }
}
?>

上の例の出力は以下となります。

apple   red     150
banana  yellow  250
kiwi    brown   75
lemon   yellow  25
orange  orange  300
pear    green   150
watermelon      pink    90

参考

 

パラメータ(引数)の説明で、$statement(型:文字列 )が準備、発行するSQLステートメントとなっていて、MySQLマニュアルの MySQL :: MySQL 5.6 リファレンスマニュアル :: 10.1 文字セットのサポート の説明によると、

MySQL では、さまざまな文字セットを使用してデータを格納し、さまざまな照合順序に従って比較を実行できます。』

『サーバー、データベース、テーブル、およびカラムレベルで文字セットを指定できます。』

MySQL では、MyISAM、MEMORY、および InnoDB のストレージエンジンの文字セットの使用をサポートします。』

『文字セットの問題は、データストレージだけではなく、クライアントプログラムと MySQL Server との通信にも影響を与えます。』

『デフォルトと異なる文字セットを使用してクライアントプログラムとサーバー間の通信を行う場合、どの文字セットを使用するのかを示す必要があります。』

『たとえば、utf8 Unicode 文字セットを使用するには、サーバー接続後に次のステートメントを発行してください。 

SET NAMES 'utf8';

 

そして、PHPマニュアルの文字セットに関する関数のPHP: mysql_set_charset - Manual の説明で、

mysql_set_charset

(PHP 5 >= 5.2.3)

mysql_set_charset クライアントの文字セットを設定する

警告

この拡張モジュールは PHP 5.5.0 で非推奨になり、PHP 7.0.0 で削除されました。
MySQLi あるいは PDO_MySQL を使うべきです。
詳細な情報は MySQL: API の選択それに関連する FAQ を参照ください。
この関数の代替として、これらが使えます。

説明

bool mysql_set_charset ( string $charset [, resource$link_identifier = NULL ] )

現在の接続における、デフォルトの文字セットを設定します。

パラメータ

charset

有効な文字セット名。

link_identifier

MySQL 接続。 指定されない場合、mysql_connect( ) により直近にオープンされたリンクが 指定されたと仮定されます。
そのようなリンクがない場合、引数を指定せずにmysql_connect( ) がコールした時と同様にリンクを確立します。
リンクが見付からない、または、確立できない場合、E_WARNING レベルのエラーが生成されます。

返り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

注意 ¶

注意:

この関数は、MySQL 5.0.7 以降でないと使用できません。

注意:

文字セットを変更するにはこの方法を使うことを推奨します。
mysql_query( ) で (SET NAMES utf8 などとして) 設定する方法はお勧めできません。
詳細は MySQL の文字セットの概念 を参照ください。

参考

 

MySQLの文字セットの概念を参照ください。』とあるので調べると、

 

文字セット

適切な文字セットをサーバーレベルで設定しておくのが理想だし、MySQL のマニュアルの » Character Set Configuration にもそうするよう書かれています。
しかしそれ以外にも、各 MySQL API には実行時に文字セットを指定する方法が用意されています。

警告

文字セットと文字のエスケープ

文字セットはきちんと理解して設定しておかないといけません。
すべての操作に影響が及ぶし、セキュリティの問題を引き起こす可能性があるからです。
たとえば、文字列のエスケープ (mysqli なら mysqli_real_escape_string( )mysql ならmysql_real_escape_string( )、 そして PDO_MySQL ならPDO::quote( )) は文字セットの設定に従った動きをします。
これらの関数は、クエリで設定した文字セットは使わないことを知っておくことが大切です。
たとえば次の例のような設定をしても、エスケープ機能は正しく動きません。

例1 文字セットを SQL で指定することによる問題 

<?php

$mysqli 
= new mysqli("localhost""my_user""my_password""world");

// これは $mysqli->real_escape_string(); に影響を及ぼしません
$mysqli->query("SET NAMES utf8");

// これも $mysqli->real_escape_string(); に影響を及ぼしません
$mysqli->query("SET CHARACTER SET utf8");

// しかしこの方法なら $mysqli->real_escape_string(); にもきちんと影響します
$mysqli->set_charset('utf8');

// いっぽう、こちらは影響を及ぼしません (utf-8 と utf8 の違いに注目) -- ここではハイフンを使ってはいけません
$mysqli->set_charset('utf-8');

?>

実行時に文字セットを変更する適切な方法を、各 API について示します。

注意: UTF-8 でありがちなミス

MySQL の文字セット名はハイフンを含まないので、MySQLUTF-8 を表す文字セットは "utf8" が正解です。"utf-8" ではないので、"utf-8" と指定しても文字セットは変わりません。

例2 文字セットの設定: mysqli 

<?php

$mysqli 
= new mysqli("localhost""my_user""my_password""world");

printf("Initial character set: %s\n"$mysqli->character_set_name());

if (!
$mysqli->set_charset('utf8')) {
    
printf("Error loading character set utf8: %s\n"$mysqli->error);
    exit;
}

echo 
"New character set information:\n";
print_r$mysqli->get_charset() );

?>

例3 文字セットの設定: pdo_mysql 

注意: これは PHP 5.3.6 以降でしか動作しません。

<?php
$pdo 
= new PDO("mysql:host=localhost;dbname=world;charset=utf8"'my_user''my_pass');
?>

例4 文字セットの設定: mysql 

<?php
$conn 
mysql_connect("localhost""my_user""my_pass");
$db   mysql_select_db("world");

echo 
'Initial character set: ' .  mysql_client_encoding($conn) . "\n";

if (!
mysql_set_charset('utf8'$conn)) {
    echo 
"Error: Unable to set the character set.\n";
    exit;
}

echo 
'Your current character set is: ' .  mysql_client_encoding($conn);
?>

PDOクラスで使っている例が無かったのですが、 query( )メソッドはパラメータ(引数)に『準備、発行するSQLステートメントSQL文)』を取ると書いてあったんで、PDOクラスでも使えるってことだと思います。

広告を非表示にする