PHP Velho Oeste 2024

PHP と HTML

PHP と HTML は深く関係しています。PHP は HTML を生成し、HTML には PHP に 送信される情報が記述されています。 以下の FAQ を読む前に、どうやって 外部から来る変数を取得するかを読んでおくことは重要です。 このマニュアルにはこのトピックに関するよい例があります。

フォームから、もしくは URL から値を渡す場合にはどういった エンコード/デコードが必要なのですか?

エンコードが重要になる場面はいくつかあります。 string $data という エンコードされていない文字列データを渡す場合について考えてみると、

  • HTML を通じて渡す場合: 文字列にはどのような値が含まれるか分からないので、 データは必ず htmlspecialchars を行い、 ダブルクオートで囲まなければなりません。

  • URL を通じて渡す場合: URL はいくつかのパーツから成り立ちます。 このデータをそのパーツのうちの一つであると解釈させたいならば、 urlencode() でエンコード しなければなりません。

例1 HTML の hidden 要素

<?php
echo '<input type="hidden" value="' . htmlspecialchars($data) . '" />'."\n";
?>

注意: $dataurlencode() をしては いけません。なぜなら、その作業はブラウザに任されているからです。 一般に普及している全てのブラウザは正しくこの処理を行ってくれます。 ただ、この処理はメソッド(GET や POST)が何であるかにかかわらずに 行われるということに気をつけてください。この処理に気づくのは GET リクエストのときだけになるでしょう。なぜなら POST リクエストの内容は通常目に触れることは無いからです。

例2 ユーザーによって編集するデータ

<?php
echo "<textarea name='mydata'>\n";
echo
htmlspecialchars($data)."\n";
echo
"</textarea>";
?>

注意: ブラウザはエスケープされたシンボルを解釈するので、data は 意図したとおりに表示されます。 フォームの内容を送信するとき、GET か POST かにかかわらず data は ブラウザによって URL エンコードされ、PHP によって URL デコードされます。 要は、URL エンコード/デコードを自分で行う必要はなく、これらの処理は すべて自動的に行われると言うことです。

例3 URL 中の場合

<?php
echo '<a href="' . htmlspecialchars("/nextpage.php?stage=23&data=" .
urlencode($data)) . '">'."\n";
?>

注意: この例では、実は GET リクエストを摸擬しています。このため、data を手動で urlencode() する必要があります。

注意: 全ての URL を htmlspecialchars() する必要があります。 なぜなら、この URL は HTML の value 属性として扱われるからです。 この場合は、ブラウザはまず htmlspecialchars() された データを元に戻し、それから URL を渡します。URL は urlencode() されているので、PHP はこれを正しく 解釈することができます。 URL 中の &&amp; に置き換えられていることに気づくでしょう。もしあなたがこれを忘れても ほとんどのブラウザは元に戻してくれますが、必ずそうしてくれるとは 限りませんので、URL が動的に変更されるものでなくても URL は htmlspecialchars() されるべき です。

<input type="image"> タグを使おうとしているのですが、変数 $foo.x$foo.y が使えません。 $_GET['foo.x'] も存在していません。どうすればよいのですか?

以下のようなタグを使えば、標準のボタンの代わりに画像を使用して フォームを送信することができます。

<input type="image" src="image.gif" name="foo" />
ユーザーが画像のどこかをクリックすると、そのフォームの内容に foo.xfoo.y という 2 つの変数が追加され、サーバーに送信されます。

PHP では foo.xfoo.y という名前は変数名として正しくないので、 自動的に foo_xfoo_y という名前に変換されます。要は、ピリオドが アンダースコアに置き換えられる、と言うことです。そのため、これらの 変数にアクセスする際には 外部から来る変数 の取得についてのセクションで記述されているのと同様な方法を とります。たとえば $_GET['foo_x'] などです。

注意:

リクエスト変数名の中のスペースは、アンダースコアに置き換えられます。

HTML フォームで配列を使用するにはどうすればよいですか?

フォームの内容を PHP スクリプトで配列として受け取るには、 <input>、<select> あるいは <textarea> といった要素の name を以下のように指定します:

<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />
変数名の最後にある括弧に注意してください。これにより、フォー ムの内容が配列として扱われます。異なる要素に同じ名前をつけること で要素を配列にグループ分けすることができます。
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyOtherArray[]" />
<input name="MyOtherArray[]" />
上記の HTML の場合、MyArray と MyOtherArray という 2 つの配列が生成され、 PHP スクリプトに送信されます。また、配列に特定のキーを設定する こともできます。
<input name="AnotherArray[]" />
<input name="AnotherArray[]" />
<input name="AnotherArray[email]" />
<input name="AnotherArray[phone]" />
この場合、配列 AnotherArray のキーは 0、1、email そして phone となります。

注意:

HTML に配列のキーを指定するかどうかは自由です。キーを指定しなかった 場合はフォームに現れる順番に番号がつけられます。最初の例だと、 キーは 0、1、2、3 となります。

配列関数外部から来る変数 も参照ください。

"select multiple" タグで選択された全ての結果を取得するには どうすればよいですか?

"select multiple" タグを使うと、ユーザーはリストから複数の項目を 選択することができるようになります。選択された項目はフォームの action で指定されたハンドラに渡されます。問題は、これらの値が全て 同じ名前で渡されることです。つまり、

<select name="var" multiple="yes">
選択されたそれぞれの項目は action のハンドラに次のように渡されます:
var=option1
var=option2
var=option3
      
それぞれの項目は前の変数 $var の値を上書きして しまいます。この問題を解決するには、PHPの "フォームの値を配列にする" 機能を使います。以下のようにするとよいでしょう。
<select name="var[]" multiple="yes">
こうすれば PHP に $var を配列として扱うように 知らせることができ、各項目の value の値は配列の要素として var[] に 追加されます。最初の項目は $var[0] になり、 次の項目は $var[1]... というようになります。 count() 関数を使えば選択された項目の数を知る ことができます。またもし必要なら sort() 関数を 使ってソートを行うこともできます。

JavaScript を使っている場合、フォーム要素に要素名を使って(訳注: document.myform.myelement.value 等の様に)アクセスしようとすると、 要素名に含まれる [] が問題となることがあるので 気をつけてください。この場合は、数字で表されるフォーム要素の ID を 使用するか、シングルクオートで要素名を囲んでフォーム要素の配列の インデックスとしてアクセスしてください。例えば、以下のようにします:

variable = document.forms[0].elements['var[]'];
      

JavaScript から PHP に変数を渡すには?

JavaScript は(普通は)クライアントサイド技術であり、一方 PHP は(普通は) サーバーサイド技術です。また HTTP は"ステートレスな"プロトコルです。 そのため、この二つの言語はダイレクトに変数を共有することができません。

しかしながら、この二つの言語の間で変数を渡すことは可能です。 一つの方法は PHP と一緒に JavaScript のコードを生成し、 ブラウザに自動的にリフレッシュ(再ロード)させることです。 以下の例はまさにそれで、PHP に画面の高さと幅を認識させています。 これは通常はクライアントサイドでしかできないことです。

例4 PHP による JavaScript の生成

<?php
if (isset($_GET['width']) AND isset($_GET['height'])) {
// ジオメトリ値を出力する
echo "画面の幅: ". $_GET['width'] ."<br />\n";
echo
"画面の高さ: ". $_GET['height'] ."<br />\n";
} else {
// ジオメトリ変数を渡す
// (元のクエリ文字列を保持する
// -- POST 変数は別の方法で扱う必要がある)

echo "<script language='javascript'>\n";
echo
" location.href=\"{$_SERVER['SCRIPT_NAME']}?{$_SERVER['QUERY_STRING']}"
. "&width=\" + screen.width + \"&height=\" + screen.height;\n";
echo
"</script>\n";
exit();
}
?>

add a note add a note

User Contributed Notes 7 notes

up
1
murphy
4 years ago
The scenario:

1. There is a php script which (possibly complemented by a direct written HTML code) consrtucts a HTML page via its echo command, based on whatever algoritmus eventually based on supplementary data from server files or databases.

2. This php script leads to data being saved into string variable(s), which (possibly) can contain arbitrary characters, including control codes (newline, tab...), HTML special characters (&,<...) and non-ASCII (international) characters.

3. These non-ASCII characters are UTF-8 encoded, as well as the HTML page (I do highly recommend) *)

4. The values of these PHP string variables have to be transferred into javascript variables for further processing by javascript (or exposing these values in HTML directly)

The problem:

it is not safe to PHP-echo such variables into HTML (javascript) directly, because some of characters possily contained in them cause malfunction of the HTML. These strings need some encoding/escaping in order to become strings of non-conflicting characters

The solution

There may be a big lot of ways of this encoding. The following one seems to me the easiest one:
The PHP variable with unpredictable value can originate from some file, as an example (or from user input as well):

$variable=file_get_content(...)

1. Convert all bytes of that string into hex values and prepend all hex-digit-pairs with %

$variable_e=preg_replace("/(..)/","%$1",bin2hex($variable))

The new variable is now guarantied to contain only %1234567890abcdefABCDEF chracters (e.g. %61%63%0a...) and can safely be directly echoed into HTML:

var variable="<?php echo $variable_e;?>" //that's NOT all folks

But now the value is still encoded. To get the original value of the variable, it has te be decoded: *)

var variable=decodeURIComponent("<?php echo $variable_e;?>")

The value of the variable is now the same as the original value.

*) I have no idea about non-UTF-8 encoded pages/data, espetially how the decodeURIComponent works in such a case, because i have no reason to use other encodings and handle them as highly deprecatad.

WARNING: this approach is not (generally) safe against code injection. I highly recommend some further check (parsing) of the value depending on the particular case.

P.S. For very large amount of data, I would recomment to save them into file on the PHP side (file_put_content) and read them by javascript via HTTP Request.

I use this approach as it needs one line of code on server as well as client side. I do agree with arguement that not all chaeacters have to be encoded.

Do not enjoy my possibly stupid solution, if you have a better idea

murphy
up
-4
Anonymous
3 years ago
I think the last example on this page may have a XSS vulnreability, e.g. sending the query string ?a="+alert('XSS')+" might cause alert('XSS') to be executed in the browser. The problem with that is that " will be percent encoded by the browser, but there could be some way to bypass the percent encoding and i think it's not good to rely on the percent encoding for security.
up
-5
Anonymous
3 years ago
There is also a very easy XSS with the width and height parameters - they should be passed through htmlspecialchars
up
-21
starbugfourtytwo at gmail dot com
4 years ago
Why use such a complicated example for js to php? why not do this..so we can understand:

javascript:

const variable = "A"

php:

do whatever it takes to get A from javascript
up
-24
smileytechguy at smileytechguy dot com
6 years ago
The (at least that I've found) best way to pass data from PHP to JS is json_encode.  Doing so will convert arrays, strings, numbers, etc. as best as possible.

<?php
$myInt
= 7;
// a bunch of special characters to demonstrate proper encoding
$myString = <<<EOF
" ' ; &\ $
EOF;
$myArr = [1, "str", 2];
$myAssocArr = ["foo" => "bar"];
?>

<script>
var myInt = <?= json_encode($myInt) ?>;
var myString = <?= json_encode($myString) ?>;
var myArr = <?= json_encode($myArr) ?>;
var myAssocArr = <?= json_encode($myAssocArr) ?>;
</script>

This will render the following JS code, which correctly stores the variables:
<script>
var myInt = 7;
var myString = "\" ' ; &\\ $";
var myArr = [1,"str",2];
var myAssocArr = {"foo":"bar"};
</script>

Do note that there are no "s or anything like that around the json_encode output; json_encode handles that for you.
up
-58
jetboy
18 years ago
While previous notes stating that square brackets in the name attribute are valid in HTML 4 are correct, according to this:

http://www.w3.org/TR/xhtml1/#C_8

the type of the name attribute has been changed in XHTML 1.0, meaning that square brackets in XHTML's name attribute are not valid.

Regardless, at the time of writing, the W3C's validator doesn't pick this up on a XHTML document.
up
-63
Jay
10 years ago
If you have a really large form, be sure to check your max_input_vars setting.  Your array[] will get truncated if it exceeds this.  http://www.php.net/manual/en/info.configuration.php#ini.max-input-vars
To Top