当前位置: 首页 > 后端技术 > PHP

递归匿名函数手动实现http_build_query系统函数

时间:2023-03-30 00:27:51 PHP

最近感觉http_build_query函数的功能还是挺神奇的。可以将任何复杂数组转换为复杂的URL查询字符串。所以我尝试手动实现它(user_http_build_query)。版本1,主函数递归附加辅助函数实现/***http_build_query实现。**@paramarray$queryPayload*@paramstring$numericPrefix*@paramstring$argSeparator*@paramint$encType**@returnstring*/functionuser_http_build_query(array$queryPayload,string$numericPrefix='',string$argSeparator='&',int$encType=PHP_QUERY_RFC1738):string{reset($queryPayload);$queryStr='';foreach($queryPayloadas$k=>$v){//特殊值处理if($v===null){continue;}如果($v===0||$v===false){$v='0';}//在解码数据时获取有效的变量名if(is_numeric($k)&&!is_string($k)){$k=$numericPrefix.$k;$queryStr.=is_scalar($v)?sprintf("%s=%s$argSeparator",$encType===PHP_QUERY_RFC3986?rawurlencode($k):urlencode($k),$encType===PHP_QUERY_RFC3986?rawurlencode($v):urlencode($v)):to_query_str($k,$v,$argSeparator,$encType);}返回替代r($queryStr,0,-strlen($argSeparator));}/***当转换值为非标量时**@paramstring$key*@paramarray|object$value*@paramstring$argSeparator*@paramint$encType**@returnstring*/functionto_query_str(string$key,$value,string$argSeparator,int$encType):string{$queryStr='';}foreach($valueas$k=>$v){//特殊值处理if($v===null){continue;}如果($v===0||$v===false){$v='0';}$fullKey="{$key}[{$k}]";$queryStr.=is_scalar($v)?sprintf("%s=%s$argSeparator",$encType===PHP_QUERY_RFC3986?rawurlencode($fullKey):urlencode($fullKey),$encType===PHP_QUERY_RFC3986?rawurlencode($v):urlencode($v)):to_query_str($fullKey,$v,$argSeparator,$encType);//递归调用}return$queryStr;}版本二、单函数递归匿名函数实现用两个函数来实现一个函数的功能显然不能令人满意。稍微改动一下,把辅助函数抽出来做成匿名函数放在主函数里面,递归匿名函数就可以了。/***http_build_query的实现。**@paramarray$queryPayload*@paramstring$numericPrefix*@paramstring$argSeparator*@paramint$encType**@returnstring*/functionuser_http_build_query(array$queryPayload,string$numericPrefix='',string$argSeparator='&',int$encType=PHP_QUERY_RFC1738):string{/***转换值是非标量的情况**@paramstring$key*@paramarray|object$value*@paramstring$argSeparator*@paramint$encType**@returnstring*/$toQueryStr=静态函数(string$key,$value,string$argSeparator,int$encType)use(&$toQueryStr):string{$queryStr='';foreach($valueas$k=>$v){//特殊值处理if($v===null){continue;}如果($v===0||$v===false){$v='0';}$fullKey="{$key}[{$k}]";$queryStr.=is_scalar($v)?sprintf("%s=%s$argSeparator",$encType===PHP_QUERY_RFC3986?rawurlencode($fullKey):urlencode($fullKey),$encType===PHP_QUERY_RFC3986?rawurlencode($v):urlencode($v)):$toQueryStr($fullKey,$v,$argSeparator,$encType);//递归调用}return$queryStr;};reset($queryPayload);$queryStr='';foreach($queryPayloadas$k=>$v){//特殊值处理if($v===null){continue;}if($v===0||$v===false){$v='0';}//对于解码数据时获取合法的变量名s$argSeparator",$encType===PHP_QUERY_RFC3986?rawurlencode($k):urlencode($k),$encType===PHP_QUERY_RFC3986?rawurlencode($v):urlencode($v)):$toQueryStr($k,$v,$argSeparator,$encType);}返回substr($queryStr,0,-strlen($argSeparator));}测试$queryPayload=[1=>'a','10'=>'b','01'=>'c','keyO1'=>null,'keyO2'=>false,'keyO3'=>true,'keyO4'=>0,'keyO5'=>1,'keyO6'=>0.0,'keyO7'=>0.1,'keyO8'=>[],'keyO9'=>'','key10'=>new\stdClass(),'pastimes'=>['golf','opera','poker','rap'],'user'=>['name'=>'BobSmith','age'=>47,'sex'=>'M','dob'=>'5/12/1956'],'children'=>['sally'=>['age'=>8,'sex'=>null],'bobby'=>['sex'=>'M','age'=>12],],];dd($queryStr1=http_build_query($queryPayload),$queryStr2=user_http_build_query($queryPayload),$queryStr3=urldecode($queryStr1),$queryStr4=urldecode($queryStr2),$queryStr1===$queryStr2,$queryStr3===$queryStr4,);//"1=a&10=b&01=c&keyO2=0&keyO3=1&keyO4=0&keyO5=1&keyO6=0&keyO7=0.1&keyO9=&消遣%5B0%5D=高尔夫&消遣%5B1%5D=歌剧&消遣%5B2%5D=扑克&消遣%5B3%5D=说唱&用户%5Bname%5D=Bob+Smith&user%5Bage%5D=47&user%5Bsex%5D=M&user%5Bdob%5D=5%2F12%2F1956&children%5Bsally%5D%5Bage%5D=8&children%5Bbobby%5D%5Bsex%5D=M&children%5Bbobby%5D%5Bage%5D=12"//"1=a&10=b&01=c&keyO2=0&keyO3=1&keyO4=0&keyO5=1&keyO6=0&keyO7=0.1&keyO9=&消遣%5B0%5D=高尔夫&消遣%5B1%5D=歌剧&消遣%5B2%5D=扑克&消遣%5B3%5D=rap&user%5Bname%5D=Bob+Smith&user%5Bage%5D=47&user%5Bsex%5D=M&user%5Bdob%5D=5%2F12%2F1956&children%5Bsally%5D%5Bage%5D=8&children%5Bbobby%5D%5Bsex%5D=M&children%5Bbobby%5D%5Bage%5D=12"//"1=a&10=b&01=c&keyO2=0&keyO3=1&keyO4=0&keyO5=1&keyO6=0&keyO7=0.1&keyO9=&pastimes[0]=高尔夫&消遣[1]=歌剧&消遣[2]=扑克&消遣[3]=说唱&user[name]=BobSmith&user[age]=47&user[sex]=M&user[dob]=5/12/1956&children[sally][age]=8&children[bobby][sex]=M&children[bobby][age]=12"//"1=a&10=b&01=c&keyO2=0&keyO3=1&keyO4=0&keyO5=1&keyO6=0&keyO7=0.1&keyO9=&pastimes[0]=高尔夫&消遣[1]=歌剧&消遣[2]=扑克&消遣[3]=说唱&用户[姓名]=鲍勃史密斯&用户[年龄]=47&用户[性别]=M&用户[出生日期]=5/12/1956&儿童[莎莉][年龄]=8&儿童[bobby][sex]=M&children[bobby][age]=12"//true//true原文链接https://github.com/guanguans/guanguans.github.io/issues/47