Solved

non static property array being populated

Posted on 2014-01-18
17
191 Views
Last Modified: 2014-02-20
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28340946.html#a39789958

can you show me a class that can hold an array which adds values from different objects
0
Comment
Question by:rgb192
  • 7
  • 4
  • 4
  • +1
17 Comments
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39791535
The word "static" seems to have many meanings in PHP.  There is a procedural meaning associated with variables that hold their values across multiple function calls.  And there are the two OOP meanings.  Hopefully these links will disambiguate:
http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static
http://php.net/manual/en/language.oop5.static.php
http://php.net/manual/en/language.oop5.late-static-bindings.php
0
 

Author Comment

by:rgb192
ID: 39809309
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28340946.html#a39789958

How can

line 28 $this->_employees[] = $e;

be able to hold values from multiple instances.


and could you show me a similar example please.
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39809338
See code below.  There are two classes defined here - Department and Employee.  In the Department class, line 13, part of the constructor that is run at the time a Department object is created from this class, says this:

$this->_employees = array();

And that statement creates an empty array in the object property named _employees.

The standard PHP notation to add a data element to the end of an array is to use the paired square brackets without any array key inside them.  Look for "creating/modifying with square bracket" on this page:
http://php.net/manual/en/language.types.array.php

Once the constructor has been run, the _employees array exists, but is empty.  It follows that we might want to add some employees using the addEmployee() method.  When we run that code, we find this statement on line 16:

$this->_employees[] = $e;

That takes the $e variable and attaches it to the end of the _employees array.  Each time we call the addEmployee() method we get one more employee added to the array.

/* Class Department.
 *  The class contains two attribute: name and employees[].
 *  The class contains two methods: 
 *  - __construct()
 *  - addEmployee()
 */
class Department 
{
    private $_name;
    private $_employees;
    function __construct($name) {
        $this->_name = $name;
        $this->_employees = array();
    }
    function addEmployee(Employee $e) {
        $this->_employees[] = $e;
        echo "<p>{$e->getName()} has been added to the {$this->_name} department.</p>";
    }
} // End of Department class.

/* Class Employee.
 *  The class contains one attribute: name.
 *  The class contains two methods: 
 *  - __construct()
 *  - getName()
 */
class Employee
{
    private $_name;
    function __construct($name) {
        $this->_name = $name;
    }
    function getName() {
        return $this->_name;
    }
} // End of Employee class.

Open in new window

0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39809376
I think I misunderstood the wording of the question. I think you -might- be asking how an array works with an object. If I understand correctly, then the answer is the difference between "references" and "values".

When you define a new object like this:

$x = new Employee();

...you are doing two things. You are creating a new Employee object, which PHP holds in its memory. Internally, PHP might simply see it as object #4 or something like that.

You are also creating a variable $x, which is ACTUALLY just a reference to object #4. So $x isn't the actual object itself, it's just the very first reference to object #4.

If you were to then say:

$y = $x;

...then you are creating another reference. PHP sees this and says, "Okay, now $y and $x both point to object #4 that I'm holding in memory."

Now let's say you have an array, and you do this:

$z = new array();
$z[] = $x;

...now PHP has THREE different references to object #4.

So when it comes to objects, PHP isn't copying objects over and over again in memory. You don't have three separate copies of the Employee object. You have one object and three pointers to it.

When you make changes to the object using ANY of the pointers, PHP makes those changes to the object itself.

$x->Foo = "abc";
echo $y; // Will show "abc"
$y->Foo = "def";
echo $x; // Will show "def"
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39809454
0
 

Author Comment

by:rgb192
ID: 39809645
I am understanding better but have more questions.


http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28342292.html#a39809338

how could you instantiate different objects in this example to use the same employee[] array?

gr8gonzo:
I do not understand how different objects can reference object#1

and what would the class be that holds class->foo property
$x->Foo = "abc";
echo $y; // Will show "abc"
$y->Foo = "def";
echo $x; // Will show "def"
0
 
LVL 108

Assisted Solution

by:Ray Paseur
Ray Paseur earned 100 total points
ID: 39809939
do not understand how different objects can reference object#1
This is just a question of terminology.  It's not different objects, but different pointers.  This is a change in the way PHP works, different from procedural (old) PHP and object-oriented (new) PHP.

In old PHP every assignment statement (assignments are made with the equal sign) copied the variable value.  In new PHP, assignment statements that assign an object do not copy the object, they only create a new variable that is a pointer to the object.  If you want a net-new copy of the original object, you instantiate it with the keyword "new" and if you want a copy of an object after instantiation (and possibly modification) you "clone" the object.

Please read the article about variables and references, and ask questions from what you find there.
0
 
LVL 33

Expert Comment

by:Slick812
ID: 39813007
greetings rgb192, , you have not given me very clear or understandable descriptions for what you are after as your result for the code you say you need an example for? ?
I will talk some about what I will guess is the information you may be needing?
For me If I need to "Share" info-data between EVERY object of a Class , I will declare a STATIC property (array in this case) in that Class code. . .

as in the PHP manual -
class Employee {
public static $my_array = array('Foo');

    public function showMy_Array($key) {
        return self::$my_array[$key];
    }
}

BUT you give this condition, which seems confusing to me -
"non static property array being populated"
You also add this - "how could you instantiate different objects in this example to use the same employee[] array?"

Although I kind of think that I understand this last statement of yours, it is not real clear, BECAUSE the - employee[] array - can not be a property of the Object (instance) as in the the class cpde -
$this->_employees = array();
and be shared among ALL of the Class Objects (instances), in the "Usual" Cl;ass code, this _employees property would be a STATIC to be shared among ALL of the Class Objects (instances). . . but for some reason you do not want this.

However, using an Array created OUTSIDE of the Class code, and then Passing that into each new instance by "REFERENCE" will let you do as you have requested, however, this is not really so much a "Class" learning thing, but more of a PHP learning thing, (my view).
     PHP code below
class Department {
protected $_name = '', $_employees = array();

// IMPORTANT, added the $Emp_Array as reference with &
function __construct($name, &$Emp_Array) {
    $this->_name = $name;
    $this->_employees = &$Emp_Array;// add as reference to $this->_employees
    }

function addEmployee(Employee $e) {
// PLEASE NOTICE, here the $this->_employees[] referes to an ARRAY OUTSIDE of any class! !
    $this->_employees[] = $e;
    echo "<p>{$e->getName()} has been added to the {$this->_name} department.</p>";
    }

function listAllEmployees( ) {
// ADDED this function to show you that the $this->_employees is "Shared"
    if (count($this->_employees) < 1) {
        echo 'NO EMPLOYEES IN LIST!<br />';
        return;
        }
    $cnt = count($this->_employees);
    echo 'There are ',$cnt,' Employess in ALL Departments by Names below<br />';
    for($i=0; $i < $cnt; ++$i) {
        echo $this->_employees[$i]->getName(),'<br />';
        }
	}
} // end of Class Department
	
class Employee {
protected $_name = '';

function __construct($name) {
        $this->_name = $name;
    }
    function getName() {
       return $this->_name;
    }
} // End of Employee class.

// // // // // // // END OF CLASS CODE

// first create a normal php array to be shared
$empArray0 = array();
// create several Employee objects
$em1 = new Employee('Start Name HR');
$em2 = new Employee('Name for Second HR');
$em3 = new Employee('Third Employee SL');
$em4 = new Employee('Forth Name SL');

// create two Departments -
$HRdpart = new Department('Human Resources', $empArray0);
$SLdpart = new Department('Sales', $empArray0);
// ADD two employees to each department
$HRdpart->addEmployee($em1);
$HRdpart->addEmployee($em2);
// to Sales
$SLdpart->addEmployee($em3);
$SLdpart->addEmployee($em4);

//list ALL employees in ALL depatrments
$HRdpart->listAllEmployees(); // will show FOUR employees, NOT two

Open in new window

I ran this code on my server and it worked, however this is a VERY poor Class code, for what you say you want, it does NOT have any way to list only the employees in ONE department, there could be changes to code to list just one department employ or ALL employ.
Even though this code works, I would NEVER USE IT! ! BECAUSE it is terrible at Encapsulation for Class properties , , as the  $empArray0  array is outside of any class, I would do with the Class STATIC array property, as this is what the class "static" property was designed to do, to Share values between instances.
ask questions if you need other factors.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39815199
gr8gonzo:
I do not understand how different objects can reference object#1

Okay, so let's try some visuals. First, let's say that we have this code:

<?php

// First, a class definition with some default values.
class Foo
{
  public $some_integer = 12345;
  public $some_string = "abc";
  public $some_foo;
}

// Create a few things in memory:
// 1. Object #1, an instance of Foo
// 2. The Values #1 and #2, which are the defaults for Foo.
// 3. The pointer named $a.

$a = new Foo();

// Now create another pointer to object #1.
$b = $a;

// And now let's create another one, this time in an array.
$array = array();
$array["myobject"] = $b; // $a would also work instead of $b

// NOTE: My diagram doesn't break down the array structure, but ultimately, the key of an array is also a pointer.

// Now create another object, Object #2. It also creates the default values and the pointer variable called $c.
$c = new Foo();

// Now make object #1 reference object #2, since the properties of an object, like $some_foo, are also pointers.
$a->some_foo = $c;

// All SIMPLE values like strings and integers are never passed by reference. So if you try to do $var1 = $var2, then you are COPYING the value.

// Create Value #5
$d = 12345;

// Create Value #6
$e = $d;
?>

Open in new window


Now check out the attached diagram. The blue shapes with rounded corners are pointers, while the grey squares are actual values in memory.

If you're still at a loss, think about this. You, me, Ray, and Slick are all updating the same question on Experts Exchange. The content of the question and the comments are not stored on our computers. The content is all stored in one location on Experts Exchange.

When we want to make an update to this question, we each follow our OWN browser bookmarks (or links in our OWN email). While your bookmark is different than my email link, they both take us to the same question on Experts Exchange. We each have different pointers that take us to the same value.

Questions and comments (the "values") can also point to other questions. For example, in your original question, you have a link to:

http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28340946.html#a39789958

You didn't copy the contents of THAT question into THIS question. Instead, you chose to simply add the URL to point to that other question. That's the same way objects referencing objects works. The content of an object can easily point to a value or to another object.
php-references-vs-values.jpg
0
 

Author Comment

by:rgb192
ID: 39846345
gr8gonzo
php-references-vs values jpg , foo() (object, array, properties)

and ray
 It's not different objects, but different pointers.

and slick
adding employee to department



Here is my question:

so there is a reference to the value

and if the value changes then so does the reference


I thought if the value was an array then new elements could be added to the array and the value would contain more data

but without a reference then no one knows the value is growing in size
(if a tree falls in a forest and no one is there to hear, does tree still make a sound?)
0
 
LVL 34

Accepted Solution

by:
gr8gonzo earned 300 total points
ID: 39847898
A reference doesn't change. A reference is simply a sign that PHP can read to figure out where the value is. The city of New York changes all the time, but a map of the United States will keep showing New York in the same location.

A reference either exists or it doesn't. When you unset() a variable, you are destroying a reference.

A value will only exist in memory as long as there is at least one reference. When the last reference is destroyed, then the value is destroyed, too. Anytime you unset() a reference, imagine PHP saying, "Hey, does anyone still need the value of this? If not, I'll throw it out." If no other references exist, PHP says, "Okay, nobody said anything, so I'm throwing it out."

// Create the Employee named John Smith with one reference.
$x = new Employee("John Smith");

// Add another reference to John Smith (the value that $x points to).
$y = $x;

// Remove $x's reference.
unset($x);

// At this point, John Smith still is in memory, because $y is still referencing it.

// Remove $y's reference
unset($y);

// Now PHP cleans up and completely removes John Smith from memory.

Open in new window


The same applies for any value and reference. ANY value that does not have a reference is destroyed / cleaned up. It doesn't matter whether it's an object or an array or a string or whatever.

An array element is just another reference, so in the above code, you could have $myarray["y"] = $x;
...and it would be the same thing as $y = $x.

If you unset $myarray, it destroys the array and all of its elements, too.

When it all comes down, the MAIN principle to understand is:
A value only exists when it has at LEAST one reference.

Without a reference, you cannot access a value to change it (so you couldn't access an array to add values to it). If you can access a value in ANY way, that means it has a reference.

So in PHP, a tree will never fall in the forest if nobody is there to hear it. Someone has to be there to chop down the tree or plant a new one. As soon as EVERYONE leaves the forest, PHP burns the forest to the ground.

(Very minor exception - you -can- create situations that have memory leaks, but it's usually difficult to do.)
0
 
LVL 33

Assisted Solution

by:Slick812
Slick812 earned 100 total points
ID: 39848026
rgb192, , you say this is your "Question" =
      so there is a "reference to the value", and if the value changes then so does the reference, , , and I thought "if the value was an array", then new elements could be added to the array and the value would contain more data, but without a reference, then no one knows the value is growing in size.

I have read this several times, and the way you state this, has no meaning to me, I do not say that in "Code work", this has no meaning, but in the "english language" , this has no meaning.

In this part of your question -
"if the value was an array, then new elements could be added to the array and the value would contain more data"
You are Correct in this part! !

But you then say -
      "but without a reference, then no one knows the value is growing in size"
According to you this whole thing starts with a "reference", so it is not possible to have "but without a reference"
anyway, this part of your statement can NEVER BE TRUE -
    "then no one knows the value is growing in size"
so your question makes no sense to me.

In PHP code work if there is a Variable, then you or anyone can get the "Value" of that variable at any time after that variable has been declared, with or without a reference to that variable, whether the variable is an array or not. So I can not understand you here.
Please , in your original question you ask -
    "can you show me a class that can hold an array which adds values from different objects"

can you tell us how we have failed to "show you this", ,  after all of the talk here about Classes, references, pointers, and static , sorry for my ignorance, I am not clear about what to say to help you with this question? You seem to be going in a circle, asking about things "the elements array" that we can not know what you mean.
0
 

Author Closing Comment

by:rgb192
ID: 39872409
thanks all

A reference either exists or it doesn't. When you unset() a variable, you are destroying a reference.

A value will only exist in memory as long as there is at least one reference. When the last reference is destroyed, then the value is destroyed, too.
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39873247
When the last reference is destroyed, then the value is destroyed, too.
That would seem to be correct, but I have not gone into the Zend internals to see if it's actually true.  It might be interesting to test that theory with memory_get_usage() and see if the "destroyed" value amounts to returning the memory or simply making the value unavailable to the PHP script.  This smells like something that could give us a memory leak ;-)
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39873310
Memory leak occurs but it is very modest.

<?php // demo/memory_get_usage.php

/**
 * Question: After an object is created and some pointers to it are created (and
 * maybe some other stuff) and then the pointers are all unset(), does PHP actually
 * remove the object and return the memory?  Or can this create a memory leak?
 *
 * http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28342292.html#a39873247
 * http://www.php.net/manual/en/function.memory-get-usage.php
 */
error_reporting(E_ALL);

Class FatObject
{
    public function __construct() { }
    public function bloat($n = 0)
    {
        while ($n > 0)
        {
            $this->array[] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            $n--;
        }
    }
}

$old = memory_get_usage();
$x   = new FatObject;
$x->bloat(5000);
$new = memory_get_usage();
$y   = clone($x);
$y->bloat(1);
$cln = memory_get_usage();
unset($x);
$aft = memory_get_usage();
unset($y);
$fin = memory_get_usage();

echo PHP_EOL;
echo "<br>BEFORE BLOAT: $old, AFTER BLOAT: $new, AFTER CLONE: $cln";
echo "<br>AFTER FIRST UNSET(): $aft, AFTER SECOND UNSET(): $fin";

Open in new window

0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 39873767
Ray, a couple of notes:

1. You have variables containing the memory usage amounts, so those will also account towards overall memory consumption.

2. PHP allocates more memory than it needs to store values, so it grabs memory space in chunks. When it releases values, it may not completely release all of the memory allocated, but it doesn't mean there's a leak. It just means it will try to reuse that same block if it can. So memory_get_usage() without a parameter will show you the "estimate" of memory usage.

memory_get_usage(true) will show you the physical allocation of memory usage, but it's also misleading sometimes. For example, if you create, bloat, and unset $x, you'll see that memory_get_usage(true) will show you a 100% physical return on memory, but likely between 8 - 64 bytes of "leak" on memory_get_usage(). If you clone $x to $y and then unset them both, the "true" version will show that it didn't release $y, but the no-parameter version will show the released memory. So it's one of those things where you just have to juggle two different memory analysis calls to get an accurate picture of what's happening to memory.
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39873806
That makes sense.  

There's a little bit more going on under the covers, too.  Try the script as written, then remove line 31 and run it again.  It almost looks like the clone is "put in the queue" but not actually accomplished until there's a mutating reference to the cloned object.  In a way that makes sense, too.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

This article will explain how to display the first page of your Microsoft Word documents (e.g. .doc, .docx, etc...) as images in a web page programatically. I have scoured the web on a way to do this unsuccessfully. The goal is to produce something …
Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now