PHP中数字索引数组的最短可能查询字符串
我在寻找最简洁的URL,而不是最短的PHP代码。我不想让我的用户被PHP在编码数组时创建的可怕URL吓坏 如果您只是通过以下方式填充数组(PHP中数字索引数组的最短可能查询字符串,php,arrays,query-string,Php,Arrays,Query String,我在寻找最简洁的URL,而不是最短的PHP代码。我不想让我的用户被PHP在编码数组时创建的可怕URL吓坏 如果您只是通过以下方式填充数组($fn),PHP将在查询字符串中执行大量重复操作: 生成的$url为 http://example.com/?c=asdf&fs[0]=5&fs[1]=12&fs[3]=99 如何将其降至最低(使用PHP或PHP中易于实现的方法)?有多种可能的方法: serialize+base64-可以吞并任何对象,但数据开销非常可怕 内爆+base64-仅限于数组,强制
$fn
),PHP将在查询字符串中执行大量重复操作:
生成的$url
为
http://example.com/?c=asdf&fs[0]=5&fs[1]=12&fs[3]=99
如何将其降至最低(使用PHP或PHP中易于实现的方法)?有多种可能的方法:
YTOZONTPOJA7CzoxNJOIc29TZSB1BNHZMUGZGF0YSI7ATOxO6MTIiYMJ09AHR0CDOVLYI7ATOYOYO6NTOINtYU6ZU1Io30=
一些不安全的数据&&==http://65535
C29TZSB1BNHZMUGZG0YXWMJIY9PWH0DHA6LY98NJU1MZU=
虽然serialize+base64结果非常长,但内爆+serialize为GET提供了安全的可管理长度输出…除了结尾处的
=
。有多种可能的方法:
YTOZONTPOJA7CzoxNJOIc29TZSB1BNHZMUGZGF0YSI7ATOxO6MTIiYMJ09AHR0CDOVLYI7ATOYOYO6NTOINtYU6ZU1Io30=
一些不安全的数据&&==http://65535
C29TZSB1BNHZMUGZG0YXWMJIY9PWH0DHA6LY98NJU1MZU=
虽然serialize+base64结果非常长,但内爆+serialize为GET提供了安全的可管理长度的输出…除了结尾处的=
。默认PHP方式
http\u build\u query
所做的是将数组序列化为URL的常用方法。PHP在$\u GET
中自动反序列化它
当只想序列化一个(非关联)整数数组时,可以使用其他选项
小阵列
对于小数组,转换为下划线分隔列表非常方便和高效。这是通过$fs=内爆('''',$fs)
完成的。那么您的URL将如下所示:
http://example.com/?c=asdf&fs=5_12_99
缺点是,您必须显式地分解('''u',$'u GET['fs'])
才能将值作为数组返回
也可以使用其他分隔符。下划线被认为是字母数字,因此很少有特殊意义。在URL中,它通常用作空间替换(例如,MediaWiki)。在带下划线的文本中使用时很难区分。连字符是另一种常用的空格替换。它也常被用作减号。逗号是一个典型的列表分隔符,但与中的下划线和连字符不同,逗号是由http\u build\u query
进行百分比编码的,几乎在任何地方都有特殊意义。竖杆(“管道”)也存在类似情况
大型阵列
当URL中有大数组时,您应该首先停止编码,开始思考。这几乎总是表明设计不好。POST HTTP方法不是更合适吗?难道您没有任何更可读、更节省空间的方法来标识已寻址的资源吗
理想情况下,URL应该易于理解和(至少部分)记住。在里面放一个大斑点真是个坏主意
现在我警告你了。如果您仍然需要在URL中嵌入一个大数组,请继续。尽可能多地压缩数据,-对它们进行编码以将二进制blob转换为文本,并对文本进行清理以嵌入URL
修改的base64
嗯。或者最好使用一个。我的选择之一是使用
而不是-
+
而不是\u
和/
- 省略填充
=
urlencode
函数
压缩
应该在gzip()和bzip2()之间进行选择。不想花费时间进行比较,对于块大小的任何设置,gzip在几个相对较小的输入(大约100个字符)上看起来更好
包装
但是什么数据应该输入到压缩算法中呢
在C语言中,可以将整数数组转换为字符数组(字节),并将其交给压缩函数。这是最明显的做事方式。在PHP中,最明显的方法是将所有整数转换为字符串形式的十进制表示,然后使用分隔符进行连接,并且仅在压缩之后。真是浪费空间
所以,让我们使用C方法!我们将消除分隔符和其他浪费的空间,并使用以下代码将每个整数编码为2个字节:
警告:pack
和unpack
行为在这种情况下取决于机器。字节顺序可能在机器之间更改。但我认为在实践中这不会是一个问题,因为应用程序不会同时在两个具有不同端性的系统上运行。但是,在集成多个系统时,可能会出现问题。此外,如果切换到具有不同endianity的系统,则使用原始endianity的链接将断开
共同编码
现在,打包、压缩和修改base64,一应俱全:
function url_embed_array($arr) {
return url_base64_encode(gzcompress(pack_nums($arr)));
}
function url_parse_array($data) {
return unpack_nums(gzuncompress(url_base64_decode($data)));
}
看。这比OP的答案要好,在他的40元素数组中,我的解产生91个字符,而他的解产生98个字符。当使用范围(1,1000)
(生成数组(1,2,3,…,1000)
)作为基准时。这大约好25%
为了完整性,OP的解决方案是
function url_embed_array($arr) {
return urlencode(base64_encode(gzcompress(implode(',', $arr))));
}
默认PHP方式
http\u build\u query
所做的是
define('URL_BASE64_FROM', '+/');
define('URL_BASE64_TO', '-_');
function url_base64_encode($data) {
$encoded = base64_encode($data);
if ($encoded === false) {
return false;
}
return str_replace('=', '', strtr($encoded, URL_BASE64_FROM, URL_BASE64_TO));
}
function url_base64_decode($data) {
$len = strlen($data);
if (is_null($len)) {
return false;
}
$padded = str_pad($data, 4 - $len % 4, '=', STR_PAD_RIGHT);
return base64_decode(strtr($padded, URL_BASE64_TO, URL_BASE64_FROM));
}
define('PACK_NUMS_FORMAT', 'n*');
function pack_nums($num_arr) {
array_unshift($num_arr, PACK_NUMS_FORMAT);
return call_user_func_array('pack', $num_arr);
}
function unpack_nums($packed_arr) {
return unpack(PACK_NUMS_FORMAT, $packed_arr);
}
function url_embed_array($arr) {
return url_base64_encode(gzcompress(pack_nums($arr)));
}
function url_parse_array($data) {
return unpack_nums(gzuncompress(url_base64_decode($data)));
}
function url_embed_array($arr) {
return urlencode(base64_encode(gzcompress(implode(',', $arr))));
}
$fs = array(5, 12, 99);
$fs_no_array = implode(',', $fs);
$url = "http://$_SERVER[HTTP_HOST]/?" .
http_build_query(array('c' => 'asdf', 's' => 'jkl')) . '&fs=' . $fs_no_array;
$fs = array_map('intval', explode(',', $_GET['fs']));
$fs_compressed = urlencode(base64_encode(gzcompress($fs_no_array)));
$fs_decompressed = gzuncompress(base64_decode($_GET['fs']));
$fs = array_map('intval', explode(',', $fs_decompressed));
$fs = array(7,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,52,53,54,61);
$fs = array(7,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,52,53,54,61);