エントリー

カテゴリー「制作」の検索結果は以下のとおりです。

SQLite3でオートインクリメント

細かい部分でつまづきつつ、PHP Labo のプログラムを書き換え中。

SQLite2でオートインクリメントな列を作りたい場合、テーブル作成時に

no INTEGER UNSIGNED NOT NULL PRIMARY KEY

としていたのだけど、SQLite3ではデータの挿入ができませんでした…。

address.no may not be NULL

とか言われてしまいます。(address はテーブル名。)色々試したところ、

no INTEGER PRIMARY KEY

ならSQLite2でもSQLite3でも大丈夫だった。調べてみると、NOT NULL を指定しているとバージョンによって微妙に挙動が異なるらしい。うーむ。

ちなみにSQLite3からは AUTOINCREMENT というキーワードが追加されているらしいけど、SQLite2では動作しないので上の方法で行くとします。

PDOの不具合

PDOのプレースホルダが意図したとおりに動作しません…。

$stmt = $pdo->prepare('SELECT * FROM address LIMIT ?, ?');
$flag = $stmt->execute(array(0, 5));

こんな風に書くと、SQLの文法エラーと言われてしまいます。
プレースホルダを文字で指定しても駄目。

$stmt = $pdo->prepare('SELECT * FROM address LIMIT :from, :to');
$flag = $stmt->execute(array(':from' => 0, ':to' => 5));

LIMIT句以外なら、普通にプレースホルダが機能するんだけどなぁ…。
ちなみに、bindValue() で値を指定してから execute() を実行するようにすればLIMIT句でも大丈夫だった。

$stmt = $pdo->prepare('SELECT * FROM address LIMIT ?, ?');
$stmt->bindValue(1, 0, PDO::PARAM_INT);
$stmt->bindValue(2, 5, PDO::PARAM_INT);
$flag = $stmt->execute();

文字で指定しても当然のように動作します。

$stmt = $pdo->prepare('SELECT * FROM address LIMIT :from, :to');
$stmt->bindValue(':from', 0, PDO::PARAM_INT);
$stmt->bindValue(':to',   5, PDO::PARAM_INT);
$flag = $stmt->execute();

なかなか原因が判らなかったけど、これはPDOの不具合らしい。

何とも厄介な…。公式サイトには

PDO::execute() errors when parameters are used in LIMIT clause

と書かれているので execute() の問題らしいけど、bindValue() を使えばバージョンに関わらず実行できる…と思っていいのかな…。
うっかりミスでSQLインジェクションが起こり得ないようにするためにプレースホルダを使っている(僕の場合は)ので、「LIMIT句に値を渡すときだけ直接指定する」という書き方は極力避けたいのだけど。

PDOお試し中

概要だけは知っていたけど、実際に使うのは多分初めて。PEAR::DB と同じような感覚で使えて良い感じです。

PDO でのエラー処理は trycatch で捕捉するのが定番みたいですが、PEAR::DB みたいに戻り値のチェックで処理することもできるのですね。
PHP Labo のプログラムは非オブジェクト指向(手続き型)で書くので、エラー処理も昔ながらの方法にしようかなぁ…。その場合、こんな感じ?

<?php

try {
  $pdo = new PDO(
    'mysql:dbname=phpdb;host=localhost',
    'user',
    'pass',
    array(
      PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT
    )
  );
} catch (PDOException $e) {
  exit($e->getMessage());
}

$stmt = $pdo->query('SELECT * FROM address');
if (!$stmt) {
  list($state, $code, $message) = $pdo->errorInfo();
  exit($state . ':' . $code . ':' . $message);
}

while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
  echo $data['no'] . ':' . $data['name'] . "<br>\n";
}

?>

コンストラクタのエラーは trycatch でしか補足できなかった。他に方法が無いか、後でもう少し調べてみます。でもやっぱり、データベースのエラーは全部 trycatch で処理した方がスッキリ書けるかなぁ…。
今のところ使っていないけど、トランザクションを使う場合は特に便利だし。

また、SQLite2を使うかSQLite3を使うかで、コンストラクタに渡す値が微妙に異なります。うーん、設定ファイルでSQLite2、SQLite3、MySQLを切り替えるようにするかな。

PHP4→PHP5への移行

このサイトはロリポップを使用しているのですが、とうとうPHP5に移行するらしいです。ちなみに Web Liberty はWADAXを使用していますが、結構前にPHP5に移行済み。
その他のサーバーもPHP4が使えなくなるのは時間の問題だと思うので、PHP Labo のプログラムをPHP4非対応に修正していきます。
代わりに、PHP5で追加された機能を色々使います。PEARが不要になるので、設置も楽になるハズ。

そんな訳で、自分用に移行メモ。「オブジェクトのコピー方法が云々」とか紹介しているのではなくて、あくまでも PHP Labo のプログラムを修正するための自分用作業メモ。ちなみに、厳密にはPHP5.1以降への移行が前提になっています。

  • PEAR::DB ではなく PDO を使用する。
  • opendir() ではなく scandir() を使用する。
  • fopen() + fwrite() + fclose()file_put_contents() で処理できる。ただし、ロック方法などを後で調べる。
  • fgetcsv() はPHP4とは異なり日本語処理に難があるため、使い物にならなくなっている(ような気がする)。文字コードの問題っぽい?
  • セッションハイジャック対策に session_regenerate_id(true) を使用する。
  • XMLの解析には SimpleXML が便利。
  • 初期設定ではMySQLではなくSQLiteを使用するようにしておく。

思いついたら追加します。
あと、PHP5への移行と同時に、ちょっとだけ機能強化もする予定。

ようやく仕事が直接関係しないプログラミングができると思うと、何だかテンションが上がるぞ。

PHPでツリー表示プログラム

これも必要になったのでメモ。

<?php

function put_tree($no, $line, $broths, $childs, $texts) {
  echo '<span class="line">' . $line . '</span>';
  echo '▼[' . $no . ']' . $texts[$no] . '<br>';

  $line = preg_replace('/├$/', '│', $line);
  $line = preg_replace('/└$/', ' ', $line);

  $no = isset($childs[$no]) ? $childs[$no] : 0;

  while ($no > 0) {
    $tail = $broths[$no] ? '├' : '└';
    put_tree($no, $line . $tail, $broths, $childs, $texts);
    $no = $broths[$no];
  }
}

?>
<html>
<head>
<title>ツリー表示</title>
<style>
.line {
  font-family: "MS ゴシック", monospace;
}
</style>
</head>
<body>
<?php

$logs = array(
  array(1, 0, 'あああああ'), //記事番号・親記事番号・記事内容
  array(2, 1, 'いいいいい'),
  array(3, 1, 'ううううう'),
  array(4, 2, 'えええええ'),
  array(5, 3, 'おおおおお'),
  array(6, 3, 'かかかかか'),
  array(7, 0, 'ききききき'),
  array(8, 6, 'くくくくく'),
  array(9, 8, 'けけけけけ'),
  array(10, 7, 'こここここ')
);

$roots  = array();
$broths = array();
$childs = array();
$texts  = array();

foreach ($logs as $log) {
  list($no, $pno, $text) = $log;

  if ($pno == 0) {
    $roots[] = $no;
  } else {
    $broths[$no]  = isset($childs[$pno]) ? $childs[$pno] : 0;
    $childs[$pno] = $no;
  }
  $texts[$no] = $text;
}
rsort($roots);

foreach ($roots as $root) {
  put_tree($root, '', $broths, $childs, $texts);
}

?>
</body>
</html>

実行結果は以下のとおり。

▼[7]ききききき
└▼[10]こここここ
▼[1]あああああ
├▼[3]ううううう
│├▼[6]かかかかか
││└▼[8]くくくくく
││ └▼[9]けけけけけ
│└▼[5]おおおおお
└▼[2]いいいいい
 └▼[4]えええええ

ツリー生成手順は、以下の書籍を参考にしています。プログラミングをはじめた頃によく読んでいた本なので、久しぶりに読んで懐かしい…。

CGI&SSIを使うとホームページ作成にこんなに差が出る

PHPで2ch互換トリップ生成

必要になったので自分用にメモ。トリップ生成時の文字コードはShift-JISにしておく。

<?php

$tripkey = '#istrip';? //パスワードとする文字列(# 付き)
$tripkey = substr($tripkey, 1);

$salt = substr($tripkey . 'H.', 1, 2);
$salt = preg_replace('/[^\.-z]/', '.', $salt);
$salt = strtr($salt, ':;<=>?@[\\]^_`', 'ABCDEFGabcdef');

$trip = crypt($tripkey, $salt);
$trip = substr($trip, -10);
$trip = '◆' . $trip;

echo $trip;

?>

トリップの概要とコードは以下のページを参考にしました。(参考というか、ほぼそのまま。)

トリップ (2ちゃんねる) - Wikipedia

自宅サーバーをさらしてみる

連続稼動3日目。普通に接続できているので、そろそろさらしてみます。

http://www.favorite-labo.net/

コンテンツは、以前に作ったAmazonレビュー検索プログラムを置いているだけ。とりあえず、自分用ツールを色々置いていくとします。
突然サーバーダウンすることがあるかもしれませんが、OSの再インストールやハードの故障などで作業中だと思ってください。(^^;

もし、マズイ設定箇所などを見つけたら、メールでこっそり教えていただけると嬉しいです。

自宅サーバー再インストール完了

一応完了。あとは使いながら調整していくつもり。Perl5、PHP5、MySQL5 を使えるようにしておいたので、色々遊んでみます。

ポートは80番のみ開放。ファイルアップロードはFTPを使うけど、アクセスはLAN内のみに限定。モデム・ルータ・CentOS のファイヤーウォールは、それぞれできるだけ厳しく設定したつもり。勿論、ファイル改竄検知システムやアンチウィルスソフトなども導入済み。Apacheのアクセスログ解析のために、AWStats もインストールしておいた。

とは言え、PerlとPHPが実行できる環境だし、80番ポートから感染するウイルスもあるので安心はできません…。少しでも不審な事があれば、OSごとインストールしなおすとします。(まずは「不審な事」に気付くための知識が必要だけど。)

ちなみに、24時間稼動させるのは、もうしばらく先の予定。

自宅サーバー再インストール中

現在CentOS5インストール中。「色々いじってから、OSごと再インストール」を繰り返しているので、インストールは4回目だったりします。(CentOS4を2回、CentOS5を2回)
多少は慣れてきたので、今回は長期間稼動させるつもり。

メールは相変わらず外部に送信できないのですが、root宛てにサーバーの状態を通知する目的には使えるので、当分は現状のまま進めるとします。もともとメールサーバーを立てるつもりは無い(むしろ凄く大変そうなので立てたくない)ので、特に問題は無し。フォームメールは使いたいけど、メールサーバーを立てなくても色々やりようはあるのです。

自宅サーバーいじり中

UNIXの絵本を読みつつ基礎を勉強中。この本が一番解りやすいと思った。

PHPからのメール送信は試してみたけど、まだ送信できず…。
MAILER-DAEMONからエラーメールは送られてくるので、メールサーバーは動作しているはず。OP25B対策が不十分なんだろうか。

ページ移動

ユーティリティ

カテゴリー

検索

エントリー検索フォーム
キーワード

過去ログ

過去ログ表示フォーム
キーワード

Feed