# PHP の使いかた

このセクションにはPHPスクリプトを書くにあたってよく問題となる事柄が 集められています。

1. PHP の関数のパラメータの順番を覚えられません。だって関数によってばらばらなんだもん。
2. あらゆるフォームから送信されたデータを扱うことができる汎用的な PHPスクリプトを書きたいのですが、POSTメソッドでどのようなデータ が送信されたかを知るにはどうするのですか？
3. シングルクオート(')をバックスラッシュでエスケープされた シングルクオート(\')に変換しなければならないのですが、 正規表現を用いてこれを行うにはどの様にするのですか？ 同様に " を \" に、\ を \\ に変換したいのです。
4. " は \" に、また ' は \' に全て変換されているのですが、 これら無用なバックスラッシュを除去するにはどうしたらよいですか？ どうやって、そしてなぜ、こんなことになっているのでしょう？
5. PHP の設定項目 register_globals はどんな影響があるの?
6. 次のようなコードを実行すると、思った通りの順番で出力が表示されません。 function myfunc($argument) { echo $argument + 10; } $variable = 10; echo "myfunc($variable) = " . myfunc($variable); なぜですか？
7. 改行されないのですが？ <pre> <?php echo "これは1行目"; ?> <?php echo "この行は改行に続いて出力されるはず"; ?> </pre>
8. 'Warning: Cannot send session cookie - headers already sent...'や 'Cannot add header information - headers already set...'といった メッセージが出力されるのですが。 sent...'.
9. リクエストヘッダに直接アクセスしたいのですが、どうすればよいですか？
10. IISで認証を行おうとすると'No Input file specified'というエラーが 発生します。
11. Windows: 他のコンピュータと共有しているファイルに、IIS でアクセスできません。
12. どうすればXMLとPHPは共存することが出来るのですか？XMLの <?xml>タグがPHPでエラーになります。
13. あらかじめ設定されている変数を全て網羅したリストはどこにあるので すか？なぜPHPのドキュメントにはその一覧がないのですか？
14. フリーではない商用ライブラリである PDFLibを使わずに PDFファイルを生成するにはどうしたらよいでしょうか？ フリーのもので、外部のPDFライブラリを必要としない ものがいいのです。
15. ユーザー定義関数の中で、標準的な ($DOCUMENT_ROOT や $HTTP_REFERER のような) CGI変数にアクセスしたいのですが、PHPはそれらの変数を見つけること ができていないようです。何がおかしいのですか？
16. いくつかの PHP ディレクティブでは、バイト値を integer ではなく省略形で設定できます。この省略形で使えるオプションを教えてください。
17. Windows で、 "127.0.0.1" だと動作するのに localhost を使うと接続がタイムアウトします。

PHP の関数のパラメータの順番を覚えられません。だって関数によってばらばらなんだもん。

  PHP は、さまざまな外部ライブラリの間を取り持つ糊のような存在です。 そのため、時にはちょっとごちゃごちゃすることもあります。 しかし、経験上、以下のような規則があるようです。

  配列関数 のパラメータは "needle, haystack" の順だけれども、 文字列関数 はその逆で "haystack, needle" の順となります。

あらゆるフォームから送信されたデータを扱うことができる汎用的な PHPスクリプトを書きたいのですが、POSTメソッドでどのようなデータ が送信されたかを知るにはどうするのですか？

  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 の設定項目 register_globals はどんな影響があるの?
  警告

  この機能は 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 であることを前提とした記事や書籍が存在します。 注意しましょう。

  詳しい情報は、以下のリソースを参照ください。

  - register_globals ディレクティブ
  - セキュリティに関する章での register_globals の説明
  - 外部からくる変数の処理
  - スーパーグローバル

  > 注意:

  > 上の例では、クエリ文字列を含む 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行もとても読めないくらい長いものになって しまいます。

'Warning: Cannot send session cookie - headers already sent...'や 'Cannot add header information - headers already set...'といった メッセージが出力されるのですが。 sent...'.

  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で認証を行おうとすると'No Input file specified'というエラーが 発生します。

  これはIISのセキュリティモデルの欠点で、IISで動作するCGIに共通する 問題です。これを回避策するには、認証のかかったディレクトリに(PHP が解釈しない)HTMLファイルを作成します。そしてMETAタグを使ってPHP を使用したページにリダイレクトするか、リンクを張ります。こうすれ ばPHPは認証済みかどうかを正しく認識することが出来ます。ISAPIモジュー ルの場合はこの問題は起きません。また、これは他のNTウェブサーバーに は影響ありません。詳しくは» http://support.microsoft.com/kb/q160422/ とHTTP 認証を 参照してください。

Windows: 他のコンピュータと共有しているファイルに、IIS でアクセスできません。

  Go to Internet Information Services を変更する必要があります。PHP ファイルを選択して プロパティを開き、セキュリティ タブに移動し、 Edit -< Anonymous access and authentication control 。

  この問題を解決するには Anonymous Access のチェックをはずして Integrated Window Authentication をチェックしたままにしておきか、 あるいは Anonymous Access をチェックしてアクセスできないユーザーを別途指定します。

どうすればXMLとPHPは共存することが出来るのですか？XMLの <?xml>タグがPHPでエラーになります。

  <?xml を直接PHPコードに埋め込むには、 PHPディレクティブのshort_tags を 0 に設定しなければなりません。 このディレクティブはini_set()でセットすることは できません。short_open_tags のオン/オフに関わらず、次のようにもできます: <?php echo '<?xml'; ?> このディレクティブはデフォルトでオンです。

あらかじめ設定されている変数を全て網羅したリストはどこにあるので すか？なぜPHPのドキュメントにはその一覧がないのですか？

  マニュアルの 定義済みの変数 のページを読んでください。スクリプト上で有効な定義済み変数のリストの 一部があります。有効な変数の完全なリスト（とその詳しい情報）は phpinfo()をコールすることで見ることができます。 マニュアルの PHPの外部から来る変数 のセクションも読んでください。HTMLフォームやCookie、URL等から 来る外部変数に関するシナリオが説明されています。

  > 注意: register_globals: 重要な注意

  > PHP 4.2.0 以降、PHP ディレクティブ register_globals のデフォルト値は off となっています。 PHP コミュニティは、ユーザーがこのディレクティブの設定に依存せず、 superglobals のような他の手段を使用することを推奨します。

フリーではない商用ライブラリである PDFLibを使わずに PDFファイルを生成するにはどうしたらよいでしょうか？ フリーのもので、外部のPDFライブラリを必要としない ものがいいのです。

  PHPで書かれている代替手段がいくつかあります。 » FPDF や » TCPDF などです。

  また、Haru 拡張モジュールもあります。 これは、フリーな外部ライブラリ libHaru を使用しています。

ユーザー定義関数の中で、標準的な ($DOCUMENT_ROOT や $HTTP_REFERER のような) CGI変数にアクセスしたいのですが、PHPはそれらの変数を見つけること ができていないようです。何がおかしいのですか？

  PHPディレクティブの register_globals がサーバーと環境変数に与える影響を認識することは重要なことです。 register_globals = off (PHP4.2.0以降デフォルトでoff)の場合、 $DOCUMENT_ROOTは存在しません。代わりに $_SERVER['DOCUMENT_ROOT']を使用してください。 register_globals = on の場合は $DOCUMENT_ROOTも $GLOBALS['DOCUMENT_ROOT']も存在します。

いくつかの PHP ディレクティブでは、バイト値を integer ではなく省略形で設定できます。この省略形で使えるオプションを教えてください。

  有効なオプションは 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 バイト。

Windows で、 "127.0.0.1" だと動作するのに localhost を使うと接続がタイムアウトします。

  PHP 5.3.4 を使っている場合、その原因は PHP のネットワーク解決に関するコードのバグです。 IPv6 が有効になっている環境では、ストリーム関連のすべての場面で localhost への接続に失敗していました。 回避策は、 "127.0.0.1" を使うようにするか IPv6 の名前解決を hosts ファイルで無効にするかのいずれかです。