How to extract specific variables from a string? - php

let's say i have the following:
$vars="name=david&age=26&sport=soccer&birth=1984";
I want to turn this into real php variables but not everything. By example, the functions that i need :
$thename=getvar($vars,"name");
$theage=getvar($vars,"age");
$newvars=cleanup($vars,"name,age"); // Output $vars="name=david&age=26"
How can i get only the variables that i need . And how i clean up the $vars from the other variables if possible?
Thanks

I would use parse_str() and then manipulate the array.
$vars="name=david&age=26&sport=soccer&birth=1984";
parse_str($vars, $varray);
$thename = $varray["name"];
$theage = $varray["age"];
$newvars = array_intersect_key($varray,
array_flip(explode(",","name,age")));

You can do something like:
function getvar($arr,$key) {
// explode on &.
$temp1 = explode('&',$arr);
// iterate over each piece.
foreach($temp1 as $k => $v) {
// expolde again on =.
$temp2 = explode('=',$v);
// if you find key on LHS of = return wats on RHS.
if($temp2[0] == $key)
return $temp2[1];
}
// key not found..return empty string.
return '';
}
and
function cleanup($arr,$keys) {
// split the keys string on comma.
$key_arr = explode(',',$keys);
// initilize the new array.
$newarray = array();
// for each key..call getvar function.
foreach($key_arr as $key) {
$newarray[] = $key.'='.getvar($arr,$key);
}
// join with & and return.
return implode('&',$newarray);
}
Here is a working example.

Related

ExpressionEngine: Pass parameter into variable tag pair and fetch in the function

I need to pass parameter into inner tag, ex.
{exp:myplugin:func}
{last_year subject="xxx"}
{/last_year}
{/exp:myplugin:func}
How can I fetch that parameter in the function?
Here's a function I've written to return the parameters for a variable pair inside a template tag pair:
private function get_variable_parameters($tagData, $varName) {
$parameters = array();
if (strpos($tagData, LD."/".$varName.RD) !== FALSE) {
//### Closing variable tag exists ###
if (preg_match_all("/".LD.$varName."(.*?)".RD."(.*?)".LD."\/".$varName.RD."/s", $tagData, $matches)) {
for ($num = 0; $num < count($matches[0]); $num++){
$allParams = explode(" ", trim($matches[1][$num]));
foreach($allParams as $value) {
$value = str_replace(array('"', "'"), '', $value);
$param = explode("=", $value);
if (!empty($param[1]))
$parameters[$param[0]] = $param[1];
}
}
}
}
return $parameters;
}//### End of get_variable_parameters function ###
So from your example code in your func method:
$tagData = ee()->TMPL->tagdata;
$varParameters = $this->get_variable_parameters($tagData, "last_year");
echo $varParameters["subject"];
Looking back over my code though, I don't think it handles multiple use of the same variable pair inside the same loop, so if required may need to change this line:
$parameters[$param[0]] = $param[1];
to:
$parameters[$num][$param[0]] = $param[1];
And then work out what instance of the variable pairs inside the same loop. Untested though, probably needs more work!

How can I get in PHP the value out of an object attribute with the path stored in a variable?

For example, I have the following:
$ValuePath = "object->data->user_nicename";
And I need to print not the value of the $ValuePath but the value of the $variable->data->user_nicename that is part of a larger call .. as I have the following situation:
echo $objects->$ValuePath->details;
and is not working .. I'm getting the error Class cannot be converted to string or something when I try it like that.
PHP pseudo-code:
function get_by_path($object, $path)
{
$o = $object;
$parts = explode('->', $path);
// if you want to remove the first dummy object-> reference
array_shift($parts);
$l = count($parts);
while ($l)
{
$p = array_shift($parts); $l--;
if ( isset($o->{$p}) ) $o = $o->{$p};
else {$o = null; break;}
}
return $o;
}
Use like this:
$value = get_by_path($obj, "object->data->user_nicename");
// $value = $obj->data->user_nicename;
Check also PHP ArrayAccess Interface which enables to access objects as arrays dynamicaly
NO you cannot do that.
From your declaration $ValuePath is a variable which holds a plain string ('object->data->user_nicename') this string is not an object.
Where as,
$objects->object->data->user_nicename->details is a object.
so $objects->object->data->user_nicename->details is not same as $objects->$ValuePath->details

Using serialized data from AJAX object with PHP

I'm sending an entire form, about 8 fields, along with my AJAX data object, one of which is a serialized string:
var fields = $(this).serialize();
var data = {
action:'newSubmission',
nonce: Nonce,
fields: fields
};
Now within PHP I cannot understand how to get each field value from the $_POST object correctly.
$test = $_POST['field'];
Is the full string and sends back to JS a properly formatted JSON object. But how do I break up the serialized string correctly in PHP?
The string will be encoded, so you will have to do that with url_decode.
Here is a function that I used to build a workable object out of the string.
function urldecode_to_obj($str) {
$str = trim($str, '"');
// explode string before decoding
foreach (explode('&', $str) as $chunk) {
$param = explode("=", $chunk);
if ($param) {
// search string for array elements and look for key-name if exists
preg_match('#\[(.+?)\]$#', urldecode($param[0]), $with_key);
preg_match('#\[\]$#', urldecode($param[0]), $no_key);
$mkey = preg_split('/\[/', urldecode($param[0]));
// converts to array elements with numeric key
if ($no_key) {
$data[$mkey[0]][] = urldecode($param[1]);
}
// converts to array elements with named key
if ($with_key) {
$data[$mkey[0]][$with_key[1]] = urldecode($param[1]);
}
if (!$no_key && !$with_key) {
$data[urldecode($param[0])] = urldecode($param[1]);
}
}
}
return (object)$data;
}
$str = "serialized_string";
$obj = urldecode_to_obj($str);
Your variables with values are now in the object. If you have a var1 variable in there with a value1:
$obj -> var1 = "value1";
You can also get thins back as an array. Just omit the (object) casting and return the data in t\he function as:
return $data;
If you want to return things to your JS then you should echo them out as an array and use json_encode:
$array = array("success" => true);
echo json_encode($array);
Try using:
$serializedData = file_get_contents("php://input");
$unserializedData = array();
parse_str($unserializedData,$serializedData);
print_r($unserializedData);
instead of the PHP $_POST superglobal use the php://input.
PHP "php://input" vs $_POST
Then you can use theparse_str() php function to turn the serialized string into a php array.
There are also a number of other ways to manually do this if you so choose:
function unserializeForm($str) {
$returndata = array();
$strArray = explode("&", $str);
$i = 0;
foreach ($strArray as $item) {
$array = explode("=", $item);
$returndata[$array[0]] = $array[1];
}
return $returndata;
}

Convert delimited string into array key path and assign value

I have a string like this:
$string = 'one/two/three/four';
which I turn it into a array:
$keys = explode('/', $string);
This array can have any number of elements, like 1, 2, 5 etc.
How can I assign a certain value to a multidimensional array, but use the $keys I created above to identify the position where to insert?
Like:
$arr['one']['two']['three']['four'] = 'value';
Sorry if the question is confusing, but I don't know how to explain it better
This is kind of non-trivial because you want to nest, but it should go something like:
function insert_using_keys($arr, $keys, $value){
// we're modifying a copy of $arr, but here
// we obtain a reference to it. we move the
// reference in order to set the values.
$a = &$arr;
while( count($keys) > 0 ){
// get next first key
$k = array_shift($keys);
// if $a isn't an array already, make it one
if(!is_array($a)){
$a = array();
}
// move the reference deeper
$a = &$a[$k];
}
$a = $value;
// return a copy of $arr with the value set
return $arr;
}
$string = 'one/two/three/four';
$keys = explode('/', $string);
$arr = array(); // some big array with lots of dimensions
$ref = &$arr;
while ($key = array_shift($keys)) {
$ref = &$ref[$key];
}
$ref = 'value';
What this is doing:
Using a variable, $ref, to keep track of a reference to the current dimension of $arr.
Looping through $keys one at a time, referencing the $key element of the current reference.
Setting the value to the final reference.
You'll need to first make sure the key's exist, then assign the value. Something like this should work (untested):
function addValueByNestedKey(&$array, $keys, $value) {
$branch = &$array;
$key = array_shift($keys);
// add keys, maintaining reference to latest branch:
while(count($keys)) {
$key = array_pop($keys);
if(!array_key_exists($key, $branch) {
$branch[$key] = array();
}
$branch = &$branch[$key];
}
$branch[$key] = $value;
}
// usage:
$arr = array();
$keys = explode('/', 'one/two/three/four');
addValueByNestedKey($arr, $keys, 'value');
it's corny but:
function setValueByArrayKeys($array_keys, &$multi, $value) {
$m = &$multi
foreach ($array_keys as $k){
$m = &$m[$k];
}
$m = $value;
}
$arr['one']['two']['three']['four'] = 'value';
$string = 'one/two/three/four';
$ExpCheck = explode("/", $string);
$CheckVal = $arr;
foreach($ExpCheck AS $eVal){
$CheckVal = $CheckVal[$eVal]??false;
if (!$CheckVal)
break;
}
if ($CheckVal) {
$val =$CheckVal;
}
this will give u your value in array.

How to recursively create a multidimensional array?

I am trying to create a multi-dimensional array whose parts are determined by a string. I'm using . as the delimiter, and each part (except for the last) should be an array
ex:
config.debug.router.strictMode = true
I want the same results as if I were to type:
$arr = array('config' => array('debug' => array('router' => array('strictMode' => true))));
This problem's really got me going in circles, any help is appreciated. Thanks!
Let’s assume we already have the key and value in $key and $val, then you could do this:
$key = 'config.debug.router.strictMode';
$val = true;
$path = explode('.', $key);
Builing the array from left to right:
$arr = array();
$tmp = &$arr;
foreach ($path as $segment) {
$tmp[$segment] = array();
$tmp = &$tmp[$segment];
}
$tmp = $val;
And from right to left:
$arr = array();
$tmp = $val;
while ($segment = array_pop($path)) {
$tmp = array($segment => $tmp);
}
$arr = $tmp;
I say split everything up, start with the value, and work backwards from there, each time through, wrapping what you have inside another array. Like so:
$s = 'config.debug.router.strictMode = true';
list($parts, $value) = explode(' = ', $s);
$parts = explode('.', $parts);
while($parts) {
$value = array(array_pop($parts) => $value);
}
print_r($parts);
Definitely rewrite it so it has error checking.
Gumbo's answer looks good.
However, it looks like you want to parse a typical .ini file.
Consider using library code instead of rolling your own.
For instance, Zend_Config handles this kind of thing nicely.
I really like JasonWolf answer to this.
As to the possible errors: yes, but he supplied a great idea, now it is up to the reader to make it bullet proof.
My need was a bit more basic: from a delimited list, create a MD array. I slightly modified his code to give me just that. This version will give you an array with or without a define string or even a string without the delimiter.
I hope someone can make this even better.
$parts = "config.debug.router.strictMode";
$parts = explode(".", $parts);
$value = null;
while($parts) {
$value = array(array_pop($parts) => $value);
}
print_r($value);
// The attribute to the right of the equals sign
$rightOfEquals = true;
$leftOfEquals = "config.debug.router.strictMode";
// Array of identifiers
$identifiers = explode(".", $leftOfEquals);
// How many 'identifiers' we have
$numIdentifiers = count($identifiers);
// Iterate through each identifier backwards
// We do this backwards because we want the "innermost" array element
// to be defined first.
for ($i = ($numIdentifiers - 1); $i >=0; $i--)
{
// If we are looking at the "last" identifier, then we know what its
// value is. It is the thing directly to the right of the equals sign.
if ($i == ($numIdentifiers - 1))
{
$a = array($identifiers[$i] => $rightOfEquals);
}
// Otherwise, we recursively append our new attribute to the beginning of the array.
else
{
$a = array($identifiers[$i] => $a);
}
}
print_r($a);

Categories