数字营销 · Web开发 · 基础设施

PHP 接收处理多个 name 相同但 value 不同的表单数据

记录一次 ASP 系统迁移 PHP 时,处理多个同名表单字段及字符串、数组兼容问题的实践。

此文章为历史存档,问题已经解决,Domai CMS已经能够接收相同表单值提交的数据并自动整合,有需要进一步了解的可以和我沟通

最近在迁移一个询盘留言管理系统时遇到了一个问题。

原来的系统使用 ASP 开发,现在需要逐步迁移到 PHP 平台。看起来只是后台语言的切换,但实际迁移过程中有一个比较麻烦的要求:

前台现有的表单尽量不能改动。

因为这套表单已经被很多网站使用,如果直接修改前台代码,就意味着这些网站都需要逐个调整。同时,甚至连表单的提交地址都不能轻易改变,仍然需要保持提交到原来的 ASP 页面地址。

提交地址的问题还比较容易解决,可以通过伪静态或者其他方式,将原来的地址转到新的 PHP 处理程序。

真正麻烦的是表单字段。

多个相同 name 的 input

原来的留言表单中,存在多个 name 相同的 input,例如:

<inputtype="text"name="a"/>
<inputtype="text"name="a"/>
<inputtype="text"name="a"/>

用户可以分别在这些输入框中填写不同的内容。

在原来的 ASP 程序中,处理这种数据比较方便,多个相同 name 的值会被组合起来处理。

但迁移到 PHP 后,情况就不一样了。

例如提交:

a=one&a=two&a=three

直接使用 PHP 接收时:

$_POST['a']

最终只能获取到其中一个值,前面的值会被后面的值覆盖。

这显然不符合原来的业务需求。

最先想到的办法:使用数组

第一个想到的方法,是让表单字段以数组的方式提交:

<inputtype="text"name="a[]"/>
<inputtype="text"name="a[]"/>
<inputtype="text"name="a[]"/>

这样 PHP 就可以直接接收到:

$_POST['a']
//结果类似:
array(
0 => 'one',
1 => 'two',
2 => 'three'
);

这个方式当然能够解决问题。

但很快又发现,这并不符合最开始的迁移要求。

因为需要修改前台代码,将原来的:

<inputtype="text"name="a"/>

改成:

<inputtype="text"name="a[]"/>

而使用这套表单的网站比较多,如果全部修改,工作量会非常大。

于是又想到,PHP 的配置中是否存在类似 ASP 的处理方式,可以自动接收多个相同 name 的值。

查了一些资料之后,并没有找到合适的办法。

最后只能退一步。

对部分表单改为数组方式

考虑到实际使用情况,最终还是决定对一部分表单进行修改,将需要提交多个值的字段改成数组形式。

不过这样又产生了另外一个问题。

同一个后台程序接收的数据,可能出现两种情况:

一种是普通字符串:

$_POST['a'] = 'hello';

另一种则是数组:

$_POST['a'] = array('one', 'two', 'three');

也就是说,后台在处理数据之前,并不知道传递过来的到底是字符串还是数组。

因此,我写了一个简单的处理函数。

根据数据类型统一处理

function input_treat($input){
if(gettype($input) == "string"){
return htmlentities(trim($input), ENT_QUOTES);
}else if(gettype($input) == "array"){
$nd = "";
foreach($input as $v){
$nd .= htmlentities(trim($v), ENT_QUOTES) . " ";
}
return $nd;
}else{
return false;
}
}

这个函数的处理逻辑比较简单。

如果传入的是字符串:

input_treat($_POST['a']);

就直接进行:

  1. 去除首尾空格
  2. HTML 实体处理
  3. 返回处理后的字符串

如果传入的是数组,例如:

array(
'one',
'two',
'three'
);

则遍历整个数组,将每一个值分别处理后,再用空格连接起来,最终返回:

one two three

这样,无论表单提交过来的是字符串还是数组,后台都可以使用同一个函数进行处理。

最终的处理方式

最终这个问题并没有找到一个完全不修改前台的解决方案。

为了让 PHP 接收到多个相同字段的值,还是需要将部分:

name="a"

修改为:

name="a[]"

然后在后台统一判断传入的数据类型。

虽然这样做仍然需要修改一部分旧表单,但相比全部重构前台代码,对原有系统的影响已经小了很多。

这次迁移过程中也让我感觉到,实际项目里的问题往往不像单独写一个新功能那么简单。

很多时候真正麻烦的地方在于:

新系统要解决问题,同时还要尽可能兼容已经存在的大量旧代码。

如果有更好的处理方法,也欢迎留言交流。

评论0

欢迎分享你的看法,也欢迎补充不同的实践经验。