April 2008

April 30, 2008

Storing images into the Database

phpでデータベースにバイナリデータ(画像・ファイル)を保存する方法。
$binaryはfile_get_contents()などで取得したバイナリデータ。

・MySQL
$query = "INSERT INTO test(bindata) VALUES('%s')";
$query = sprintf($query, mysql_real_escape_string($binary, $conn));
mysql_query($query, $conn);
・MySQLi
$query = "INSERT INTO test(bindata) VALUES('%s')";
$query = sprintf($query, mysqli_real_escape_string($conn, $binary));
mysqli_query($conn, $query);
・PostgreSQL
$query = "INSERT INTO test(bindata) VALUES('%s')";
$query = sprintf($query, pg_escape_bytea($conn, $binary));
pg_query($conn, $query);
・OCI8
$query = "INSERT INTO test(bindata) VALUES(EMPTY_BLOB()) RETURNING bindata INTO :bindata";
$stmt = oci_parse($conn, $query);
$lob = oci_new_descripter($conn, OCI_D_LOB);
oci_bind_by_name($stmt, ":bindata", $lob, -1, SQLT_BLOB);
$res = oci_execute($stmt, OCI_DEFAULT);
$lob->save($binary);
oci_commit($conn);
・SQL Server
デフォルトでは4KBを超えるクエリは制限されているので、php.iniのmssql.textlimitやmssql.textsizeのサイズを大きくする必要がある。
$query = "INSERT INTO test(bindata) VALUES(%s)";
$query = sprintf($query, "0x" . bin2hex($binary));
mssql_query($query, $conn);
・Firebird/Interbase
$query  = "INSERT INTO test(bindata) VALUES(?)";
$blobId = ibase_blob_create();
ibase_blob_add($blobId, $binary);
$blob = ibase_blob_close($blobId);
ibase_query($conn, $query, $blob);
・PDO_MYSQL/PDO_PGSQL/PDO_SQLITE
$query = "INSERT INTO test(bindata) VALUES(:bindata)";
$stmt = $pdo->prepare($query);
$stmt->bindValue(":bindata", $binary, PDO::PARAM_LOB);
$pdo->beginTransaction();
$stmt->execute();
$pdo->commit();
・PDO_OCI
他のPDO拡張のようにバイナリデータを直接渡せないので注意。
$query = "INSERT INTO test(bindata) VALUES(EMPTY_BLOB()) RETURNING bindata INTO :bindata";
$stmt = $pdo->prepare($query);
$tmpfile = file_put_contents($tmpfilePath, $binary);
$fp = fopen($tmpfile, "rb");
$stmt->bindValue(":bindata", $fp, PDO::PARAM_LOB);
$pdo->beginTransaction();
$stmt->execute();
$pdo->commit();
fclose($fp);
unlink($tmpfilePath);


April 26, 2008

Windows Settings

重たい腰を上げて自宅の適当なWindows(XP)をちゃんとした。

テーマ、スタートメニュー、コントロールパネルをクラシック表示に。

「コントロールパネル」->「ユーザー アカウント」->「ユーザーのログオンやログオフの方法を変更する」で「ようこそ画面を使用する」のチェックを外す。

スタートメニューのヘルプとかログオフとかを消すためにレジストリをいじる。
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer

NoClose             REG_DWORD    0x00000001 (1)
NoFind              REG_DWORD    0x00000001 (1)
NoRecentDocsMenu    REG_DWORD    0x00000001 (1)
NoSMHelp            REG_DWORD    0x00000001 (1)
StartMenuLogoff     REG_DWORD    0x00000001 (1)
ランチャに「Orchis」をインストール。
スタートメニューから終了オプションを消したので、Orchisに追加する。
特殊項目の追加 -> ログオン状態と電源管理
「Windowsの終了」と「再起動」を項目に追加する。

Orchisが落ちて、二度と立ち上がらなくてWindowsを落とせないという不幸な状況に陥った場合はコンソールから終了する。
> shutdown -s -t 0
仮想デスクトップに「WinDeskWide」をインストール。
縦1横4の4画面でCTRL-ALT-1〜4のホットキーを各画面に割り当てる。

キーの割り当てに「窓使いの憂鬱」をインストール。
最低限の設定でわりと十分。
C:\Documents and Settings\USERDIR\.mayu

# 日本語109を英語104に
include "109.mayu"
include "104on109.mayu"

keyseq $WindowClose = A-F4

keymap Global
  key *IC-C-Space = $ToggleIME  # CTRL-SpaceでIME切り替え
  mod control += 英数           # CapsLockをCTRLに
  key *英数 = *LControl
  key C-Q = $WindowClose        # CTRL-Qでウィンドウクローズ
マルチバイト対応のPuTTYをインストール。
PuTTYごった煮版というのをインストールする。

PuTTY設定 -> 変換
文字コードの設定で「UTF-8/AutoDetect Japanese」を選択。
PuTTY設定 -> セッション
「標準の設定」を選択し『保存』。

Live MessengerがあるのにMessengerがあって、勝手に起動してLive Messengerのほうで「別のところでログイン...」がどうのこうのと迷惑なのでアンインストールする。

スタートメニュー -> ファイル名を指定して実行
下のを貼り付けて『OK』。
RunDll32 advpack.dll,LaunchINFSection %windir%\INF\msmsgs.inf,BLC.Remove
PostgreSQLの最新を入れようと思い、古いバージョンをアンインストール。
新しいバージョンのインストール時に「pgsql」アカウントを作成しようと思ったら既にいるらしい。前のインストール時にランダムなパスワードを振ってしまったので、パスワードが分からず。さらにコントロールパネルのユーザアカウントにも表示されないので非常に迷惑。

コンソールから削除することに。"net user"で確認すると、前の前で作成したと思われる「postgres」ユーザも発見したのでそれも削除。
> net user pgsql /delete
> net user postgres /delete


April 23, 2008

Synergy

最近なぜかwindowsをよく使うので、synergyでlinux(fedora)とキーボートとマウスを共有することにした。

windowsをプライマリとする。

"http://www.snapfiles.com/get/synergy.html"からSynergyInstaller-1.3.1.exeをダウンロードし、インストールする。
Synergyを立ち上げ、「Share this computer's keyborad and mouse」を選択し、「Configure」ボタンから設定をする。
Screensの「+」ボタンを押し、Screen Nameにフルコンピュータ名を入力し追加する。フルコンピュータ名はコントロールパネル->システム->コンピュータ名で見れる。次にlinuxのIPをScreen Nameに入力し、追加する。

次にlinksの設定をする。
マシンは、windowsが右手、linuxが左手とする。
windowsのフルコンピュータ名が「mywindows」、linuxのIPが「192.168.0.10」とする。

以下のように2つlinkを設定する。
1. [0]to[100]% of the [right] of [192.168.0.20] goes to [0] to [100]% of [mywindows]
2. [0]to[100]% of the [left] of [mywindows] goes to [0] to [100]% of [192.168.0.20]
これで、windowsの左側からlinuxの右側へ、linuxの右側からwindowsの左側へマウスを移動できるようになる。

「Start」からSynergyをスタートさせる。

FedoraでのSynergyのインストール。
$ yum install -y senergy
Synergy Clientを立ち上げる。
$ synergyc [windowsのIP]


April 22, 2008

PDO_MYSQL::lastInsertId()

トランザクション内(begin〜commit)でINSERTされたデータの連番を取得する場合、commitの前にlastInsertId()をコールする必要がある。そうしないと"0"が返される。
CREATE TABLE test
(
  id INTEGER PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(24) NOT NULL
)
$pdo = new PDO("mysql:host=localhost;dbname=testdb", "root", "");
$stmt = $pdo->prepare("INSERT INTO test(name) VALUES(:name)");
$stmt->bindValue(":name", "somename");
$pdo->beginTransaction();
$pdo->execute();
$pdo->lastInsertId();  // last id
$pdo->commit();

$pdo->lastInsertId();  // "0"
commitの後でも、LAST_INSERT_ID()関数なら取得できる。
$stmt = $pdo->prepare("SELECT LAST_INSERT_ID() AS id");
$stmt->execute();
$row = $stmt->fetch(PDO_::FETCH_ASSOC);
$row["id"]  // last id


April 21, 2008

mysql error "Incorrect information"

mysqlで以下のエラーが発生し、再起動できない場合の対処。
ERROR 1033 (HY000): Incorrect information in file: ...
"innodb_log_file_size"の値を増やすとこうなる。
innodbのトランザクションログ(ib_logfile)をどこかに退避するか削除してしまう。

その後、再起動する。

小さくした場合は起動はできるがSELECTすると同様のエラーが発生する模様。
なので、同様の作業をすること。

April 20, 2008

PHP & Oracle 10g XE

Windows & PHP & Oracle 10g XE

Oracleを'C:\Oracle'にインストールする。

Oracle Instant Client(instantclient-basic-win32-10.2.0.3-20061115.zip)をダウンロードし、展開する。

C:\Oracle\instantclientフォルダを作成する。

展開したフォルダ内のoraociei10.dll、orannzsbb10.dll、oci.dllの3つのファイルを、作成したinstantclientフォルダにコピーする。

C:\Oracle\app\oracle\product\10.2.0\server\NETWORK\ADMIN\tnsnames.oraを作成したinstantclientフォルダにコピーする。

環境変数(コントロールパネル->システム->詳細設定->環境変数)の設定でinstantclientフォルダへのパスをPATHの先頭に追加する。
ユーザ環境変数の「新規」でNLS_LANG変数を作成し、値を'Japanese_Japan.AL32UTF8'にする。
また、TNS_ADMIN変数を作成し、値を'C:\Oracle\instantclient'にする。

php.iniでOCI8をロードする。
extension=php_oci8.dll
接続する。
$conn = oci_connect("USERNAME", "PASSWORD", "//localhost/XE", "AL32UTF8");


April 19, 2008

PHP & SQL Server 2005 XE

Windows & PHP & SQL Server 2005 XE

Microsoftから下記のものをダウンロード&インストール。

・SQL Server
SQL Server 2005 Express Edition Service Pack 1
・管理ツール
SQL Server Management Studio Express

SQL Serverのインストール時の「認証モード」の選択では、接続ユーザをWindowsアカウントと関係なくするため「混合モード」を選択する。
照合順序の設定では補助文字(サロゲートペアによる文字)を扱えるようにするため、「Japanese_90」を選択する。また、普段使用するデータベースに合わせ、「大文字と小文字を区別する」「アクセントを区別する」「かなを区別する」「文字幅を区別する」にチェックを入れる。これは'Japanese_90_CS_AS_KS_WS'となる。CSとかASとかは以下の通り。

・CI => Case Insensitive
    大文字・小文字を区別しない。
・CS => Case Sensitive
    大文字・小文字を区別する。
・AI => Accent Insensitive
    濁音などを区別しない。(「ハ」=「バ」=「パ」)
・AS => Accent Sensitive
    濁音などを区別する。
・KS => Kana Sensitive
    ひらがなとカタカナを区別する。
・WS => Width Sensitive
    文字幅(全角・半角)を区別する。
・BIN => Binary
    すべて区別する。

管理ツールを起動する。
起動時に「ファイル C:\WINDOWS\〜\...\mscorlib.tlbを読み込むことができませんでした。」のようなメッセージが出る場合はレジストリを編集する。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\90\Tools\ShellSEM\TlbAutoRepair\mscorlib.tlb

TlbPathのパス(データ)の%CLRVERSION%を'v2.0.50727'に変更する
管理ツールを起動しSQL Server認証を選択し、saアカウントで接続する。
オブジェクトエクスプローラの「セキュリティ」->「ログイン」を右クリックし、新しいログインをクリック。
ログイン名'develop'を入力し「SQL Server認証」を選択しパスワード'develop'を入力。「パスワードポリシーを適用する」のチェックを外し、「規定の言語」をJapaneseにする。

オブジェクトエクスプローラの「データベース」を右クリックし、新しいデータベースをクリック。
データベース名'test'を入力し、所有者を先程作成した'develop'にする。

オブジェクトエクスプローラの「セキュリティ」->「ログイン」->「develop」を右クリックし、プロパティをクリック。
規定のデータベースを先程作成した'test'にする。

・SQL Serverとphpの連携。
デフォルトの設定(php.ini)だと4096バイトより大きいデータがphpから書き込めないので、そのサイズを大きくしておく。また、通常のDATETIME形式で取得できるようにするための設定もする。
mssql.textlimit = 2147483647
mssql.textsize = 2147483647
mssql.datetimeconvert = Off
接続にmssql拡張を使用する場合。
extension=php_mssql.dll
$conn = mssql_connect(".\SQLEXPRESS", "develop", "develop");
dllがロードできない場合はコンソールでphpを実行してみて、「ntwdblib.dllが見つからないため〜」のようなメッセージが出るなら、http://www.webzila.com/からntwdblib.dllをダウンロードしC:\WINDOWS\system32に置く。

接続にPDO_ODBC拡張を使用する場合。
extension=php_pdo_odbc.dll
$pdo = new PDO("odbc:Driver={SQL Native Client};Server=.\SQLEXPRESS;Database=test;Uid=develop;Pwd=develop;");


April 17, 2008

mail function

phpでメール送信。毎回微妙に忘れるのでメモ。

Message-Idのドメインは引けるものであること。
また、パラメータのアドレスはメールが届くものであること。
function sendmail($from, $to, $subject, $body)
{
  $headers = "MIME-Version: 1.0\r\n"
           . "Content-Transfer-Encoding: 7bit\r\n"
           . "Content-Type: text/plain; charset=ISO-2022-JP\r\n"
           . "Message-Id: <" . md5(uniqid(microtime())) . ">@mail.example.com\r\n"
           . "From: $from";
  
  $parameter = "-f admin@example.com";
  
  $subject = mb_encode_mimeheader($subject, "ISO-2022-JP");
  $body = mb_convert_encoding($body, "ISO-2022-JP");
  
  mail($to, $subject, $body, $headers, $parameter);
}
エンベロープのsenderアドレスを設定するために第5引数(additional_parameters)を指定すること。しかし、X-Warningヘッダが付加されてしまうので、それを回避するためにpostfixの設定が必要。これをしないとスパム扱いされたりする。
vi /path/to/main.cf

...

header_checks = regexp:/path/to/header_checks

...
vi /path/to/header_checks

...

/^X-Authentication-Warning:/ IGNORE


April 14, 2008

PDO_OCI CLOB

PDO_OCIではCLOBやBLOBカラムのデータがリソースで返される。
データ(文字列)の取得は以下のようにする。
$contents = stream_get_contents($row["body"]);
oracle(oci8)関数でフェッチする場合はデータ(文字列)で返されるため、このようなことをやる必要はない。

April 13, 2008

Firebird Service Setting

PHP Warning:  ibase_connect(): Unable to complete network request to host "localhost". Failed to locate host machine. Undefined service gds_db/tcp.
Windowsで上のようなエラーが出る場合の対処。
C:\WINDOWS\system32\drivers\etc\SERVICES

...

gds_db          3050/tcp

...


Sabel

Sabel PHP Frameworkを開発しています。
http://www.sabel.jp/

Search
Categories
Tags
Recent Articles
Archives