PHP 和 HTML

PHP 和 HTML 有很多相互作用:PHP 能生成 HTML,HTML 可以向 PHP 传递信息。在阅读这些常见问题之前,先学会怎样 从 PHP 之外取得变量很重要。此主题的手册页也包括很多例子。还要仔细留意 register_globals对你意味着什么。

当我通过表单/URL 传值时需要用什么编码/解码方法?

在几个环节上编码方式很重要。假定有 string $data,其中包含了想通过非编码方式传递的字符串,那这是相关步骤:

  • HTML 解析。要指定一个任意的字符串, 必须将其放在双引号中,并用 htmlspecialchars()处理整个值。

  • URL:URL 由几部分组成。如果希望自己的数据被当作其中一项来解释, 必须urlencode()对其编码。

Example #1 隐藏的 HTML 表单单元

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

Note: urlencode()来处理 $data是错误的,因为是浏览器的责任来 urlencode()数据。所有流行的浏览器都能正确处理。注意不论何种方法(例如 GET 或 POST)都会这样。不过只会在用 GET 请求时注意到这一点,因为 POST 请求通常是隐藏的。

Example #2 等待用户编辑的数据

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

Note: 数据会按照预期的显示在浏览器中,因为浏览器会解释 HTML 转义符号。 当提交时,不论是 GET 或者 POST 方法,数据都会被浏览器进行 urlencode 来传输,并直接被 PHP urldecode。所以最终不需要自己处理任何 urlencoding/urldecoding,全都是自动处理的。

Example #3 URL 中的例子

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

Note: 事实上这在编造一个 HTML 的 GET 请求,因此需要手工对数据进行 urlencode()

Note: 需要对整个 URL 进行 htmlspecialchars(),因为 URL 是作为 HTML 属性的一个值出现的。在本例中,浏览器会首先对值进行 un- htmlspecialchars(),然后再传递此 URL。PHP 将能正确理解 URL,因为对数据进行了 urlencoded() 要注意到 URL 中的 &被替换成了 &amp;。如果忘了这一步,尽管大多数浏览器都能恢复,但也不总是这样。因此即使 URL 不是动态的,也 需要对 URL 进行 htmlspecialchars()

我在试用 <input type="image"> 标记,但是没有 $foo.x$foo.y变量,它们哪去了?

当提交表单时,可以用图片代替标准的提交按钮,用类似这样的标记:

<input type="image" src="image.gif" name="foo" />
当用户点击了图片的任何部分,该表单会被发送到服务器并加上两个额外的变量: foo.xfoo.y

因为 foo.xfoo.y在 PHP 中会成为非法的变量名,它们被自动转换成了 foo_xfoo_y。也就是用下划线代替了点。因此,可以按照在 来自 PHP 之外的变量这一节中说明的那样访问这些变量。例如, $_GET['foo_x']

Note:

请求变量名中的空格被转换为下划线。

怎样在 HTML 的 <form> 中建立数组?

要使你的 <form> 结果被当成 array发送到 PHP 脚本,要对 <input>,<select> 或者 <textarea> 单元这样命名:

<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />
注意变量名后的方括号,这使其成为一个数组。可以通过给不同的单元分配相同的名字来把单元分组到不同的数组里:
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyOtherArray[]" />
<input name="MyOtherArray[]" />
这将产生两个数组,MyArray 和 MyOtherArray,并发送给 PHP 脚本。还可以给数组分配指定的键名:
<input name="AnotherArray[]" />
<input name="AnotherArray[]" />
<input name="AnotherArray[email]" />
<input name="AnotherArray[phone]" />
AnotherArray 数组将包含键名 0,1,email 和 phone。

Note:

指定数组的键名是 HTML 的可选项。如果不指定键名,则数组被按照单元在表单中出现的顺序填充。第一个例子将包含键名 0,1,2 和 3。

参见 数组函数来自 PHP 之外的变量

怎样从可多选的 HTML 的 select multiple 标记中得到所有结果?

可多选的 select multiple 标记是 HTML 的一个构造,允许用户从一个列表中选择多个项目。这些项目接着被传递给该表单 action 中指定的处理程序。问题是它们都会被用同样的名字传递。例如:

<select name="var" multiple="yes">
每个被选项将这样被传递到表单处理程序:
var=option1 var=option2 var=option3
每个选项将覆盖前面一个 $var变量的内容。解决方案是用 PHP 的"表单单元数组"特性。使用方法如下:
<select name="var[]" multiple="yes">
这将告诉 PHP 将 $var当成数组对待,每个对 var[] 的赋值都会给数组增加一项。第一项将成为 $var[0],下一个是 $var[1],等等。可以用 count()函数来测定选择了多少个项目,必要时可以用 sort()函数来对选项的数组进行排序。

注意如果在 JavaScript 中通过名字来引用单元,单元名字中的 []可能会造成问题。用表单单元中的数字序号来替代,或者将变量名用单引号括起来并用其作为单元数组的索引,例如:

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

怎样从 Javascript 传递一个变量到 PHP?

由于 Javascript (通常情况下)是客户端技术,而 PHP (通常情况下)是服务器端技术,而且 HTTP 是一种"无状态"协议,因此两种语言之间不能直接共享变量。

但是,有可能在二者之间传递变量。一种实现的方法是用 PHP 生成 Javascript 代码,并让浏览器自动刷新,将特定的变量传递回 PHP 脚本。以下例子显示了如何这样做——让 PHP 代码取得显示屏幕的高度和宽度,通常只能在客户端这么做。

<?php
if (isset($_GET['width']) AND isset($_GET['height'])) {
  
// output the geometry variables
  
echo "Screen width is: "$_GET['width'] ."<br />\n";
  echo 
"Screen height is: "$_GET['height'] ."<br />\n";
} else {
  
// pass the geometry variables
  // (preserve the original query string
  //   -- post variables will need to handled differently)

  
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();
}
?>

User Contributed Notes

Anonymous 09-Apr-2021 12:21
There is also a very easy XSS with the width and height parameters - they should be passed through htmlspecialchars
Anonymous 09-Apr-2021 12:16
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.
murphy 28-Jan-2020 08:58
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
starbugfourtytwo at gmail dot com 29-May-2019 11:04
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
smileytechguy at smileytechguy dot com 02-Feb-2018 04:55
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.
Jay 01-Apr-2014 09:25
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
jetboy 30-Dec-2005 07:06
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.
PHP8中文手册 站长在线 整理 版权归PHP文档组所有