Suppose I have an array of a objects of user defined class. Wanted to know how do I extract the elements of the array in PHP.
// class definition
class User
{
public $fname;
public $lname;
}
// array of objects of the class defined above
$objUser1 = new User():
$objUser2 = new User():
$objUser3 = new User():
$objUser4 = new User():
$alUser = array();
$alUser[] = $objUser1;
$alUser[] = $objUser2;
$alUser[] = $objUser3;
$alUser[] = $objUser4;
// trying to iterate and extract values using typcasting - this does not work, what is the alternative.
foreach($alUser as $user)
{
$obj = (User) $user; // gives error - unexpected $user;
}
Thats how I used to do in java while extracting objects from the Java ArrayList, hence thought the PHP way might be similar. Can anyone explain it.
foreach ($alUser as $user) {
$obj = $user;
}
Why do you need typecasting for this?
PHP is a dynamically typed language. There is no need to cast in most cases.
It is impossible to cast to a User: see PHP's documentation on type juggling and casting.
This example would print "$user is a object (User)" four times.
foreach($alUser as $user) {
echo '$user is a ' . get_type($user);
if(is_object($user)) {
echo ' (' . get_class($user) . ')';
echo "\n";
}
It would be nice for example Eclipse PDT to determine the type of object for Code Completion. otherwise you are stuck backtracing, where the array was created and what objects were put into it and then look at the class file to see what functions are available (or temp create a new theObject() to see what methods/properties are available if you know what type of object it is. other times may not be as easy if many objects call functions that create those arrays and objects in them, so have to backtrace to see how those arrays made). Heard a few other IDE's may be able to determine type better like phpEd possibly?
Related
How to retrieve value from a complicated object structure in php? I know using '->' operator we can access the value but I am very confused in the object I am returned with. From the object returned, I want to fetch the character value. How do i do that?
I am using Neo4jPHP and trying to execute a cypher query "MATCH (n) RETURN distinct keys(n)" to return all distinct property keys. After doing a var_dump of the row object, the partial output is shown below.
Edit:- My edited code after following Mikkel's advice:-
$keyquery="MATCH (n) RETURN distinct keys(n)";
$querykey=new Everyman\Neo4j\Cypher\Query($client, $keyquery);
$resultkey = $querykey->getResultSet();
foreach ($resultkey as $row)
{
for($i=0;$i<count($row[0]);$i++)
{
echo $row[0][$i]; // returns all the property keys from the Row object
}
}
You can't access the object property directly as it was declared as protected (only accessible from within the class or an inheriting class).
However, in such a case, the developer has usually added an object method or overloading function that allows you to access the information you're looking for. Taking a peek at the source, it looks like you should be able to access the data you're looking for using either:
// this works because the class implements Iterator
foreach ($myobject as $row) {
echo $row['keys(n)']; // outputs "character"
}
or:
// this works because the class implements ArrayAccess
// don't ask me why they put keys and values in different arrays ('columns' and 'raw')
echo $myobject[0]['keys(n)']; // outputs "character"
If you look the class Row you will find out that you can access it treating the object like an array.
$character = $myRow[0];
Looking at the object you dumped here, you can see that the object is implementing \Iterator, \Countable, \ArrayAccess, which means you can basically treat it like an array. The underlying data source is the protected $raw.
$queryResult = ...;
foreach ($queryResult as $row) {
echo $row['character'] . PHP_EOL;
}
The value you are looking for is protected and not accessible,
try find object class and add function to retrieve the value.
use regular expression to extract the portion, which is not recommended:
/\'character\'(length\=(.*?))/
Since objects are passed by reference by default now, is there maybe some special case when &$obj would make sense?
Objects use a different reference mechanism. &$object is more a reference of a reference. You can't really compare them both.
See Objects and references:
A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
&$object is something else than $object. I'll give you an example:
foreach ($objects as $object) {
if ($cond) {
$object = new Object(); // This won't affect $objects
}
}
foreach ($objects as &$object) {
if ($cond) {
$object = new Object(); // This will affect $objects
}
}
I won't answer the question if it makes sense, or if there is a need. These are opinion based questions. You can definitely live without the & reference on objects, as you could without objects at all. The existence of two mechanisms is a consequence of PHP's backward compatibility.
There are situations where you add & in front of function name, to return any value as a reference.
To call those function we need to add & in front of object.
If we add & in front of object, then it will return value as reference otherwise it will only return a copy of that variable.
class Fruit() {
protected $intOrderNum = 10;
public function &getOrderNum() {
return $this->intOrderNum;
}
}
class Fruitbox() {
public function TestFruit() {
$objFruit = new Fruit();
echo "Check fruit order num : " . $objFruit->getOrderNum(); // 10
$intOrderNumber = $objFruit->getOrderNum();
$intOrderNumber++;
echo "Check fruit order num : " . $objFruit->getOrderNum(); // 10
$intOrderNumber = &$objFruit->getOrderNum();
$intOrderNumber++;
echo "Check fruit order num : " . $objFruit->getOrderNum(); // 11
}
}
I've read up about PHP variable references but I'm not 100% and was hoping someone could help.
If I have a class like the following:
class Item
{
public $value;
}
I then have an array of those items in a variable - lets call that $items. All I did was new Item()...and $items[] = $newItem;.
Now, I want to populate another array but it filters the original array based on its value. So like the following:
foreach($items as $key => $value)
{
$filteredItems[] = &value;
}
Now, I have ANOTHER variable that iterates over that filtered list and does something like so:
$theItem = $filteredItems[10];
$theItem->value = 100;
Now this is where I'm confused. Do I need to set $theItem to &filteredItems[10]; (reference) or will it just know that the value in the array is a reference type and $theItem also becomes a reference to that same item? I'm after that last set of $theItem->value = 100; changes the very original object stored in the $items list.
In PHP 5 objects are always passed around by their "handle" for lack of better word. This means if you do this:
$a = new Item();
$a->value = 1;
$b = $a;
$b->value++;
echo $a->value;
The value of 2 is echoed. Why? Because the handle of the object is copied from $a to $b and they both point to the same object. This isn't a reference in terms of using &, but behaves similarly enough to the point that people generally call it the same thing... even though it's not.
So you do not need any use of references in your code. Usually in PHP, you never need to use references when using objects.
With respect to objects, you really only notice references if you do this (assign a new value to the variable itself):
function foo(Item &$a)
{
$a = null;
}
$b = new Item();
foo($b);
var_dump($b);
This results in NULL, which wouldn't happen without a reference. But again, this is not typical usage, so you can really forget about using references with objects.
(And of course the use of a function isn't necessary here to illustrate the point, but that's the most typical place you'll see them in the "real world.")
It's like this:
foreach($items as $key => &$value) {
$filteredItems[] = $value;
}
The point where you give the original instance into a different scope is where you put the &.
Same is for functions:
function myFunction(&$variable) { }
Example:
<?php
class test {
public $testVar;
public function __construct() {
$this->testVar = "1";
}
}
function changeByReference(&$obj) {
$obj->testVar = "2";
}
$instance = new test();
// Prints 1
echo $instance->testVar, PHP_EOL;
changeByReference($instance);
// Prints 2
echo $instance->testVar, PHP_EOL;
Read more about it here: http://php.net/manual/en/language.oop5.references.php
If you want to copy an instance, use clone - php.net/clone
The easiest way to get it is when you know the difference between these: class, object and instance. (I'd explain it more at this point but it would only confuse you more because my english is not accurate enough for now to explain the details enough.)
The main function of the example class uses the reusableFunction twice with different data and attempts to send that data to a different instance variable ($this->result1container and $this->result2container) in each case, but the data doesn't get into the instance variables.
I could get it to work by making reusableFunction into two different functions, one with array_push($this->result1container, $resultdata) and the other with array_push($this->result2container, $resultdata), but I am trying to find a solution that doesn't require me to duplicate the code.
My solution was to try to pass the name of the result container into the function, but no go. Does somebody know a way I could get this to work?
Example Code:
Class Example {
private $result1container = array();
private $result2container = array();
function __construct() {
;
}
function main($data1, $data2) {
$this->reusableFunction($data1, $this->result1container);
$this->reusableFunction($data2, $this->result2container);
}
function reusableFunction($data, $resultcontainer) {
$resultdata = $data + 17;
// PROBLEM HERE - $resultcontainer is apparently not equal to
// $this->result1container or $this->result2container when I
// try to pass them in through the parameter.
array_push($resultcontainer, $resultdata);
}
function getResults() {
return array(
"Container 1" => $this->result1container,
"Container 2" => $this->result2container);
}
}
(If this is a duplicate of a question, I apologize and will happily learn the answer from that question if somebody would be kind enough to point me there. My research didn't turn up any answers, but this might just be because I didn't know the right question to be searching for)
It looks to me like you want to be passing by reference:
function reusableFunction($data, &$resultcontainer) {
...
If you don't pass by reference with the & then you are just making a local copy of the variable inside reuseableFunction .
You are changing the copy, not the original. Alias the original Array by referenceDocs:
function reusableFunction($data, &$resultcontainer) {
# ^
And that should do the job. Alternatively, return the changed Array and assign it to the object member it belongs to (as for re-useability and to keep things apart if the real functionality is doing merely the push only).
Additionally
array_push($resultcontainer, $resultdata);
can be written as
$resultcontainer[] = $resultdata;
But that's just really FYI.
You may pass the attributes name as a String to the method like this:
function reusableFunction($data, $resultcontainer) {
$resultdata = $data + 17;
array_push($this->{$resultcontainer}, $resultdata);
}
//..somewhere else..
$this->reusableFunction($data, 'result2Container')
Some php experts wrote some texts about "why you shouldn't use byReference in php".
Another solution would be to define the containers as an array. Then you can pass an "key" to the method that is used to store the result in the array. Like this:
private $results = array();
function reusableFunction($data, $resIdx) {
$resultdata = $data + 17;
array_push($this->$results[$resIdx], $resultdata);
}
//..somewhere else..
$this->reusableFunction($data, 'result2Container');
//..or pass a number as index..
$this->reusableFunction($data, 1);
If I have code like this:
class Person {
$age;
$height;
$more_stuff_about_the_person;
function about() {
return /* Can I get the person's name? */;
}
}
$John = new Person();
$Peter = new Person();
print $John->about(); // Print "John".
print $Peter->about(); // Print "Peter".
Is it possible to print the person's name, stored as the variable name, from the method?
As it's not standard procedure, I'm guessing it's a bad idea.
I've looked it up and I can't find anything about it.
No. Objects can have multiple names, or no names. What would happen here:
$John = new Person();
$Richie = $John; // $John and $Richie now both refer to the same object.
print $Richie->about();
or here:
function f($person)
{
print $person->about();
}
f(new Person());
If the objects need to know their own names, then they need to explicitly store their names as member variables (like $age and $height).
Eje211, you're trying to use variables in very bizarre ways. Variables are simply data holders. Your application should never care about the name of the variables, but rather the values contained within them.
The standard way to accomplish this - as has been mentioned already, is to give the Person class a 'name' property.
Just to re-iterate, do not rely on variable names to determine the output/functionality of your application.
User defined variables names should be treated as totally transparent to the PHP compiler (or any compiler for that matter). The objects you create are just references to memory that point to the real object. Their name has no meaning. Name is a member of person.
You can, however, get the variables you want with get_defined_vars()
foreach (get_defined_vars() as $key => $val) {
if ($val instanceof Person) {
echo $key;
}
}
This should absolutely not be done, however, and the object would still need to know the order in which the variables were stored. No idea how you would calculate that.
This example might be helpful currently there is no method that tells you the object name you have to specify yourself like in the code below:
class Person {
public $age=0;
public $height=0;
public $objPerson='';
function about($objPerson,$age,$height) {
return
'Person Object Name: '.$objPerson.'<br>'.
'Age: '.$age.'<br>'.
'height: '.$height.'ft<br><hr>';
}
}
$John = new Person();
$Peter = new Person();
print $John->about('John',25,'5.5');
print $Peter->about('Peter',34,'6.0');