I'm looking for the name of the PHP function to build a query string from an array of key value pairs. Please note, I am looking for the built in PHP function to do this, not a homebrew one (that's all a google search seems to return). There is one, I just can't remember its name or find it on php.net. IIRC its name isn't that intuitive.
You're looking for http_build_query().
Here's a simple php4-friendly implementation:
/**
* Builds an http query string.
* #param array $query // of key value pairs to be used in the query
* #return string // http query string.
**/
function build_http_query( $query ){
$query_array = array();
foreach( $query as $key => $key_value ){
$query_array[] = urlencode( $key ) . '=' . urlencode( $key_value );
}
return implode( '&', $query_array );
}
Just as addition to #thatjuan's answer.
More compatible PHP4 version of this:
if (!function_exists('http_build_query')) {
if (!defined('PHP_QUERY_RFC1738')) {
define('PHP_QUERY_RFC1738', 1);
}
if (!defined('PHP_QUERY_RFC3986')) {
define('PHP_QUERY_RFC3986', 2);
}
function http_build_query($query_data, $numeric_prefix = '', $arg_separator = '&', $enc_type = PHP_QUERY_RFC1738)
{
$data = array();
foreach ($query_data as $key => $value) {
if (is_numeric($key)) {
$key = $numeric_prefix . $key;
}
if (is_scalar($value)) {
$k = $enc_type == PHP_QUERY_RFC3986 ? urlencode($key) : rawurlencode($key);
$v = $enc_type == PHP_QUERY_RFC3986 ? urlencode($value) : rawurlencode($value);
$data[] = "$k=$v";
} else {
foreach ($value as $sub_k => $val) {
$k = "$key[$sub_k]";
$k = $enc_type == PHP_QUERY_RFC3986 ? urlencode($k) : rawurlencode($k);
$v = $enc_type == PHP_QUERY_RFC3986 ? urlencode($val) : rawurlencode($val);
$data[] = "$k=$v";
}
}
}
return implode($arg_separator, $data);
}
}
Implode will combine an array into a string for you, but to make an SQL query out a kay/value pair you'll have to write your own function.
Related
This question already has answers here:
PHP - Convert multidimensional array to 2D array with dot notation keys
(5 answers)
Closed 8 months ago.
I'm trying to grab all the keys of a multidimensional array and format them a certain way. Here's a partial array:
$ini_config['aaa']['email']['main'] = 'me#name.com';
$ini_config['bbb']['email']['ccc'] = 'you#name.com';
$ini_config['bbb']['phone']['local'] = '800-555-1212';
$ini_config['bbb']['phone']['skype'] = '744-222-1234';
$ini_config['ccc']['phone']['main'] = 'domain.com';
$ini_config['ccc']['domain']['https'] = 'https://www. domain.com';
$ini_config['ccc']['fax'] = '744-222-1237';
and here's the format I need them in:
aaa_email_main
bbb_email_ccc
bbb_phone_local
bbb_phone_skype
ccc_phone_main
ccc_domain_https
ccc_fax
This script is the closest I've been able to come to what I need:
<?php
rloop($ini_config);
function rloop($array) {
global $full_key;
foreach($array as $key => $value) {
if(is_array($value) ) {
$full_key .= $key .'_';
$array[$key] = rloop($array[$key]);
}
else {
$array[$key] = (string) $value;
$filename = $full_key . $key;
echo 'filename: '. $filename . PHP_EOL;
$full_key = '';
}
}
}
N.B. The number of levels can be from 1 to 4, and all keys are strings.
Thanks
$ini_config['aaa']['email']['main'] = 'me#name.com';
$ini_config['bbb']['email']['ccc'] = 'you#name.com';
$ini_config['bbb']['phone']['local'] = '800-555-1212';
$ini_config['bbb']['phone']['skype'] = '744-222-1234';
$ini_config['ccc']['phone']['main'] = 'domain.com';
$ini_config['ccc']['domain']['https'] = 'https://www. domain.com';
$ini_config['ccc']['fax'] = '744-222-1237';
function keyPaths(array $array, array $carry = [], string $separator = ''): array {
foreach ($array as $key => $value) {
if (is_array($value)) {
$carry = keyPaths($value, $carry, $separator . $key . '_');
} else {
$carry[] = $separator . $key;
}
}
return $carry;
}
$result = keyPaths($ini_config);
Thanks to #lucas.j here's what I'm using now:
function get_all_keys($array, $collector='') {
$separator = '_';
foreach ($array as $key => $value) {
if (is_array($value)) {
get_all_keys($value, $collector.$key.$separator);
}
else {
$filename = $collector.$key;
$content = $value;
// echo 'filename: '. $filename . PHP_EOL; //:debug
// echo 'content: ' . $content . PHP_EOL; //:debug
file_put_contents($filename, $content);
}
}
}
After adding strategically placed echo statements, I was able to see what the $separator variable was doing. So I renamed it to $collector, since it's collecting the keys to form the "all-keys" string. I also renamed the function to be a little more descriptive, and added the hard-coded underscore to a new variable called $separator.
And since I don't need a new variable created, I dropped $carry and am performing what I need done directly in the else section.
Thanks, Lucas!
I'm trying to make a payment plugin for my webshop for Ogone ideal payments. I can make a payment, but when I return I cannot get the SHA-signs to match.
I have the following get request on return:
orderID=476&amount=90%2E82&PM=iDEAL&ACCEPTANCE=0000000000&STATUS=9&PAYID=43934127&NCERROR=0&BRAND=iDEAL&SHASIGN=5AB0A065BAA83C5D807249A66E661ACBB6709B8F
According to the documentation, I have to order the keys alphabetically and only hash those that are allowed.
These are the allowed keys:
['AAVADDRESS', 'AAVCHECK', 'AAVZIP', 'ACCEPTANCE', 'ALIAS', 'AMOUNT', 'BRAND', 'CARDNO', 'CCCTY', 'CN', 'COMPLUS', 'CURRENCY', 'CVCCHECK', 'DCC_COMMPERCENTAGE', 'DCC_CONVAMOUNT', 'DCC_CONVCCY', 'DCC_EXCHRATE', 'DCC_EXCHRATESOURCE', 'DCC_EXCHRATETS', 'DCC_INDICATOR', 'DCC_MARGINPERCENTAGE', 'DCC_VALIDHOUS', 'DIGESTCARDNO', 'ECI', 'ED', 'ENCCARDNO', 'IP', 'IPCTY', 'NBREMAILUSAGE', 'NBRIPUSAGE', 'NBRIPUSAGE_ALLTX', 'NBRUSAGE', 'NCERROR', 'ORDERID', 'PAYID', 'PM', 'SCO_CATEGORY', 'SCORING', 'STATUS', 'TRXDATE', 'VC'];
I made this method to make the hash:
/**
* #return string
*/
protected function getShaOutSign()
{
$hash = '';
$values = \Input::all();
$values = array_change_key_case($values, CASE_UPPER);
ksort($values);
foreach ($values as $key => $value) {
if (in_array($key, $this->shaOut)) {
if(!empty($value))
{
$hash .= $key . '=' . $values[$key] . $this->settings->shaout;
}
}
}
return strtoupper(sha1($hash));
}
I'm 100% sure the SHA out key is correct.
The string it makes before I do SHA1:
ACCEPTANCE=0000000000abcDEFghj1234560987654AMOUNT=90.82abcDEFghj1234560987654BRAND=iDEALabcDEFghj1234560987654ORDERID=476abcDEFghj1234560987654PAYID=43934127abcDEFghj1234560987654PM=iDEALabcDEFghj1234560987654STATUS=9abcDEFghj1234560987654
And the final hash I get is:
68E459CB933E04B582A5D564CE6F591D5819B7F1
No matter what I try, I just can't get it to match it with the one in the $_GET request.
My sha-out key: abcDEFghj1234560987654
What can I try next?
The problem is clearly that part:
if(!empty($value))
{
$hash .= $key . '=' . $values[$key] . $this->settings->shaout;
}
Your request contains '...&NCERROR=0...'.
So the value is 0. And 0 is empty.
I had the same problem. But I used array_filter() function:
$parameters = array_filter($parameters);
Also array_filter() removed my 'empty' ncerror field.
The sha out calculation is wrong. This is the code I use in my projects to calculate it, $sha_parms is the full response of Ogone. So $_POST or $_GET
/**
* Function to calculate the sha that is received from Ogone
*/
public function getShaOut($sha_parms, $sha_out = null) {
$sha_out = $sha_out ?: self::PASS_PHRASE_OUT;
$sha_parms = $this->ogoneSort($sha_parms);
$sha_string = '';
foreach ($sha_parms as $key => $value) {
if ($key != 'SHASIGN' && $value != '') {
$sha_string .= $key . '=' . $value . $sha_out;
}
}
//return($sha_string);
return strtoupper(sha1($sha_string));
}
/**
*
*
**/
private function ogoneSort($array) {
$arrayToSort = array();
$origArray = array();
foreach ($array as $key => $value) {
$arrayToSort[strtolower($key)] = $value;
//stores the original value in an array
$origArray[strtolower($key)] = $key;
}
ksort($arrayToSort);
$sortedArray = array();
foreach($arrayToSort as $key => $value) {
//switch the lowercase keys back to their originals
$key = strtoupper($origArray[$key]);
$sortedArray[$key] = $value;
}
return $sortedArray;
}
$array['a:b']['c:d'] = 'test';
$array['a:b']['e:f']= 'abc';
I need output like below. array can have multiple level . Its comes with api so we do not know where colon come.
$array['ab']['cd'] = 'test';
$array['ab']['ef']= 'abc';
(untested code) but the idea should be correct if want to remove ':' from keys:
function clean_keys(&$array)
{
// it's bad to modify the array being iterated on, so we do this in 2 steps:
// find the affected keys first
// then move then in a second loop
$to_move = array();
forach($array as $key => $value) {
if (strpos($key, ':') >= 0) {
$target_key = str_replace(':','', $key);
if (array_key_exists($target_key, $array)) {
throw new Exception('Key conflict detected: ' . $key . ' -> ' . $target_key);
}
array_push($to_move, array(
"old_key" => $key,
"new_key" => $target_key
));
}
// recursive descent
if (is_array($value)) {
clean_keys($array[$key]);
}
}
foreach($to_move as $map) {
$array[$map["new_key"]] = $array[$map["old_key"]];
unset($array[$map["old_key"]]);
}
}
try this:
$array=array();
$array[str_replace(':','','a:b')][str_replace(':','','c:d')]="test";
print_r($array);
This seems like the simplest and most performant approach:
foreach ($array as $key => $val) {
$newArray[str_replace($search, $replace, $key)] = $val;
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Dynamic array keys
I have an array $Values
which is set up like this
$Values
1
2
3
a
b
c
4
which is nested.
and I have a key like this: $key = "a"]["b"]["c";
Can I now do: Values[$key], ti get the value in c ?
#Edit
Simply said: I want to get the value from array $Values["a"]["b"]["c"] By doing $Values[$key]. What should my key be then?
No, but you can extract the result:
$Values = array( '1' => 'ONE',
'2' => 'TWO',
'3' => 'THREE',
'a' => array( 'b' => array( 'c' => 'alphabet') ),
'4' => 'FOUR'
);
$key = '"a"]["b"]["c"';
$nestedKey = explode('][',$key);
$searchArray = $Values;
foreach($nestedKey as $nestedKeyValue) {
$searchArray = $searchArray[trim($nestedKeyValue,'"')];
}
var_dump($searchArray);
Will only work if $key is valid.
Now how do you get in a situation with a key like this anyway? Perhaps if you explained the real problem, we could give you a real answer rather than a hack.
No, you only can get individual keys from variables. Depending on what you really want to do you could use references to your array elements.
Nah you can't. This is invalid syntax.
Hover you can do:
$key = 'a,b,c';
// or:
$key = serialize( array( 'a','b', 'c'));
// or many other things
And than implement your array-like class which will implement ArrayAccess or ArrayObject (let's way you'll stick with $key = 'a,b,c';):
class MyArray extends ArrayAccess {
protected $data = array();
protected &_qetViaKey( $key, &$exists, $createOnNonExisting = false){
// Parse keys
$keys = array();
if( strpos( $key, ',') === false){
$keys[] = $key;
} else {
$keys = explode( ',', $key);
}
// Prepare variables
static $null = null;
$null = null;
$exists = true;
// Browse them
$progress = &$this->data;
foreach( $keys as $key){
if( is_array( $progress)){
if( isset( $progress[ $key])){
$progress = $progress[ $key];
} else {
if( $createOnNonExisting){
$progress[ $key] = array();
$progress = $progress[ $key];
} else {
$exists = false;
break;
}
}
} else {
throw new Exception( '$item[a,b] was already set to scalar');
}
}
if( $exists){
return $progress;
}
return $null;
}
public offsetExists( $key){
$exists = false;
$this->_getViaKey( $key, $exists, false);
return $exists;
}
// See that we aren't using reference anymore in return
public offsetGet( $key){
$exists = false;
$value = $this->_getViaKey( $key, $exists, false);
if( !$exists){
trigger_error( ... NOTICE ...);
}
return $value;
}
public offsetSet ( $key, $val){
$exists = false;
$value = $this->_getViaKey( $key, $exists, true);
$value = $val;
}
}
// And use it as:
$array = MyArray();
$array['a']['b']['c'] = 3;
$array['a,b,c'] = 3;
Or implement function:
public function &getArrayAtKey( $array, $key){
// Similar to _qetViaKey
// Implement your own non existing key handling
}
Is there a way to turn off the PHP functionality for Submitting a multidimensional array via POST with php?
So that submission of <input type="text" name="variable[0][1]" value="..." /> produces a $_POST like so...
array (
["variable[0][1]"] => "...",
)
NOT like so:
array (
["variable"] => array(
[0] => array (
[1] => "..."
),
),
)
I'm thinking/hoping an obscure PHP.ini directive or something... ?
No, but nothing stops you from fetching the query string (through $_SERVER['QUERY_STRING']) and parsing it manually. For instance:
$myGET = array();
foreach (explode("&", $_SERVER['QUERY_STRING']) as $v) {
if (preg_match('/^([^=])+(?:=(.*))?$/', $v, $matches)) {
$myGET[urldecode($matches[1])] = urldecode($matches[2]);
}
}
I should think not. What exactly are you trying to do?
You could use variable(0)(1) or variable_0_1 as names for example.
Don't believe you can do that. I also don't understand why you'd need to. But this should work:
$_POST['variable'] = array(array('abc','def'),array('ddd','ggg'));
print_r(flatPost('variable'));
function flatPost($var)
{
return enforceString($_POST[$var], $var);
}
function enforceString($data, $preKey = '')
{
if(!is_array($data))
{
return array($preKey . $data);
}
$newData = array();
foreach($data as $key => &$value)
{
$element = enforceString($value, $preKey . '[' . $key . ']');
$newData = array_merge($newData, $element);
}
return $newData;
}
It's a little over the top, but if necessary you could manually parse the request body.
<?php
if(!empty($_POST) && $_SERVER['CONTENT_TYPE'] == 'application/x-www-form-urlencoded') {
$_post = array();
$queryString = file_get_contents('php://input'); // read the request body
$queryString = explode('&', $queryString); // since the request body is a query string, split it on '&'
// and you have key-value pairs, delimited by '='
foreach($queryString as $param) {
$params = explode('=', $param);
if(array_key_exists(0, $params)) {
$params[0] = urldecode($params[0]);
}
if(array_key_exists(1, $params)) {
$params[1] = urldecode($params[1]);
}
else {
$params[1] = urldecode('');
}
$_post[$params[0]] = $params[1];
}
$_POST = $_post;
}
?>