why would you wrap a variable in square brackets? php 7 [duplicate] - php

Is there a way to explode a string into variables e.g
some_function($min, $max, "3, 20");
such that $min is assigned the value 3 and $max is assigned the value 20.
I know I can simply use
$data = explode("3, 20");
just wondering if there is another way.

PHP's language construct list() can perform multiple assignments to variables (or even other array keys) by assigning an array.
list($min, $max) = explode(",", "3,20");
However, you would still need to apply a trim() to your variables since the $max value would have a leading space, or replace explode() with preg_split('/\s*,\s*/', $string) to split it on commas and surrounding whitespace.
Note: Use caution with list() to be sure that the array you're assigning contains the same number of elements as list() has variables.
In PHP 5.x, when assigning a value directly to another array, as an element of that array, list() values are assigned from right to left in PHP 5.x, not left to right. In other words, you'll end up with array that is populated backwards (last value, first).
https://www.php.net/manual/en/migration70.incompatible.php
In PHP 7.x list() arguments are assigned from left to right, when assigning elements directly to an array. In other words, you'll end up with the first value as the first element in the recipient array.
<?php
list($a[], $a[], $a[]) = [1, 2, 3];
var_dump($a);
?>
PHP Manual
PHP 5.X Last value gets the first element position, but the recipient must an array (in this case $a, is the array)!
array(3) {
[0]=>
int(3)
[1]=>
int(2)
[2]=>
int(1)
}
PHP 7.x First value becomes the first array element.
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
PHP Manual

Since PHP 7.1 there is a new feature called
Symmetric array destructuring: The shorthand array syntax ([]) may now
be used to destructure arrays for assignments (including within
foreach), as an alternative to the existing list() syntax, which is
still supported.
That means that you can do now:
[$one, $two] = explode(";", "one;two");
echo $one; // one
echo $two; // two
As an alternative to list(), I find it myself a very elegant and readable solution that arrived with 7.1+ ... it is the same, but better.
Note: As the quote indicates, you can use the shorthand array syntax ([]) to assign variables in foreach declarations, but that's not related to the question, so check it out!
Documentation: https://www.php.net/manual/en/migration71.new-features.php

Related

What happens when extract() is used in an array with default key values (0,1,2,...)

I haven't given this much thought before but recently tried an sample code to c what happens when using extract() on an array with default key values, how is it supposed to work there.
$testArray = array("apple", "ant", "book", "bag");
extract($testArray);
print_r($testArray);
echo "${1}";
where will be the values apple, ant, book, and bag stored after extract() is applied.
This is a simple question but somebody please help me solve it.
If you pass no flag; nothing. With no flags, extract will only work if an associative array is passed.
From the documentation:
You must use an associative array; a numerically indexed array will not produce results unless you use EXTR_PREFIX_ALL or EXTR_PREFIX_INVALID.
So you can pass a numerical array, but you must pass a flag and a prefix for the variable name. Prefixes will be prepended to the invalid variable name, along with an underscore:
$pref = 'P';
$testArray = array("apple", "ant", "book", "bag");
extract($testArray, EXTR_PREFIX_INVALID, $pref);
var_dump($P_1); // ant
eval.in
As it is in your code it would not create any variables because there are not defined keys so the keys are 0, 1, 2... therefore, invalid variable names that will prevent them from being extracted.
if you use EXTR_PREFIX_ALL or EXTR_PREFIX_INVALID to prefix your keys with something to make them valid variable names then you could see them in
echo $whateveryourprefixis0;
echo $whateveryourprefixis1;
echo $whateveryourprefixis2;
...

PHP objects with Int variables

I've noticed something quite strange with PHP Objects and can't find a documented cause of it.
The following code demonstrates the behaviour
<?php
$a = (object) array( 0 => 1 );
foreach($a as $b => $c) {
$a->$b = ++$c; //I'm expecting the key to be overwritten here
}
var_dump($a);
$var = 0;
var_dump($a->$var);
$var = "0";
var_dump($a->$var);
and the output
object(stdClass)#1 (2) {
[0]=>
int(1)
["0"]=>
int(2)
}
int(2)
int(2)
Is the numeric part of the class inaccessible using -> syntax?
When you perform an (object) cast on an array you promote that array as the internal property list of an anonymous object (i.e. stdClass).
The way properties are indexed in an object is slightly different than that of an array; specifically, object property names are always treated as strings whereas array indices are looked up based on the intended type (e.g. numeric strings are seen as integers).
The above behaviour doesn't affect foreach loops because there's no hashing involved there; as far as PHP is concerned, a regular array is being iterated.
To answer your question, yes, the numeric keys from your original array can't be accessed using the -> operator. To avoid this you should remove the numeric indices from your array before the cast is performed.
It's hard to find this behaviour in the documentation, but a hint of it can be found here:
If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible ...
FYI
In this particular case you can circumvent the issue by using references; this is not recommended, please follow the earlier advise of not using numeric property names:
foreach ($a as &$c) {
++$c;
}
unset($c);
Update
2014-11-26: I've updated the documentation; the live pages will be updated this Friday - commit.
stdClass handles data terribly loosely, since it's an object representation of an internal array (thus the ability of of casting without problems).
$stdClassObject->property = "value";
The property is handled as a string, but upon casting, the property type doesn't change (which is somehow understandable, as if you cast to an object and then to an array again, you'd have lost all the integer indexes).
I don't think they could do better than that, but you can create your own alternative to stdClass :-)

Can PHP arrays hold items of different type?

In other programming languages the definition of arrays is something which can hold similar kind of elements. For example if I declare something like int i[] it will store integers, but in PHP a single array seems to be holding strings and numbers together.
Will the number/integer be treated as string in such type of array in PHP?
According to the PHP manual you can indeed store heterogeneous types inside a PHP "array" - scroll down to example 3.
Note that even though the example is about keys being ints or strings, the values assigned in the example are also both ints and strings, demonstrating that it is possible to store heterogeneous types.
Be aware that in the case of different-typed keys there is automatic casting involved so you may have surprising results in the case where e.g. a string contains a valid decimal representation.
Yes. A PHP array can have multiple data types in it.
Also, you should note that arrays in PHP actually are represented in the form of key-value pairs, where the elements you will input into the array are values.
You can explicitly define keys too, when entering elements into the array, but when you don't, PHP will use indices starting from 0.
Example:
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
?>
PHP will interpret as
array(4) {
["foo"]=>
string(3) "bar"
["bar"]=>
string(3) "foo"
[100]=>
int(-100)
[-100]=>
int(100)
}
Reference- http://php.net/manual/en/language.types.array.php
You can store anything you want in an array.
Will the number/integer be treated as string in such type of array in PHP?
Not upon storing it. However, when you use a value as such, PHP will convert it. The usage of a value determines its interpretation. (Attention, the key is converted upon storing, however, if it is considered numerical)
Not going to put oil on the fire of the PHP Arrays are no arrays here…
But yes, you can put different variable types (string, int, …) together in a PHP thing called Array.

explode string into variables

Is there a way to explode a string into variables e.g
some_function($min, $max, "3, 20");
such that $min is assigned the value 3 and $max is assigned the value 20.
I know I can simply use
$data = explode("3, 20");
just wondering if there is another way.
PHP's language construct list() can perform multiple assignments to variables (or even other array keys) by assigning an array.
list($min, $max) = explode(",", "3,20");
However, you would still need to apply a trim() to your variables since the $max value would have a leading space, or replace explode() with preg_split('/\s*,\s*/', $string) to split it on commas and surrounding whitespace.
Note: Use caution with list() to be sure that the array you're assigning contains the same number of elements as list() has variables.
In PHP 5.x, when assigning a value directly to another array, as an element of that array, list() values are assigned from right to left in PHP 5.x, not left to right. In other words, you'll end up with array that is populated backwards (last value, first).
https://www.php.net/manual/en/migration70.incompatible.php
In PHP 7.x list() arguments are assigned from left to right, when assigning elements directly to an array. In other words, you'll end up with the first value as the first element in the recipient array.
<?php
list($a[], $a[], $a[]) = [1, 2, 3];
var_dump($a);
?>
PHP Manual
PHP 5.X Last value gets the first element position, but the recipient must an array (in this case $a, is the array)!
array(3) {
[0]=>
int(3)
[1]=>
int(2)
[2]=>
int(1)
}
PHP 7.x First value becomes the first array element.
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
PHP Manual
Since PHP 7.1 there is a new feature called
Symmetric array destructuring: The shorthand array syntax ([]) may now
be used to destructure arrays for assignments (including within
foreach), as an alternative to the existing list() syntax, which is
still supported.
That means that you can do now:
[$one, $two] = explode(";", "one;two");
echo $one; // one
echo $two; // two
As an alternative to list(), I find it myself a very elegant and readable solution that arrived with 7.1+ ... it is the same, but better.
Note: As the quote indicates, you can use the shorthand array syntax ([]) to assign variables in foreach declarations, but that's not related to the question, so check it out!
Documentation: https://www.php.net/manual/en/migration71.new-features.php

Any reason PHP don't iterate array by reference?

$arr = array(array(array()));
foreach($arr as $subarr)
{
$subarr[] = 1;
}
var_dump($arr);
Output:
array(1) {
[0]=>
array(1) {
[0]=>
array(0) {
}
}
}
But for object,it's reference:
class testclass {
}
$arr = array(new testclass());
foreach($arr as $subarr)
{
$subarr->new = 1;
}
var_dump($arr);
Output:
array(1) {
[0]=>
object(testclass)#1 (1) {
["new"]=>
int(1)
}
}
Why treat array different from object?
PHP passes all objects by reference. (PHP5?)
PHP passes all arrays by value.
Originally PHP passed both objects and arrays by value, but in order to cut down on the number of objects created, they switch objects to automatically pass by reference.
There is not really a logical reason why PHP does not pass arrays by reference, but that is just how the language works. If you need to it is possible to iterate over arrays by value but you have to declare the value explicitly by-reference:
foreach ( $myArray as &$val ){
$val = 1; //updates the element in $myArray
}
Thanks to Yacoby for the example.
Frankly I prefer arrays to be passed by value because arrays are a type of basic data structure, while objects are more sophisticated data structures. The current system makes sense, at least to me.
Foreach copies the iterated array because it allows you to modify the original array while inside the foreach, and it's easier to use that way. Wouldn't it be the case, your first example would blow up. There is no way to keep PHP from copying the array inside a foreach. Even when using the pass-item-by-reference syntax foreach($foo as &$bar), you'll still work on a copy of the array, one that contains references instead of actual values.
Objects, on the other hand, are expected from most object-oriented developers to always be passed by reference. This became the case in PHP 5. And when you copy an array that contains objects, you actually copy the references to objects; so even though you're working on an copy of the array, you're working on the same objects.
If you want to copy an object, use the clone operator. As far as I know, there is no way to have certain objects always be passed by value.
$foo = new Foo;
$bar = clone $foo;
Why would array and object be treated the same?
PHP simply passes objects by reference (->), and passes all arrays by value.
If all objects were passed by value, the script would make many copies of the same class, thereby using more memory.

Categories