このセクションにはPHPスクリプトを書くにあたってよく問題となる事柄が 集められています。
PHP は、さまざまな外部ライブラリの間を取り持つ糊のような存在です。 そのため、時にはちょっとごちゃごちゃすることもあります。 しかし、経験上、以下のような規則があるようです。
配列関数 のパラメータは "needle, haystack" の順だけれども、 文字列関数 はその逆で "haystack, needle" の順となります。
PHPは$_POSTのような 定義済みの変数 を沢山提供しています。$_POSTを連想配列として ループすることでPOSTされた全ての値にアクセスできます。例えば、 foreach で単純にループして empty() で値をチェックし、 結果を出力します。
<?php
$empty = $post = array();
foreach ($_POST as $varname => $varvalue) {
if (empty($varvalue)) {
$empty[$varname] = $varvalue;
} else {
$post[$varname] = $varvalue;
}
}
print "<pre>";
if (empty($empty)) {
print "None of the POSTed values are empty, posted:\n";
var_dump($post);
} else {
print "We have " . count($empty) . " empty values\n";
print "Posted:\n"; var_dump($post);
print "Empty:\n"; var_dump($empty);
exit;
}
?>
もしデータベースに格納するためにそんなことをしようとしているのなら、 データベース自身が持つエスケープの仕組みを使うようにしましょう。 MySQL なら mysql_real_escape_string()、 PostgreSQL なら pg_escape_string() などです。 汎用的な関数 addslashes() や stripslashes() もありますが、 これはさらに古い時代の PHP コードで使われていたものです。
注意: ディレクティブに関する注意: magic_quotes_gpc
PHP ディレクティブmagic_quotes_gpc のデフォルトは on です。この場合、すべての GET, POST, COOKIE データに ついて addslashes() が実行されます。 これらを取り除くため stripslashes() を使用することが できます。
なぜかバックスラッシュがついてしまう、という現象の原因のほとんどは、PHP の magic_quotes_gpc ディレクティブが On になっていることです。これは古い時代の PHP の機能であり、現在は無効にしておくべきものです。この仕組みに頼ってはいけません。 文字列からバックスラッシュを取り除くために、PHP の stripslashes() を使うことができます。
注意: ディレクティブに関する注意: magic_quotes_gpc
PHP ディレクティブmagic_quotes_gpc のデフォルトは on です。この場合、すべての GET, POST, COOKIE データに ついて addslashes() が実行されます。 これらを取り除くため stripslashes() を使用することが できます。
この機能は PHP 5.3.0 で 非推奨となり、 PHP 5.4.0 で削除されました。
まずはじめに、この ini 設定がどういうはたらきをするのかを説明します。 例として、次のような URL を使用します。 http://example.com/foo.php?animal=cat そして foo.php の中身は次のようなコードが書かれているものとします。
<?php
// ここでは $_GET を使うことを推奨します
echo $_GET['animal'];
// $animal を使用するには register_globals が on でなければなりませんが
// こんなことはしないでください
echo $animal;
// これはすべての変数について当てはまります。たとえば $_SERVER についても同じで、
echo $_SERVER['PHP_SELF'];
// $PHP_SELF を使用するには register_globals が on でなければなりません
// 改めて言いますが、こんなことはしないでください
echo $PHP_SELF;
?>
上のコードでおわかりのように、register_globals を使用すると数多くの変数が作成されます。 長年にわたってこの手のコーディングは問題視されており、 ここ数年 register_globals のデフォルト設定は無効になっています。 大半のウェブサーバーは register_globals を無効にしていますが、 いまだに register_globals が on であることを前提とした記事や書籍が存在します。 注意しましょう。
詳しい情報は、以下のリソースを参照ください。
注意:
上の例では、クエリ文字列を含む URL を使用しています。 このように情報を渡す場合には GET HTTP リクエストを使用するので、 この場合はスーパーグローバル $_GET を使用します。
function myfunc($argument)
{
echo $argument + 10;
}
$variable = 10;
echo "myfunc($variable) = " . myfunc($variable);
式の中で関数の実行結果を使用する(例えば上の例の様に他の文字列と 連結する)ためには、echo するのではなく、その 値を return しなければいけません。
<pre>
<?php echo "これは1行目"; ?>
<?php echo "この行は改行に続いて出力されるはず"; ?>
</pre>
PHPでは、"?>"か"?>\n"(\nは改行を表します)をPHPのコードブロッ クの終端と見なします。このため、コードブロック終端の改行記号は省 略され、表示される文は1行になります。つまり、改行をさせるために は、PHPのコードブロックの終端の後にもう1つ改行を挿入する必要があ るということです。
なぜPHPはこのようなことをするのでしょうか?なぜならHTMLを出力する 場合にはこの方が都合のよいことが多いからです。もしとても長い1行を 出力しなければならない場合に、改行が解釈されてしまうとしたらどう でしょう。ソースコードの1行もとても読めないくらい長いものになって しまいます。
header(), set_cookie()や セッション関数は出力ストリームに ヘッダを付加する関数で、ヘッダを送信できるのは本文の出力を 開始する前のみです。headers_sent()を使って 既にヘッダが送信済みでないかチェックすることができます。 出力制御関数もご覧ください。
もしPHPがApacheモジュールとして動作しているなら、 getallheaders()を使えば全てのヘッダを取得する ことができます。下のちょっとしたコードで全てのリクエストヘッダを 表示することができます。
$headers = getallheaders();
foreach ($headers as $name => $content) {
echo "headers[$name] = $content<br />\n";
}
apache_lookup_uri(), apache_response_headers(), fsockopen()も参照してください。
これはIISのセキュリティモデルの欠点で、IISで動作するCGIに共通する 問題です。これを回避策するには、認証のかかったディレクトリに(PHP が解釈しない)HTMLファイルを作成します。そしてMETAタグを使ってPHP を使用したページにリダイレクトするか、リンクを張ります。こうすれ ばPHPは認証済みかどうかを正しく認識することが出来ます。ISAPIモジュー ルの場合はこの問題は起きません。また、これは他のNTウェブサーバーに は影響ありません。詳しくは» http://support.microsoft.com/kb/q160422/ とHTTP 認証を 参照してください。
Go to Internet Information Services を変更する必要があります。PHP ファイルを選択して プロパティを開き、セキュリティ タブに移動し、 Edit -< Anonymous access and authentication control 。
この問題を解決するには Anonymous Access のチェックをはずして Integrated Window Authentication をチェックしたままにしておきか、 あるいは Anonymous Access をチェックしてアクセスできないユーザーを別途指定します。
<?xml を直接PHPコードに埋め込むには、 PHPディレクティブのshort_tags を 0 に設定しなければなりません。 このディレクティブはini_set()でセットすることは できません。short_open_tags のオン/オフに関わらず、次のようにもできます: <?php echo '<?xml'; ?> このディレクティブはデフォルトでオンです。
マニュアルの 定義済みの変数 のページを読んでください。スクリプト上で有効な定義済み変数のリストの 一部があります。有効な変数の完全なリスト(とその詳しい情報)は phpinfo()をコールすることで見ることができます。 マニュアルの PHPの外部から来る変数 のセクションも読んでください。HTMLフォームやCookie、URL等から 来る外部変数に関するシナリオが説明されています。
注意: register_globals: 重要な注意
PHP 4.2.0 以降、PHP ディレクティブ register_globals のデフォルト値は off となっています。 PHP コミュニティは、ユーザーがこのディレクティブの設定に依存せず、 superglobals のような他の手段を使用することを推奨します。
PHPで書かれている代替手段がいくつかあります。 » FPDF や » TCPDF などです。
また、Haru 拡張モジュールもあります。 これは、フリーな外部ライブラリ libHaru を使用しています。
PHPディレクティブの register_globals がサーバーと環境変数に与える影響を認識することは重要なことです。 register_globals = off (PHP4.2.0以降デフォルトでoff)の場合、 $DOCUMENT_ROOTは存在しません。代わりに $_SERVER['DOCUMENT_ROOT']を使用してください。 register_globals = on の場合は $DOCUMENT_ROOTも $GLOBALS['DOCUMENT_ROOT']も存在します。
有効なオプションは K(キロバイト)、M(メガバイト)および G(ギガバイト: PHP 5.1.0 以降で有効)です。これらはすべて、大文字小文字を区別しません。 これ以外の文字はバイト値と判断されます。 1M は、1 メガバイトあるいは 1048576 バイトと等しくなります。1K は、1 キロバイトあるいは 1024 バイトです。この表記法は、 php.ini や ini_set() 関数で使えます。
注意: キロバイト? キビバイト?
PHP の記法では 1 キロバイト = 1024 バイトとしていますが、 IEC の標準規格では 1024 バイトのことを 1 キビバイト (kibibyte) と呼ぶことになっています。 まとめ: PHP での k および K = 1024 バイト。
PHP 5.3.4 を使っている場合、その原因は PHP のネットワーク解決に関するコードのバグです。 IPv6 が有効になっている環境では、ストリーム関連のすべての場面で localhost への接続に失敗していました。 回避策は、 "127.0.0.1" を使うようにするか IPv6 の名前解決を hosts ファイルで無効にするかのいずれかです。