PHP::Reference or copy (case inside)? - php

Please help me to prove about the case if variable reference or copy.
Case1 - $arr copy or reference?:
class Ex1{
public static $var1=array(10=>'work', 20=>'home');
}
$arr=Ex1::$var1;
Case2 - $arr copy or reference?:
class Ex1{
protected static $var1=array(10=>'work', 20=>'home');
public static function getArr(){
return self::$var1;
}
}
$arr=Ex1::getArr();
Thanks,
Yosef

By my reckoning, it should be a copy.
class Ex1{
public static $var1=array(10=>'work', 20=>'home');
}
$arr=Ex1::$var1;
var_dump($arr);
$arr[15] = 'play';
var_dump($arr);
$arr2=Ex1::$var1;
var_dump($arr2);
Ex1::$var1 = array(10=>'work', 15=>'asylum', 20=>'home');
$arr3=Ex1::$var1;
var_dump($arr3);
var_dump($arr2);
gives
array
10 => string 'work' (length=4)
20 => string 'home' (length=4)
array
10 => string 'work' (length=4)
20 => string 'home' (length=4)
15 => string 'play' (length=4)
array
10 => string 'work' (length=4)
20 => string 'home' (length=4)
array
10 => string 'work' (length=4)
15 => string 'asylum' (length=6)
20 => string 'home' (length=4)
array
10 => string 'work' (length=4)
20 => string 'home' (length=4)

Both copy. Only objects are transmitted by reference by default.

Modify $arr and then var_dump(Ex1::getArr()); and you'll see if it was a copy or a reference.
edit: didn't see Ex1::var1 was protected

It is going to be a copy, test it like:
$arr=Ex1::$var1;
$arr['omg'] = 'lol';
var_dump($arr);
var_dump(Ex1::$var1);

Related

PHP and JSON from Openstreetmap search

I am trying to use Openstreetmap and PHP to point to a place on a map.
As you can see below, I retrieve a JSON array, but PHP returns a NULL value.
Note that my $url is a valid JSON (you can check it here).
<?
$url = 'http://nominatim.openstreetmap.org/search/Piazza%20Duomo%20Trento?format=json&addressdetails=1&limit=1&polygon_svg=1';
$html = file_get_contents($url);
$jsonout = json_decode($html);
echo $jsonout[0];
?>
What am I doing wrong?
What am I doing wrong?
First of all, your openning tag is not correct :
<? ----> <?php
Then, you cannot echo an array like that. Use var_dump on your array to see the structure.
When I try your code with the corrections, I got this :
array (size=1)
0 =>
object(stdClass)[1]
public 'place_id' => string '8577656' (length=7)
public 'licence' => string 'Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright' (length=84)
public 'osm_type' => string 'node' (length=4)
public 'osm_id' => string '924463183' (length=9)
public 'boundingbox' =>
array (size=4)
0 => string '46.0675164' (length=10)
1 => string '46.0676164' (length=10)
2 => string '11.1217498' (length=10)
3 => string '11.1218498' (length=10)
public 'lat' => string '46.0675664' (length=10)
public 'lon' => string '11.1217998' (length=10)
public 'display_name' => string 'Piazza Duomo, Piazza del Duomo, centro storico Trento, Trento, TN, TAA, 38122, Italia' (length=85)
public 'class' => string 'highway' (length=7)
public 'type' => string 'bus_stop' (length=8)
public 'importance' => float 0.311
public 'icon' => string 'http://nominatim.openstreetmap.org/images/mapicons/transport_bus_stop2.p.20.png' (length=79)
public 'address' =>
object(stdClass)[2]
public 'bus_stop' => string 'Piazza Duomo' (length=12)
public 'pedestrian' => string 'Piazza del Duomo' (length=16)
public 'suburb' => string 'centro storico Trento' (length=21)
public 'city' => string 'Trento' (length=6)
public 'county' => string 'TN' (length=2)
public 'state' => string 'TAA' (length=3)
public 'postcode' => string '38122' (length=5)
public 'country' => string 'Italia' (length=6)
public 'country_code' => string 'it' (length=2)
public 'svg' => string 'cx="11.1217998" cy="-46.067566399999997"' (length=40)
In answer to your question, except for trying to output an array with the following statement
echo $jsonout[0];
Which will throw a Catchable fatal error: Object of class stdClass could not be converted to string
Everything is ok.
If this is about accessing the members of the json_decode return, see below
$jsonout is an array with one element,
that one element is an object, you can access its members like this
print $jsonout[0]->licence;
Which will output
Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright
If you'd like an associative array, you can pass the second argument for json_decode, like this
$jsonout = json_decode($html,true);
print $jsonout[0]['display_name'];
Which will decode the json into an associative array and will display in a similar way
Piazza Duomo, Piazza del Duomo, centro storico Trento, Trento, TN, TAA, 38122, Italia
please use print_r() in place of echo
$url = "http://nominatim.openstreetmap.org/search/Piazza%20Duomo%20Trento?format=json&addressdetails=1&limit=1&polygon_svg=1";
$html = file_get_contents($url);
$jsonout = json_decode($html);
print_r($jsonout[0]);
and you will get your result.
or you can print $jsonout[0]["license"]

Function changing and returning object's value even if it is 'passed by value'

I am in a situation where i am mapping an array into object and then assigning it to another array. Simply making an array of object out of nested array.
array (size=2)
0 =>
array (size=3)
'edu_id' => string '3' (length=1)
'edu_degree' => string 'MCA' (length=3)
'edu_institute' => string 'ECB' (length=3)
1 =>
array (size=3)
'edu_id' => string '4' (length=1)
'edu_degree' => string 'BCA' (length=3)
'edu_institute' => string 'CET' (length=3)
This is the array and i am trying to convert it into this -
array (size=2)
0 =>
object(MatEducation)[11]
private 'id' => int 1
private 'eduId' => string '3' (length=1)
private 'degree' => string 'MCA' (length=3)
private 'institute' => string 'ECB' (length=3)
1 =>
object(MatEducation)[11]
private 'id' => int 1
private 'eduId' => string '4' (length=1)
private 'degree' => string 'BCA' (length=3)
private 'institute' => string 'CET' (length=3)
Here is the mapper function.
/**
* #param MatEducation $obj - i am passing this object so that
* function dont need to create 'new' object every time.if i create
* a new object then i get the desired result.
* #param array $arr this array contain the value to be converted.
* #return MatEducation
*/
public function toMatEducation(MatEducation $obj, array $arr)
{
$obj->setEduId($arr['edu_id']);
$obj->setDegree($arr['edu_degree']);
$obj->setInstitute($arr['edu_institute']);
return $obj;
}
And a call to mapper function is like -
/**return array of MatEducation Objects.*/
$arrayOfObject = array();
foreach ($result as $key=>$row) {
$arrayOfObject[$key] = $this->map->toMatEducation($education, $result[$key]);
}
return $arrayOfObject;
Since by default all the values are passed are 'pass by value' thus the $education object must not change and should return a copy of it from function. If its still changing than at the time of assignment to $arrayOfObject[$key] a new copy should be generated. So my question is why all the index of $arrayOfObject are pointing to same object.?
EDIT this is the array what i am getting now.
array (size=2)
0 =>
object(MatEducation)[11]
private 'id' => int 1
private 'eduId' => string '4' (length=1)
private 'degree' => string 'BCA' (length=3)
private 'institute' => string 'CET' (length=3)
1 =>
object(MatEducation)[11]
private 'id' => int 1
private 'eduId' => string '4' (length=1)
private 'degree' => string 'BCA' (length=3)
private 'institute' => string 'CET' (length=3)
Objects themselves are passed by value, but their properties aren't.
$a = new stdclass;
$a->p = 0;
$b = $a;
$b->p = 1;
$a->p would be changed into 0. If you change $b now, it would not affect $a itself, but changing the properties of $b would affect the properties of $a. Although they are not the same variable, they reference to the same object.
Note: That's not true to arrays though - two variables that are not by reference would not reference to the same array. For example, $a = [0]; $b = $a; $b[0] = 1; would not change the value of $a[0] unless it was $b =& $a, but this is not true for objects.
A simple solution to your case is to use clone. In your example, if you used toMatEducation(clone $education, ...) instead, it would work.

Retrieving view data in a view composer

If I do the following in this view composer:
View::composer('product.edit', function($view)
{
$viewdata = $view->getData();
dd($viewdata);
});
I can see in the output that exists 'language_id', however I don't know how to retrieve it, since $viewdata['language_id'] will throw an exception.
How should I go about this?
Update:
The accepted answer led me to discover that when a presenter is involved in this operation, the model will be available in the offset, here is the final code:
View::composer('product.edit', function($view)
{
$data = $view->offsetGet('product')->toArray();
echo $data['language_id'];
exit;
});
You may try this:
$language_id = $view->offsetGet('language_id');
Following public methods are available in the $view object (An instance of Illuminate\View\View)
0 => string '__construct' (length=11)
1 => string 'render' (length=6)
2 => string 'renderSections' (length=14)
3 => string 'with' (length=4)
4 => string 'nest' (length=4)
5 => string 'withErrors' (length=10)
6 => string 'getEnvironment' (length=14)
7 => string 'getEngine' (length=9)
8 => string 'getName' (length=7)
9 => string 'getData' (length=7)
10 => string 'getPath' (length=7)
11 => string 'setPath' (length=7)
12 => string 'offsetExists' (length=12)
13 => string 'offsetGet' (length=9)
14 => string 'offsetSet' (length=9)
15 => string 'offsetUnset' (length=11)
16 => string '__get' (length=5)
17 => string '__set' (length=5)
18 => string '__isset' (length=7)
19 => string '__unset' (length=7)
20 => string '__call' (length=6)
21 => string '__toString' (length=10)
You may also try something like this:
if($view->offsetExists('language_id')) {
$language_id = $view->offsetGet('language_id');
}
Worth noting you can also access view data using the attribute syntax (at least starting Laravel 8):
$languageId = $view->product->language_id ?? null;

PHP SimpleXMLElement: Count isn't counting all public properties of the Object

I have the following code:
$b = $br->b;
var_dump($b);
$iCountBlock = count($b);
Where b is a SimpleXMLElement object. The var dump outputs:
object(SimpleXMLElement)[16]
public 'blockID' => string '160999' (length=6)
public 'blockDesc' => string 'Description' (length=37)
public 'moduleID' => string '1' (length=1)
public 'pubID' =>
object(SimpleXMLElement)[18]
public 'contentID' => string '93305' (length=5)
public 'linkToPageID' =>
object(SimpleXMLElement)[19]
public 'moduleFunction' => string 'replaceHTML' (length=11)
public 'moduleVars' =>
object(SimpleXMLElement)[20]
public 'c' =>
object(SimpleXMLElement)[21]
public 'contentID' => string '93305' (length=5)
public 'contentType' => string '1' (length=1)
public 'description' => string 'new.usdish.com index redesign content' (length=37)
public 'content' =>
object(SimpleXMLElement)[22]
However, $iCountBlock gets set to 1... it doesn't appear to be counting all the public properties of the object as it should. I also tried using a foreach loop to loop over each property of b and it didn't even enter the loop.
foreach($b as $key => $val) { ... }
I'm kinda at a loss here, as I'm not sure what's going on. Any thoughts?
Form PHP 5.3 and higher SimpleXMLElement does use a count function for the length!
$count = $b->count();
In PHP before 5.3 you have to use the childern property for getting the count.
$count = count($b->children());
Info at: http://php.net/manual/en/simplexmlelement.count.php

How do I check an objects property types?

Sorry for the title, I couldn't find a better way to write it =/
I am receiving a error object called ErrorBase.
If there is only one error it will return me the following:
public 'ErrorBase' =>
public 'CODIGO_ERRO' => string '1' (length=1)
public 'MENSAGEM_ERRO' => string 'Autenticação Inválida' (length=24)
public 'TIPO_ERRO' => string 'Usuario' (length=7)
But if there is more than one error, it will return me a array of objects like this:
public 'ErrorBase' =>
array
0 =>
object(stdClass)[30]
public 'CODIGO_ERRO' => string '1' (length=1)
public 'MENSAGEM_ERRO' => string 'Autenticação Inválida' (length=24)
public 'TIPO_ERRO' => string 'Usuario' (length=7)
1 =>
object(stdClass)[31]
public 'CODIGO_ERRO' => string '002' (length=3)
public 'MENSAGEM_ERRO' => string 'teste 002' (length=9)
public 'TIPO_ERRO' => string 'tipo 002' (length=8)
2 =>
object(stdClass)[32]
public 'CODIGO_ERRO' => string '003' (length=3)
public 'MENSAGEM_ERRO' => string 'teste 003' (length=9)
public 'TIPO_ERRO' => string 'tipo 003' (length=8)
3 =>
object(stdClass)[33]
public 'CODIGO_ERRO' => string '004' (length=3)
public 'MENSAGEM_ERRO' => string 'teste 004' (length=9)
public 'TIPO_ERRO' => string 'tipo 004' (length=8)
How can I work with these situations?
How do I check if there is a array of objects or only a object?
Thanks in advance for any help.
Try... is_object() and is_array()
is_array($variable) returns true if $variable contains an array, and false otherwise.
Use is_array() :
if (is_array($this->ERROR_BASE))
To test the class of an object :
if ($var instanceof ErrorBase) {
To test if it is an array :
if (is_array($var)) {
use gettype() to returns the vars type.
or use is_array/is_object to test for each

Categories