Can i get the effect of JSON_NUMERIC_CHECK without JSON?
i.e. Recrusive replacement of numeric strings to ints or floats.
Example with JSON_NUMERIC_CHECK:
<?php
// some input from somewhre
$data = explode(',', 'abc,7,3.14');
echo "Before:"; var_dump($data);
$data = json_decode(json_encode($data, JSON_NUMERIC_CHECK), TRUE);
echo "After:"; var_dump($data);
But I geuss converting to json and back is slow, is there some other way to get the same result?
You can loop over your strings and cast any numeric value to int or float using the following code:
/**
* Normalize an object, array or string by casting all
* numeric strings it contains to numeric values.
*
* #param array|object|string $data
* #return mixed
*/
function normalize($data) {
if (is_array($data))
return array_map('normalize', $data);
if (is_object($data))
return (object) normalize(get_object_vars($data));
return is_numeric($data) ? $data + 0 : $data;
}
$data = "15,2.35,foo";
$data = normalize(explode(',', $data));
// => [15, 2.35, 'foo']
Hope this helps :)
More efficient way
/**
* Normalize an string or object by casting all
* numeric strings it contains to numeric values.
* Note that it changes the variable directly
* instead of returning a copy.
*
* #param object|string $data
* #return void
*/
function normalizeItem(&$data) {
if (is_object($data)) {
$data = get_object_vars($data);
normalize($data);
$data = (object) $data;
} else {
$data = is_numeric($data) ? $data + 0 : $data;
}
}
/**
* Applies normalizeItem to an array recursively.
*
* #param array &$list
* #return bool
*/
function normalize(&$list) {
return array_walk_recursive($list, 'normalizeItem');
}
You can use array_map() with a callback.
$data = explode(',', 'abc,7,3.14');
$re = array_map(function(&$a) {
return ctype_digit($a) ? intval($a) : $a;
}, $data);
var_dump($re);
https://eval.in/715641
Related
If I do this:
$array = ["one", "two", "three"];
$array_copy = "$array"; // or "{$array}"
I doesn't get the original array but instead a string conversion of it. ¿Is there any way to acomplish this task? To get the array reference by his string name.
Thank you.
Edit:
I am aware of this:
$array = ["one", "two", "three"];
$array_copy = $"array";
or
$name = "array";
$array_copy = $$name
But I need to achive this in any situation. Example:
$array = ["one", "two", "three" => ["four"] ];
$sub_array = "{$array['three']}"; // this returns an string, not the array ["four"]
I hope is more clear now.
Edit 2
Let's put it in other way. Imagine you need that an user input (string) be able to access the content of any declared variable. Example:
$customer = [ "name"=>"Peter", "address"=> ["street"=>"5th", "number"=>1969] ];
$variable_name = $_GET["varname"];
var_export( $$variable_name ); // What can write the user to print $customer["address"] array?
because you equal to string, just do it directly
$array_copy = $array
but copy is just copy, not a referense, if you want reference you should write like this
$array_copy = &$array
but there are should be reasons to get the reference
or if you have some variable with array name then you can do like this
$array = ["one", "two", "three"];
$arrayName = 'array';
$array_copy = $$arrayName;
You may use a function that takes a path such as customer.address as a parameter to retrieve the address index of the $customer array automatically:
$customer = ['name' => 'Peter', 'address' => ['street' => '5th', 'number' => 1969]];
/**
* #param array $array
* #param string $path A dot-separated property path.
* #param mixed $default
* #return mixed
*/
function getArrayValue(array $array, string $path, $default = null)
{
$parts = explode('.', $path);
return array_reduce($parts, static function ($value, $part) use ($default) {
return $value[$part] ?? $default;
}, $array);
}
/**
* #param string $path A dot-separated path, whose first part is a var name available in the global scope.
* #param mixed $default
* #return mixed
*/
function getGlobalArrayValue(string $path, $default = null)
{
#list($varName, $propertyPath) = explode('.', $path, 2);
return getArrayValue($GLOBALS[$varName] ?? [], $propertyPath, $default);
}
echo getGlobalArrayValue('customer.name'), PHP_EOL; // Peter
echo getGlobalArrayValue('customer.address.street'), PHP_EOL; // '5th'
echo getGlobalArrayValue('customer.address.idontexist', 'somedefaultvalue'), PHP_EOL; // 'somedefaultvalue'
echo getGlobalArrayValue('idontexist.address', 12); // 12
Demo: https://3v4l.org/O6h2P
Error page recieved
This is the code block where the error originates. How do I handle this code snippet, I need it to work on laravel 5.4 the $extras variable is an array.
/**
* Map to configuration
*
* #param $keys
* #param $config_var
* #param $extras
* #return array
*/
private function map_to_config($keys, $config_var, $extras = [])
{
try {
$configArray =
array_map(function ($string) use ($keys, $extras) {
line 132 where the error is--> return array_combine($keys, explode(":", $string)) + $extras;
}, explode(",", $config_var));
return array_filter($configArray);
} catch (\Exception $e) {
return [];
}
}
}
array_combine returns FALSE if number of values in arrays given as arguments is different. That's probably a reason why you're getting an error about unsupported operand types - you're trying to combine a boolean with an array.
I'm trying to debug some old code from CodeIgniter 2.2. When running some data thru Session, I noticed an unserialize error, Message: unserialize(): Error at offset 160 of 163 bytes. After doing some debugging and research, I found out it's a common backslash issue when unserializing data from Sessions.
The serialized data I'm using has objects of data with backslashes in them, which causes the errors to occur. I'm in need of a replacement that can handle standard class objects as well.
Could someone recommend a quick replacement for codeigniter's Session _serialize() and _unserialize() methods?
public function data_test() {
$input = array(
(object)array('name' => 'test2', 'desc' => 'bla bla ob/gyn'),
(object)array('name' => 'test2', 'desc' => 'bla bla ob\\gyn'),
);
var_dump($input);
$data = $this->_serialize($input);
var_dump($data);
$result = $this->_unserialize($data);
var_dump($result);
}
// --------------------------------------------------------------------
/**
* Serialize an array
*
* This function first converts any slashes found in the array to a temporary
* marker, so when it gets unserialized the slashes will be preserved
*
* #access private
* #param array
* #return string
*/
function _serialize($data) {
if (is_array($data)) {
foreach ($data as $key => $val) {
if (is_string($val)) {
$data[$key] = str_replace('\\', '{{slash}}', $val);
}
}
} else {
if (is_string($data)) {
$data = str_replace('\\', '{{slash}}', $data);
}
}
return serialize($data);
}
// --------------------------------------------------------------------
/**
* Unserialize
*
* This function unserializes a data string, then converts any
* temporary slash markers back to actual slashes
*
* #access private
* #param array
* #return string
*/
function _unserialize($data) {
$data = unserialize(strip_slashes($data));
if (is_array($data)) {
foreach ($data as $key => $val) {
if (is_string($val)) {
$data[$key] = str_replace('{{slash}}', '\\', $val);
}
}
return $data;
}
return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data;
}
/**
* Serialize an array
*
* This function serializes the data and then base64_encodes it for
* storage with memcached. This avoids the common backslash issue.
*
* #access private
* #param array
* #return string
*/
function _serialize($data) {
return base64_encode(serialize($data));
}
// --------------------------------------------------------------------
/**
* Unserialize
*
* This function unserializes a data string. I first base64_decodes
* the data from memcached storage.
*/
function _unserialize($data) {
return unserialize(base64_decode($data));
}
You can sometimes come across this issue if you are using different versions of PHP, or if you change the version of PHP you are using while a session was open.
For example if you have a session cookie with an app that uses PHP 5.6.* and then you try to use it with an app (that resides on another sub-domain) that uses PHP 7.2.*, then you are going to get a warning error. Or, if you had an open session and then you changed the version of PHP that you are using with your app (say if you are developing locally and switching around PHP versions), then you'll get the warning. So best to use serialize/unserialize and with PHP version that does not change.
How can I fix this method to accept reference passing?
It throws Fatal error:Only variables can be passed by reference.
/**
* Set a value "deep within" an associative array.
*
* #param array $array_ - Target array to set value on.
* #param mixed $value - A value to set.
* #param string $keyPath - Like 'campaign.pushMessages.sendDate'.
*/
private function setValueForKeyPath(&$array, $value, $keyPath)
{
$keys = explode(".", $keyPath, 2); // Like [ 'campaign', 'pushMessages.sendDate' ]
// If keys is a leaf key...
$isLeaf = (count($keys) == 1);
if ($isLeaf)
{
// ...simply set the value.
$array[$keys[0]] = $value;
}
else
{
// ...or set a sub-array as value.
$this->setValueForKeyPath($array[$keys[0]], $value, $keys[1]);
}
}
I am trying to figure out the best way to use dot notation when passing in a key or set of keys into a function and getting that post value.
Example
shipping.first_name
What it looks like in actual $_POST array:
$_POST[shipping][first_name] = 'some value'
I would like to be able to pass in (as a parameter) the string, and have the function return the post value.
function get_post($str = NULL){
return $_POST[$key1][$key1]..etc.
}
Current attempt (working as intended, but need to put into $_POST):
From: SO Question
function assignArrayByPath(&$arr, $path) {
$keys = explode('.', $path);
while ($key = array_shift($keys)) {
$arr = &$arr[$key];
}
}
$output = array();
assignArrayByPath($output, $str);
This produces an array of:
Array ( [shipping] => Array ( [first_name] => ) )
I would like then to do something like this:
return isset($_POST.$output) ? true : false;
So how do I take that array created from the period separated string and check if it exists in POST?
I think this might be a duplicate, but I am not positive. I apologize in advance if it is. Any help is much appreciated.
See Laravel array_set implement http://laravel.com/api/source-function-array_set.html#319
/**
* Set an array item to a given value using "dot" notation.
*
* If no key is given to the method, the entire array will be replaced.
*
* #param array $array
* #param string $key
* #param mixed $value
* #return array
*/
function array_set(&$array, $key, $value)
{
if (is_null($key)) return $array = $value;
$keys = explode('.', $key);
while (count($keys) > 1)
{
$key = array_shift($keys);
// If the key doesn't exist at this depth, we will just create an empty array
// to hold the next value, allowing us to create the arrays to hold final
// values at the correct depth. Then we'll keep digging into the array.
if ( ! isset($array[$key]) || ! is_array($array[$key]))
{
$array[$key] = array();
}
$array =& $array[$key];
}
$array[array_shift($keys)] = $value;
return $array;
}
Check exists you can see array_get http://laravel.com/api/source-function-array_get.html#224
/**
* Get an item from an array using "dot" notation.
*
* #param array $array
* #param string $key
* #param mixed $default
* #return mixed
*/
function array_get($array, $key, $default = null)
{
if (is_null($key)) return $array;
if (isset($array[$key])) return $array[$key];
foreach (explode('.', $key) as $segment)
{
if ( ! is_array($array) || ! array_key_exists($segment, $array))
{
return value($default);
}
$array = $array[$segment];
}
return $array;
}