I know PHP is not an OO language, however its simplicity has attracted me to building web applications using it. I am a strong believer in Object designs for modular coding and am trying to work with PHPs restrictions. However I believe I have hit a snag. When an object is associated with another object, it apparently becomes associated with a copy of that object, not the object itself. This becomes impossible to deal with cyclical references.
Example
class Organization{
var $Members;
class Members{
var $Organization;
}
$phpDevelopers = new Organization();
$joe = new Member();
$phpDevelopers->Members['Joe'] = $joe;
$joe->Organization = $phpDevelopers;
$mary = new Member();
$phpDevelopers->Members['Mary'] = $mary;
$mary->Organization = $phpDevelopers;
$sue = new Member();
$phpDevelopers->Members['Sue'] = $sue;
$sue->Organization = $phpDevelopers;
if I ask Joe, what other people are members of his organization, he would say nobody. Mary would say Joe, and Sue would be the only correct answer of Joe and Mary.
Am I correct in my assumption of the association being to a copy and is there a way around this?
Object Associations
Moderator: General Moderators
-
IlyaNemihin
- Forum Newbie
- Posts: 6
- Joined: Mon Jan 19, 2004 5:35 am
User &$variable to pass reference.
See example:
Note, that when we add member to the organization we set reference to the organization.
Regards,
Ilya
See example:
Code: Select all
<?php
// example of OOP of PHP
class Organization{
var $_members;
var $_name;
function Organization( $name ){
$this->_name = $name;
}
function addMember( &$member ){
$member->setOrganization( &$this );
$this->_membersї$member->getName()] = &$member;
}
function getMemberNames(){
// return array of members
return array_keys( $this->_members );
}
function getName(){
return $this->_name;
}
}
class Member{
var $organization;
var $_name;
function Member( $name ){
$this->_name = $name;
}
function getName(){
return $this->_name;
}
function setOrganization( &$organization ){
$this->organization = &$organization;
}
}
$phpDevelopers = new Organization( 'phpDevelopers' );
$joe = new Member( 'joe' );
$phpDevelopers->addMember( &$joe );
$mary = new Member( 'mary' );
$phpDevelopers->addMember( &$mary );
$sue = new Member( 'sue' );
$phpDevelopers->addMember( &$sue );
// test
print 'Name: '.$joe->getName()."\n";
print 'Organizarion: '.$joe->organization->getName()."\n";
print 'Members: '.join( ', ', $joe->organization->getMemberNames() )."\n";
print "\n";
print 'Name: '.$mary->getName()."\n";
print 'Organizarion: '.$mary->organization->getName()."\n";
print 'Members: '.join( ', ', $mary->organization->getMemberNames() )."\n";
print "\n";
?>Regards,
Ilya
From eclipse readme:
Incidentally, this is how you would define an interface template in php:
OOP works very well in php no matter what some people say. Take a look at http://www.phppatterns.com.- To get Java-like object behavior, ALWAYS use references when:
- Creating objects : $object =& new Object;
- Passing objects : function receiveObject(&$object) { //... }
- Returning objects: function &returnObject() { return $object; }
PHP's default behavior is to create copies, which is almost always NOT what
you really want. When some object contains a reference to a second object
and you create a copy of the first object instead of a reference, this copy
will NOT share the reference to the second object, but will hold a copy of
that object instead. This can (and will) lead to strange and undesired
behavior. To summarize:
function &getNiftyComputationResult(&$iterator))
{
$result =& new NiftyComputationResult;
for ($iterator->reset(); $iterator->isValid(); $it->next())
{
$result->add($iterator->getCurrent());
}
return $result;
}
$it =& new ArrayIterator(array(8, 5, 3, 9, 6, 1, 7, 4, 2));
$result =& getNiftyComputationResult($it);
It takes a while to get used to, but it is truly the only way to correctly
handle objects in PHP 4 ('correctly' meaning 'Java-like' in this context).
Incidentally, this is how you would define an interface template in php:
Code: Select all
<?php
class Thing
{
function foo()
{
die('Method not implemented<br />.' . __LINE__ . ' | ' . __FILE__);
}
function bar()
{
die('Method not implemented<br />.' . __LINE__ . ' | ' . __FILE__);
}
}
?>
Last edited by McGruff on Tue Aug 09, 2005 7:57 pm, edited 2 times in total.
- phppeanuts
- Forum Newbie
- Posts: 6
- Joined: Mon May 24, 2004 6:36 pm
- Location: Netherlands
- phppeanuts
- Forum Newbie
- Posts: 6
- Joined: Mon May 24, 2004 6:36 pm
- Location: Netherlands
Hi McGruff,
At first sight is seems kind of overkill to me to create a class just to replace those two or three (with reset()) lines of code. But maybe there is some magic to it i am ignorant about, so i took a look at phpClasses.org (i found a reference to this thread on their forum) and found a class
Iterator. It has a function pos() method but it does NOT return a reference. Same for the at($index) method.
Maybe i am biased by my Smalltalk & XP background, but foreach just seems to be "the simpelest thing that could possibly work" for simply iterating - except it does not work properly with objects in php4
.
Greetings,
Henk,
http://www.phpPeanuts.org.
At first sight is seems kind of overkill to me to create a class just to replace those two or three (with reset()) lines of code. But maybe there is some magic to it i am ignorant about, so i took a look at phpClasses.org (i found a reference to this thread on their forum) and found a class
Iterator. It has a function pos() method but it does NOT return a reference. Same for the at($index) method.
Maybe i am biased by my Smalltalk & XP background, but foreach just seems to be "the simpelest thing that could possibly work" for simply iterating - except it does not work properly with objects in php4
Greetings,
Henk,
http://www.phpPeanuts.org.
I wouldn't replace foreach with an iterator for every single loop but often a piece of code can be made more generic by using an iterator. The std example is a Table decorator which can take any kind of collection as an arg - QueryIterator, ArrayIterator, etc and prints a table. Implementation hiding is the magic.
The iterator class in your link looked a bit unfocussed although I didn't spend much time looking at it. Eclipse is what I'd recommend (returns a ref).
There is also a phppatterns take on the iterator interface. Jason's thoughts here. As you maybe know, iterators have now been added to php5.
The iterator class in your link looked a bit unfocussed although I didn't spend much time looking at it. Eclipse is what I'd recommend (returns a ref).
There is also a phppatterns take on the iterator interface. Jason's thoughts here. As you maybe know, iterators have now been added to php5.
PS: forgot to mention you can use foreach to iterate through a list of objects whilst maintaining references (php4):
Code: Select all
<?php
/*
CLASS Foo
*/
class Foo
{
var $state = 'ugly duckling';
function change()
{
$this->state= 'beautiful swan';
}
function getState()
{
return $this->state;
}
}
///////////////
// END CLASS //
///////////////
$foo =& new Foo;
$array = array();
$array[] =& $foo;
foreach($array as $ob)
{
$ob->change();
}
echo $foo->getState(); // ugly duckling - copied objects
$foo =& new Foo;
$array = array();
$array[] =& $foo;
foreach(array_keys($array) as $key)
{
$array[$key]->change();
}
echo $foo->getState(); // beautiful swan - object wasn't copied
?>