PHP equivalent for Python's repr() [duplicate] - php

This question already has an answer here:
PHP Array to String equivalent
(1 answer)
Closed 10 years ago.
I'm creating a simple array wrapper class and want it's __toString() method to be formatted like a Python list, eg: ["foo", "bar", 6, 21.00002351]. Converting each element to a string is not enough, since string-objects are actually enquoted in the list-representation.
Is there a repr() equivalent in PHP, and if not, what would a PHP implementation look like?

Python's repr() returns an output where
eval(repr(object)) == object
Called by the repr() built-in function and by string conversions (reverse quotes) to compute the “official” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment).
So the closest thing in PHP would be
var_export — Outputs or returns a parsable string representation of a variable
The keyword here is parseable. While functions print_r and var_dump will give a certain representation of the data passed to them, they are not easily parseable, nor do they look like PHP expression, which could be eval'd.
Example:
var_export(['foo', 'bar', 1,2,3]);
will give
array (
0 => 'foo',
1 => 'bar',
2 => 1,
3 => 2,
4 => 3,
)
and that is perfectly valid PHP code:
$data = ['foo', 'bar', 1, 2, 3];
$repr = var_export($data, true);
// have to use it with return though to eval it back into a var
$evald = eval("return $repr;");
var_dump($evald == $data); // true
Another option would be to use serialize to get a canonical and parseable representation of a data type, e.g.
$data = ['foo', 'bar', 1, 2, 3];
$repr = serialize($data);
// -> a:5:{i:0;s:3:"foo";i:1;s:3:"bar";i:2;i:1;i:3;i:2;i:4;i:3;}
var_dump( unserialize($repr) == $data ); // true
Unlike var_export, the resulting representation is not a PHP expression, but a compacted string indicating the type and it's properties/values (a serialization).
But you are likely just looking for json_encode as pointed out elsewhere.
Making this a Community Wiki because I've already answered this in the given dupe.

I don't know Python but PHP arrays can contain any data type and nesting levels. I don't know how that translates into your format.
There're many functions to print an array:
print_r()
var_dump()
var_export()
... but your format reminds me of JSON so you can simply do this:
<?php
$foo = array (
'foo',
'bar',
6,
21.00002351,
);
echo json_encode($foo); // ["foo","bar",6,21.00002351]
Of course, it's by no means automatic, i.e., this won't trigger any toString() method at all:
echo $foo; // "Array" + PHP Notice: Array to string conversion

Related

php comparison operator in assignment

I saw a small php quiz online that contained the following code:
$somevalue[[ 2 <=['-']=> 2][1]] = $somestring;
My question is, what does the part before the assignment do?
$somevalue[[ 2 <=['-']=> 2][1]]
<= looks like the comparison operator but in that case it is comparing 2 to '-'?
PHP's array initialization syntax looks like this:
$arr = [ key => value ];
So in this part:
2 <=['-']=> 2
The 'key' is the result of the expression 2 <= ['-'], which according to this page evaluates to true (an array is always greater than what you are comparing it to, unless it's another array). Because PHP arrays keys are either integers or strings, the boolean result is implicitly cast to the integer 1, so you end up with:
1 => 2
So the simplified expression:
[ 1 => 2 ][1]
Will evaluate to the second element of the array we've just created (PHP array's are 0-based), so this will simplify to:
2
So at the end we end up with:
$somevalue[2] = $somestring;
To understand this you need to break the statement in parts,
echo 2 <=['-'];//return true
PHP Comparison operator
After this the statement will be
$somevalue[[1 => 2][1]] = $somestring;
Here you see the array index 1 has values 2. After this the last index which is 1, from the array [1 => 2] it will return 2, so finally you will have
$somevalue[2] = $somestring;

Convert array of values into a single float value in PHP?

I have an array with these values (when the array is printed with print_r();
Array:
[0] => 66
[1] => 233
[2] => 204
[3] => 205
The values in hex are:
Array:
[0] => 0x42
[1] => 0xE9
[2] => 0xCC
[3] => 0xCD
What I'm looking to do is to turn this 4 byte array into a float value. If I use implode(); to turn the array into a value, it just combines the string into 66233204205 instead of 0x42E9CCCD which are not similar. Thus I can't use floatval(). PHP is new to me, and so is using string values instead of the actual bits, like I can in C.
What I'm thinking is to some how implode() it with the hex values, instead of those integer numbers, and then use floatval().
Any ideas guys?
EDIT:
Just so it's a little clearer, I should be obtaining 116.900 as the result
You have to do a simple math operation to concatenate hex values of the array one after the other. The algorithm would be like this:
Assign the first hex value of the array to a resultant variable, $concat in this case.
Use a for loop to loop through the array from 2nd element till nth element
In each iteration of the loop left shift 8 times the existing hex value of the resultant variable and place the new hex value in the least significant 8 bits of the resultant variable.
// Suppose $array is your original array
$concat = $array[0];
$count = count($array);
for($i = 1; $i < $count; $i++){
$concat = ($concat << 8) + $array[$i];
}
// display concatenated hex value: 42e9cccd
var_dump(dechex($concat));
// Now do your operation on the concatenated hex value
Here's a demo, https://eval.in/844793
Revised Answer with ....
Performing math with hex strings used to be a feature supported in PHP. Now with PHP 7, a hex string only represents a string of characters and no longer is recognized as containing a numeric value. If you attempt to do math with it, the result is zero. Consider the following code:
<?php
$arr = [66, 233, 204, 205];
$res = array_reduce( $arr, function($c,$i) {
$c.=dechex( $i );
return $c;
});
$temp = "0x" . $res; // 0x42e9cccd
var_dump($temp + 0);
See demo
This code attempts to provide the hex string a mathematical context by adding zero to the value contained in $temp. This code works until PHP 7 because the powers that be determined that hexstrings created more problems than they were worth; see this RFC and the Manual:"Hexadecimal strings are no longer considered numeric".
Concatenation, being a string operation, creates the example's hex string whose direct usage proves unwise in a math operation. A notice will be emitted (in PHP 7.1), complaining as follows:
Notice: A non well formed numeric value encountered
You may suppress displaying this notice, but the resulting sum will be zero in PHP 7. When the code functions correctly in PHP 5.6, the result of 1122618573 seems wrong, certainly far too large to cast as a float and obtain the value that the OP seeks.
... A Bona Fide Work-Around
<?php
$arr = [66, 233, 204, 205];
$res = array_reduce( $arr, function($c,$i) {
$c.=dechex( $i );
return $c;
});
$temp = "0x" . $res;
$int = filter_var( $temp, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX );
if (false === $int) {
throw new Exception("Invalid integer!");
}
$arr = (unpack('f', pack('i', $int )));
$f = array_pop($arr);
printf("%.3f",$f);
See demo
PHP will recognize the numeric hex string that array_reduce() yields if you use filter_var() with the indicated parameters. In this fashion, you may obtain an integer evaluating as 1122618573. The key thing rather than the integer's value is its binary bit pattern. Borrowing from the official answer here, the code needs to pack $int into a binary string, which it subsequently will unpack as a float -- almost. That result will be returned as an array with just one element. After popping off and capturing that element's float value, printf() displays 116.900.
This appends the values of the array to eachother (in hexadecimal). PHP's dechex() function.
http://php.net/dechex
dechex — Decimal to hexadecimal
$b = [66,233,204,205];
$a = dechex($b[0]);
for($x = 1; $x < count($b); $x++) {
$a = $a . dechex($b[$x]);
}
echo $a; // $a = 42e9cccd
You didn't specify if your array represents an integer, if is the integer part of the floating point value, or is the entire number represented in IEEE 754 format.
Anyway, I would suggest you to take a look at the "pack" function.
$value = pack('i', your_value);
HERE you can find the documentation: basically you have to provide the type you want to obtain, along with your value(s), of course.
Also PHP is NOT a strongly typed language, so you don't have to distinguish integer from floats, in this case. You can treat integer like floats, and viceversa. But if you want to be 100% sure, just do something like this:
$value = floatval(pack('i', your_value));
This is, of course, machine dependent, but I don't know of any machine running PHP that doesn't use IEEE 754 floats.

strlen on array returns 5 in php

From the docs -
int strlen ( string $string )
it takes string as a parameter, now when I am doing this-
$a = array('tex','ben');
echo strlen($a);
Output -
5
However I was expecting, two type of output-
If it is an array, php might convert it into string so the array will become-
'texben' so it may output - 6
If 1st one is not it will convert it something like this -
"array('tex','ben')" so the expected output should be - 18 (count of all items)
But every time it output- 5
My consideration from the output is 5 from array word count but I am not sure. If it is the case how PHP is doing this ?(means counting 5)
The function casts the input as a string, and so arrays become Array, which is why you get a count of 5.
It's the same as doing:
$a = array('tex','ben');
echo (string)$a; // Array
var_dump((string)$a); // string(5) "Array"
This is the behavior prior to PHP 5.3. However in PHP 5.3 and above, strlen() will return NULL for arrays.
From the Manual:
strlen() returns NULL when executed on arrays, and an E_WARNING level error is emitted.
Prior [to 5.3.0] versions treated arrays as the string Array, thus returning a string length of 5 and emitting an E_NOTICE level error.
Use
$a = array('tex','ben');
$lengths = array_map('strlen',$a);
to get an array of individual lengths, or
$a = array('tex','ben');
$totalLength = array_sum(array_map('strlen',$a));
to get the total of all lengths
The array is implicitly converted to a string. In PHP this yields the output Array, which has 5 letters as strlen() told you.
You can easily verify this, by running this code:
$a = array('tex','ben');
echo $a;

What is this bitwise OR doing in this weird array key construct?

Can someone explain to me what this means?? I have never seen this construct - taken from the Prestashop doc
foreach ( $languages as $language )
{
echo '<div id="test_' . $language['id_lang'|'id_lang'] .... // <-- What the??
// ...
}
$language contains the following keys:
Array
(
[id_lang] => 1
[name] => English (English)
// and others...
)
The result is that it takes the value of $language["id_lang"] - 1. But I don't understand the syntax and can't find any documentation about it.
This php -a session shows that it's totally meaningless:
php > $value = 'something'|'something';
php > echo $value;
something
php > $arr = array('abc' => 1, 'def' => 2);
php > echo $arr['abc'|'abc'];
1
php > echo $arr['def'|'def'];
2
Basically, if you "bitwise or" anything by itself, you get the original value. This property is called idempotence in mathematics. For further info, read:
http://en.wikipedia.org/wiki/Idempotence
http://en.wikipedia.org/wiki/Bitwise_operation#OR
Honestly, the original author of that code had no idea what they were doing.
What that does is use the bitwise operator on the ASCII values of the characters in the string "id_lang", although why they are doing this is beyond me, since the result is always going to be the same.
To elaborate a little bit, let's say (for convenience) that we're using ASCII, where each character is encoded as a single byte. Let's look at what happens when it does the comparison for the binary representation of the first character (i is 105, which in binary is 01101001):
"i": 01101001
OR "i": 01101001
___________
= 01101001
= "i"
0|0 is 0, 1|1 is 1, so inevitably all bits remain unchanged.
It's not doing anything, strangely enough.
var_dump('id_lang'|'id_lang');
#=> string(7) "id_lang"
http://ideone.com/zXdRMO
Even if it was doing something, using a bitwise operator on a string-based array key certainly feels like code smell to me.

Weird PHP String Integer Comparison and Conversion

I was working on some data parsing code while I came across the following.
$line = "100 something is amazingly cool";
$key = 100;
var_dump($line == $key);
Well most of us would expect the dump to produce a false, but to my surprise the dump was a true!
I do understand that in PHP there is type conversion like that:
$x = 5 + "10 is a cool number"; // as documented on PHP manual
var_dump($x); // int(15) as documented.
But why does a comparison like how I mentioned in the first example converts my string to integer instead of converting the integer to string.
I do understand that you can do a === strict-comparison to my example, but I just want to know:
Is there any part of the PHP documentation mentioning on this behaviour?
Can anyone give an explanation why is happening in PHP?
How can programmers prevent such problem?
If I recal correcly PHP 'casts' the two variables to lowest possible type.
They call it type juggling.
try: var_dump("something" == 0);
for example, that'll give you true . . had that bite me once before.
More info: http://php.net/manual/en/language.operators.comparison.php
I know this is already answered and accepted, but I wanted to add something that may help others who find this via search.
I had this same problem when I was comparing a post array vs. keys in a PHP array where in my post array, I had an extra string value.
$_POST["bar"] = array("other");
$foo = array(array("name"=>"foobar"));
foreach($foo as $key=>$data){
$foo[$key]["bar"]="0";
foreach($_POST["bar"] as $bar){
if($bar==$key){
$foo[$key]["bar"]="1";
}
}
}
From this you would think that at the end $foo[0]["bar"] would be equal to "0" but what was happening is that when $key = int 0 was loosely compared against $bar = string "other" the result was true to fix this, I strictly compared, but then needed to convert the $key = int 0 into a $key = string "0" for when the POST array was defined as array("other","0"); The following worked:
$_POST["bar"] = array("other");
$foo = array(array("name"=>"foobar"));
foreach($foo as $key=>$data){
$foo[$key]["bar"]="0";
foreach($_POST["bar"] as $bar){
if($bar==="$key"){
$foo[$key]["bar"]="1";
}
}
}
The result was $foo[0]["bar"]="1" if "0" was in the POST bar array and $foo[0]["bar"]="0" if "0" was not in the POST bar array.
Remember that when comparing variables that your variables may not being compared as you think due to PHP's loose variable typing.

Categories