What does the (array) syntax do? - php

I'm currently building code in Laravel and adding the (array) part to my code fixed my laravel sync problem when there was no data being passed in the array. This is the question I learned from and got the (array) code to use.
I'm having a hard time finding the documentation for this in laravel or php and was wondering which language/framework the (array) code originates from and what it exactly does. If you could direct me to the right documentation page I would love that as well.

It's just another way of creating an array by using an existing variable
$x = 1; // int
$y = (array)$x; // array[0] => 1
$z = [$x]; // array[0] => 1
I should note that the last way would be preferred (directly declaring it as an array), since it's clearer what will happen (type juggling can produce unexpected results when converting values like this).
http://php.net/manual/en/language.types.array.php#language.types.array.casting

I think you are struggling with the process of type casting in php, like:
PHP type casting to array
We can convert any data type variable in array using (array) keyword. Any scalar data type conversion into array will create array and add element at 0th index.
For example:
<?php
var_dump((array) , 5);// value 5 in the array with 0th index
var_dump((array) NULL);// Will be empty array
?>
Explanation with example

It's just an array castring, according to the php manual
Converting to array
For any of the types integer, float, string, boolean and resource,
converting a value to an array results in an array with a single
element with index zero and the value of the scalar which was
converted. In other words, (array)$scalarValue is exactly the same as
array($scalarValue).
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; private variables have the class name prepended to the
variable name; protected variables have a '*' prepended to the
variable name. These prepended values have null bytes on either side.
This can result in some unexpected behaviour:
<?php
>
> class A {
> private $A; // This will become '\0A\0A' }
>
> class B extends A {
> private $A; // This will become '\0B\0A'
> public $AA; // This will become 'AA' }
>
> var_dump((array) new B()); ?>
The above will appear to have two keys named 'AA', although one of
them is actually named '\0A\0A'.
Converting NULL to an array results in an empty array.

Related

Are arrays passed by reference or value in PHP?

Are arrays passed by reference or value in PHP?
For example, let's see this code.
function addWeight($arout, $lineCountry, $lineDomain, $target, $weight)
{
$currentDomain=getDomain();
$currentCountry=getCountry();
if ($currentCountry==$lineCountry && ($currentDomain == $lineDomain || $lineDomain==""))
{
$tarobreakpoint=0;
$arout [$target] = intval($weight);
}
return $arout;
}
Basically it took an array as a parameter. Depending on some circumstances it adds elements to the array. I wonder if this is efficient? If $arout is passed by reference like all arrays should then I think it's efficient. But if it's just copied and passed by value then well it's not.
So what's the verdict?
According to the manual, PHP arrays are passed by value:
Array assignment always involves value copying. Use the reference operator to copy an array by reference.
If you'd like to pass an array's reference, use the corresponding operator (&) as mentioned above, and remove the return $arout; line in the addWeight() function:
<?php
// pass $array by reference using & operator
addWeight(&$array, $lineCountry, $lineDomain, $target, $weight);

PHP super weird warning : illigal string offset while creating a key

I have a very strange problem.
I am running through a foreach loop to compile an array but I receive an error.
I reveive the following warning :
Warning: Illegal string offset 'clientaccount_id' in
For this line of code:
$this->PreparedData[$table][$field] = 0;
I would say this to be logic if I would be doing something like:
$testVariable = $this->PreparedData[$table][$field];
Then the variable $field filled with 'clientaccount_id' would not exist.
But I am CREATING the field 'clientaccount_id' so to ME this is almost impossible to give an error.
The code
private function AssignData(){
foreach($this->FieldKeys as $table => $value){
///######## IF THE PREPARED DATA ARRAY DOES NOT EXIST
if(isset($this->PreparedData[$table]) === false){
///######## SET THE ARRAY KEY
$this->PreparedData[$table] = array();
}
///######## RUN THROUGH ALL SET SUB DATA
foreach($value as $field){
///######## IF THE FIELD EXISTS
if(isset($this->AccountData[$field]) === true){
///######## ASSIGN THE DATA
///$this->PreparedData[$table][$field] = $this->AccountData[$field];
///$this->PreparedData[$field] = $this->AccountData[$field];
$this->PreparedData[$table][$field] = 0;
}
}
}
exit('GOT THROUGH!!');
}
Could anyone see the error I am overlooking?
Solved!!
Thanks to VMcreator
Changed :
isset($this->PreparedData[$table]) === false
to this:
is_array($this->PreparedData[$table]) === false
Please read the explanation below WHY
Try to change this line:
isset($this->PreparedData[$table]) === false
to this:
!is_array($this->PreparedData[$table])
I saw this explanation here:
It just boils down to PHP's crazy type system.
$fruits['response']['errormessage'] is the string 'banana', so you're
attempting to access a character in that string by the ['orange']
index.
The string 'orange' is converted to an integer for the purposes of
indexing, so it becomes 0, as in
$fruits['response']['errormessage'][0]. The 0th index of a string is
the first character of the string, so for non-empty strings it's
essentially set. Thus isset() returns true.
You might be curious why your situation is comparable to that quoted statement even if $this->PreparedData[$table] seems a single dimensional array only, well its not a single dimensional array only, because you are accessing a class object, its just like doing this $this["PreparedData"][$table].

PHP Reference in array key

PHP:
$a = array("key" => 23);
var_dump($a);
$c = &$a["key"];
var_dump($a);
unset($c);
var_dump($a);
Output:
array(1) {
["key"]=>
int(23)
}
array(1) {
["key"]=>
&int(23)
}
array(1) {
["key"]=>
int(23)
}
In the second dump the value of "key" is shown as a reference. Why is that?
If I do the same with a normal variable instead of an array key this does not happen.
My only explanation would be that array keys are usually stored as references and as long as there is only one entry in the symbol table it is shown as a scalar in the dump.
Internally, PHP arrays are hashmaps (or dictionaries, or HashTables or whatever you want to call it). Even a numerically indexed array is implemented as a hash table, which is a zval, just like any other.
However, what you're seeing is expected behaviour, which is explained both here and here.
Basically, what your array looks like internally is this:
typedef struct _zval_struct {
zvalue_value value;
zend_uint refcount__gc;
zend_uchar type;
zend_uchar is_ref__gc;
} zval;
//zval_value:
typedef union _zvalue_value {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
} zvalue_value;
In case of an array, the zval.type will be set to indicate that the zval value is an array, and so the zval_value.ht member will be used.
What happens when you write $c = &$a['key'] is that the zval that is assigned to $a['key'] will be updated: zval.refcount__gc will be incremented, and is_ref__gc will be set to 1. Simply because the value is not copied, but the value is used by more than 1 variable: meaning this value is a reference. Once you unset($c);, the refcount is decremented, and the reference is lost, and so is_ref is set to 0.
Now for the big one: Why don't you see the same thing when you use regular, scalar variables? Well, that's because an array is a HashTable, complete with its own, internal, ref-counting (zval_ptr_dtor). Once an array itself is empty, it too should be destroyed. By creating a reference to an array value, and you unset the array, the zval should be GC'ed. But that would mean you have a reference to a destroyed zval floating around.
Therefore, the zval in the array is changed to a reference, too: a reference can be deleted safely. So that if you were to do this:
$foo = array(123);
$bar = &$foo[0];
unset($foo[0]);
echo $bar, PHP_EOL;
Your code will still work as expected: $foo[0] no longer exists, but $bar is now the only existing reference to 123.
This is just a really, really, short and incomplete explanation, but google the PHP internals, and how the memory management works, how references are dealt with internally, and how the garbage collector uses the is_ref and refcount members to manage the memory.
Pay special attention to the internal mechanisms like copy-on-write, and (when looking through the first link I provided here), look for the snippet that looks like this:
$ref = &$array;
foreach ($ref as $val) {}
Because it deals with some oddities in terms of references and arrays.

Check whether certain array keys are given or not

I'm writing some kind of a function that accepts an associative array as an argument.
This array can be:
Empty
Has only one element. With key either pageParam or wrapperClass.
Has two elements. Must be keyed with pageParam and wrapperClass.
Now i've written these checks to ensure that:
The array is not more than 2 elements.
The array does not have any elements other than pageParam and wrapperClass
The problem is, My second check is not working properly. Here's my code :
public function init_paginator(array $parameters = array())
{
if(!empty($parameters))
{
// This check works
if(count($parameters) > 2)
{
throw new \Exception("Paginator only accepts 2 elements in array: pageParam and wrapperClass.");
}
// This check does not work, even if its condition is satisfied
if(!in_array(array_keys($parameters), array('pageParam', 'wrapperClass')))
{
throw new \Exception("Paginator only accepts 2 elements in array: pageParam and wrapperClass.");
}
// Code..
}
}
The exception in the second check is always thrown if i entered the array argument like :
array("dummyKey"=>"dummyValue")
array("dummyKey1"=>"dummyValue1", "dummyKey2"=>"dummyValue2")
array("pageParam"=>"test") Or array("wrapperClass"=>"wrapper_class")
array("pageParam"=>"test", "wrapperClass"=>"wrapper_class")
The last two inputs is what puzzles me! Why the exception is thrown despite that my arguments are right.
Your second check looks for the value array_keys($parameters) inside array('pageParam', 'wrapperClass'). It compares an array of strings with two string values.
What you want is the keys of $parameters to be equal to the values of array('pageParam', 'wrapperClass'), thus:
array_keys($parameters) === array('pageParam', 'wrapperClass');
For arrays, the === operator evaluates to TRUE if both arrays have the same key/value pairs in the same order and of the same types. If you don't care about order, you can use ==.
By the way, this check renders the first one useless.
The doc aren't as descriptive as they should be, but the intent with the two arrays as args is that the needle is an array and the haystack is an array of arrays (multi-dimensional) that may contain the needle array. I'm headed out so will look again later, but maybe this as an alternative:
if(count(array_diff_key(array_keys(array('pageParam', 'wrapperClass')), $parameters)) > 1) {
//exception
}
The problem is in the way you use in_array
It'll never work because it keeps matching an array array_keys($parameters) to strings within another array array('pageParam', 'wrapperClass')
So, it keeps returning false
See PHP: in_array
Using array( array('pageParam', 'wrapperClass'), array('pageParam'), array('wrapperClass'), array()) as second parameter for in_array might work.

PHP - Array fatal error

I've got an odd error in my PHP code regarding dynamic arrays.
The error outputted is:
Fatal error: Cannot use string offset as an array ... on line 89
This is a portion of my code, it is within a foreach loop, which is looping through settings in a database:
foreach($query->fetchAll() as $row)
{
if($site!=CURRENT_SITE_TEMPLATE)
{
$property = 'foreignSettings';
$propertyType = 'foreignSettingsTypes';
} else {
$property = 'settings';
$propertyType = 'settingTypes';
}
$this->$property[$row['variable_section']][$row['variable_name']] = $row['variable_value'];
settype($this->$property[$row['variable_section']][$row['variable_name']],$row['variable_type']);
$this->$propertyType[$row['variable_section']][$row['variable_name']] = $row['variable_type'];
}
For the sake of the example code, $site is 'admin' and CURRENT_SITE_TEMPLATE is 'admin'.
In addition, $foreignSettings, $foreignSettingsTypes, $settings, and $settingTypes are all defined as arrays in the class scope
The error is on line 89, which is:
$this->$property[$row['variable_section']][$row['variable_name']] = $row['variable_value'];
I originally thought it was because of the $property variable accesing the array, however, this looks like valid legal code in the PHP documentation ( http://php.net/manual/en/language.variables.variable.php in example #1)
Any help on this error would be appreciated.
Thanks
In your given example $property is a string. You are then trying to use that as an array. Strings only has numeric indexes (if you need to use as an array).
The problem is as follows: $this->$property[0] means you access the 0th place of $property which in your case would be the first letter of the string $property. Thus you end up with $this->f or $this->s.
with $this->$property[0][0] you would be trying to access the 0th place of the 0th place of the $property string what results in an error because you try to access the 0th place of the char s what is not possible since the char s can not be referenced as an array.
what you want is $this->{$propperty}[0][0] what means that you try to access the 0th place of the 0th place of the variable that has the name $propperty.

Categories