Reputation: 71
I am trying to encode URI parameters for an ajax call in Wordpress without using JQuery. I think I achieved this, but I really don't know if it is a usefull function or it is just useless because already exists in a native JS function that I don't know.
Are there better solutions?
I also don't like the if (!recur) res = res.slice(0, -1);
at the end, but I didn't found better solutions to delete the very last "&".
Here is what I wrote (also made a Pen https://codepen.io/globdug/pen/mdarxRo )
const action = "action_name";
const nonce = "nonce_value";
const data = [
[1, 2, "abc", 3, false, "ciao"],
"ciao",
123,
5213515,
{
name: "Tanto va la gatta al lardo",
slug: "tanto-va-la-gatta-al-lardo"
},
{
key: "ciao",
test: ["a", "b", "ciao"]
},
{
name: "Tre tigri contro tre tigri",
slug: "tre-tigri-contro-tre-tigri"
}
];
function arrayToEncodedString(
obj, // Array of data to be processed
varName = "data", // Name of variable that will be processed by the PHP function. It will receive an array
encode = true, // Just for testing, if true keys and values will be encoded with encodeURIComponent
prevKey = "", // Blank only during the first call
recur = false // A flag to check if it is the last "&" at the end of the string.
) {
let res = "";
for (const key in obj) {
const value = obj[key];
let currentKey =
prevKey === "" ? varName + "[" + key + "]" : prevKey + "[" + key + "]";
/**
* If current value is an object,
* I will call the function again to iterate it.
*/
if (typeof value === "object") {
/*
* This time I call the function with recur = true
* to avoid deletion of the last "&"
*/
res += arrayToEncodedString(value, varName, encode, currentKey, true);
} else {
/**
* I add this check just for debugging and readability
*/
if (encode) {
res += `${encodeURIComponent(currentKey)}=${encodeURIComponent(value)}&`;
} else {
res += `${currentKey}=${value}&`;
}
}
}
/**
* Remove last "&". Only if "recur" is true
* to avoid deletion of the last "&" of data processed recursively
*/
if (!recur) res = res.slice(0, -1);
return res;
}
function prepareForAjax(data, action, nonce, encode = true, varName) {
return `action=${action}&nonce=${nonce}&${arrayToEncodedString(
data,
varName,
encode,
undefined,
undefined
)}`;
}
/**
* Thanks ChatGPT
*/
function highlightURLParameters(paramString) {
// Regex per individuare chiavi e valori
const regex = /([^&=]+)=([^&]+)/g;
// Sostituisci la stringa con HTML formattato
const formattedString = paramString.replace(
regex,
function (match, key, value) {
return (
'<span class="key">' +
key +
'</span>=<span class="value">' +
value +
"</span>"
);
}
);
return formattedString;
}
document.getElementById("resRaw").innerHTML = highlightURLParameters(
prepareForAjax(data, action, nonce, false)
);
document.getElementById("res").innerHTML = highlightURLParameters(
prepareForAjax(data, action, nonce)
);
.wrapper {
font-family: monospace;
}
pre {
background-color: #232323;
border: 2px solid #000;
padding: 10px;
color: white;
white-space: pre-wrap;
}
.key,
.value {
font-weight: bold;
margin: 0 5px;
}
.key {
color: cyan;
}
.value {
color: orange;
}
<div class="wrapper">
<b>Data to send:</b><br>
<pre id="resRaw"></pre>
<b>String encoded:</b><br>
<pre id="res"></pre>
</div>
Upvotes: 0
Views: 126
Reputation: 178383
Yes there is a built-in function URL.searchParams.
No need to encode.
const url = new URL("https://example.com/page.php");
const parms = {"action":"action_name","nonce":"nonce_value"};
Object.entries(parms).forEach(([key, value]) => url.searchParams.set(key,value))
console.log(url.toString())
In your case with the nested array, I would use JSON.stringify and pass the complete object instead of data[0][1] etc
Send JSON data from Javascript to PHP?
In your case:
Client:
const action = "action_name";
const nonce = "nonce_value";
const data = [
// ... Your data
];
const payload = {
action,
nonce,
data // No need to stringify data here; it will be part of the entire JSON payload
};
fetch('your-php-file.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload) // Stringify the entire payload
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
Server:
// Get the payload from frontend
$rawData = file_get_contents("php://input");
// Decode the JSON payload
$decodedData = json_decode($rawData, true);
$action = $decodedData['action'];
$nonce = $decodedData['nonce'];
$data = $decodedData['data']; // Data is already an array or object, as it was part of the JSON payload
// Here you have $action, $nonce, and $data to be used in the program
PS: To not remove the last thing in something, create an array and join on the thing. For example (but don't, use the above suggestions)
const keyValues = [];
keyValues.push("action=action_name"); // loop here of course
keyValues.push("nonce=nonce_value");
const url = `${serverUrl}?${keyValues.join("&")}`
Upvotes: 0