SitePoint Sponsor

User Tag List

Results 1 to 17 of 17
  1. #1
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,804
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)

    Getting an attribute from the perent object.

    I have a set of nested objects/classes. Essentially each object is a registry of its child classes, plus some unique attribute
    Code:
    Class A{
      public A_Attribute1= 'some value';  
      public A_Attribute2= 'some value';
      public GenAttribute= 'attribute general';
      protected content=array(); // all classB instances 
    } 
    Class B extends class A{
      public B_Attribute1= 'some value';  
      public B_Attribute2= 'some value';
      public GenAttribute= 'different attribute general';
      protected content=array(); // all classC instances 
    } 
    
    Class C extends class B{
      public C_Attribute1= 'some value';  
      public C_Attribute2= 'some value';
      public GenAttribute= 'Still different attribute general';
      protected content=array(); // all classD instances 
    } 
    
    Class D extends class C {
      public D_Attribute1= 'some value';  
      public D_Attribute2= 'some value';
      public GenAttribute= 'uniqu attribute general';
      protected content=array(); // some data  
    }
    Is there direct way to get attributes from the parent instance?

    $a=new a();
    and $a->content has 10 instances of class B, each of which have 5 or so instances of class C...

    from inside of one of the Class C objects, can you retrieve "B_Attribute2" of the parent object(instance) of the class B object that holds it?

  2. #2
    SitePoint Wizard wonshikee's Avatar
    Join Date
    Jan 2007
    Posts
    1,223
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    If they're public, they can be accessed from anywhere.

    Can you explain exactly where you need it?

  3. #3
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,804
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    Well what I meant was that i would like to be able to have a function to GET the value in the PARENT. :/

    so AS IF you could use function with $this->:: parent to get the value of the propierty 'B_Attribute2' of the INSTANCE of the object that holds it..

    Note I know that the :: parent can get a static property of a class parent, but what I am thinking of is more of a regular property within INSTANCE that contains an INSTANCE of a child class. I hope that makes my question clearer.

  4. #4
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    http://www.php.net/manual/en/keyword.parent.php

    FYI, your class/object design is pretty bad.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  5. #5
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,804
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    I fear my question is not being understood due to the fact that I dont know if what I am asking is even possible in OOP. Thats what I get for being lazy.

    Yes, you can access a class function or STATIC variable with :: parent. This I know. What I am trying to do is access a property of an INSTANCE that contain other instances from within one of the instances it contains. Think inception.


    This is a NON WORKING example of what I have been toying with
    PHP Code:

    class Root{
            public         
    $registry    =    array();
            protected    
    $births        =    'Level1';
            protected    
    $myName        =    'Root';
            function 
    addEl($name){
                
    $this->registry[$name]                =    new $this->births();
                
    $this->registry[$name]->myName        =    $name;
            }
            function     
    myNameIs(){
                echo 
    'I am ',self::getName(),'.<br>';
            }
            function 
    getName(){
                return 
    $this->myName;
            }
            protected function     
    getRegistry(){
                return 
    self::$registry
            }
    }
    class 
    Level1 extends Root{
            protected    
    $births        =    'Level2';
            function     
    hoosYaDaddy(){
                
    $dad    =      parent:: getName(); // this doesnt actually return waht I want as it just access getName() int the parent and uses  the curren object properties  as variables. 
                
    echo 'a child of ',$dad,'.<br>';
            }
            function 
    parentAccess(){
                
    $ret    =    parent::getRegistry();
                return     
    $ret ;
            }

    }
    class 
    Level2 extends Level1{
            protected            
    $births        =    'Level3';

    }
    class 
    Level3 extends Level2{
            function 
    addEl($name){
                
    $this->regsitry[$name]    =    'data';
            }

    }
    $b='Root';
    $a= new $b();
    $a->addEl('first');
    $a->addEl('second');
    $a->addEl('third');
    $a->registry['second']->addEl('primary');
    $a->registry['second']->addEl('secondary');
    $a->registry['second']->addEl('tertiary');
    $a->registry['second']->addEl('Quator');
    $a->myNameIs();
    $a->registry['second']->myNameIs();
    $a->registry['second']->hoosYaDaddy(); 
    The Idea is that hoosYaDaddy() would access 'myName' in the parent object , NOT in itself.

  6. #6
    SitePoint Wizard wonshikee's Avatar
    Join Date
    Jan 2007
    Posts
    1,223
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    You could store the parent during creation:

    $this->registry[$name]->daddy = $this->myName;

    function hoosYaDaddy(){
    $dad = $this->daddy;
    echo 'a child of ',$dad,'.<br>';
    }


    $a->registry['second']->registry['secondary']->myNameIs();
    $a->registry['second']->registry['secondary']->hoosYaDaddy();

    Those tests seem to return correctly.

    This kind of stuff hurts my head and just feels like you're trying to create something pointlessly complicated.

  7. #7
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,804
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    You could store the parent during creation
    Thats the way I have handled in the past...

    $a->registry['second']->registry['secondary']->myNameIs();
    It's exactly this chaining I am trying to avoid. The goal would be able to reach the parent from a function inside the child ( which also would mean I could potentially climb up all the way to the root element by recursively accessing this function)


    Keep in mind my example is essentially abstract ( not to be confused with abstract classes) .. I am just trying to represent navigation through containers.

  8. #8
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    parent:: is not STATIC!!!

    But you see, the problem is, your class/objects are poorly designed.
    It will not work like you expect it to work.

    "What I am trying to do is access a property of an INSTANCE that contain other instances from within one of the instances it contains." This is the incarnation of bad programming. An Instance contained within another instance should have no awareness of it being contained within an instance. It becomes a nightmare to maintaine, code for, debug....all sorts of problems. Not to mention you get crazy amount of recursive looping.


    Here is a basic example of how I might do it...without full understanding of what you are doing.
    PHP Code:
    <?php

    class Tree
    {
      protected 
    $name$index = array();
      
      public function 
    __construct $name ) {
        
    $this->name $name;
      }
      
      public function 
    register $obj ) {
        
    $this->index[] = $obj;
        return 
    $this;
      }
      
      public function 
    __toString ()
      {
        
    $out 'Tree: ' $this->name "\n";
        foreach ( 
    $index as $child ) {
          
    $out .= '  ' $child->__toString() . "\n";
        }
        
        return 
    $out;
      }
    }

    class 
    Leaf
    {
      protected 
    $name;

      public function 
    __construct $name ) {
        
    $this->name $name;
      }
      
      public function 
    __toString () { return 'Leaf: ' $this->name; }
    }

    $r = new Tree'SubRoot' );
    $r->register( new Leaf'SubChild1' ) )
      ->
    register( new Leaf'SubChild2' ) )
      ->
    register( new Leaf'SubChild3' ) );

    $t = new Tree'Root' );
    $t->register( new Leaf'Child1' ) )
      ->
    register$r )
      ->
    register( new Leaf'Child2' ) )
      ->
    register( new Leaf'Child3' ) );
      

    $t->__toString();
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  9. #9
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    After looking it over a bit, I am assuming of course, that you are wanting this concerning html:
    HTML Code:
    <ul>
      <li><a href="">Link1</a></li>
      <li><a href="">Link2</a>
        <ul>
          <li><a href="">Link1</a></li>
          <li><a href="">Link2</a></li>
          <li><a href="">Link3</a></li>
          <li><a href="">Link4</a></li>
          <li><a href="">Link5</a></li>
        </ul>
      </li>
      </li>
      <li><a href="">Link3</a></li>
      <li><a href="">Link4</a>
        <ul>
          <li><a href="">Link1</a></li>
          <li><a href="">Link2</a></li>
          <li><a href="">Link3</a></li>
          <li><a href="">Link4</a></li>
          <li><a href="">Link5</a></li>
        </ul>
      </li>
      </li>
      <li><a href="">Link5</a></li>
    </ul>
    Untested of course but this code should be able to output the above:
    Navigation holds Link(s), Link holds Navigation.
    PHP Code:
    class Navigation
    {
      protected 
    $links = array();
      
      public function 
    addLink Link $link ) {
        
    $this->links[] = $link;
      }
      
      public function 
    __toString()
      {
        
    $out '<ul>';
        
        foreach ( 
    $links as $link ) {
          
    $out .= '<li>' $link->__toString() . '</li>';
        }
        
        return 
    "$out</ul>";
      }
    }

    class 
    Link
    {
      protected 
    $name$nav;
      
      public function 
    __construct $name ) {
        
    $this->name $name;
      }
      
      public function 
    addSubNav Navigation $nav ) {
        
    $this->nav $nav;
      }
      
      public function 
    __toString ()
      {
        
    $out '<a href="#">' $this->name '</a>';
        if ( isset( 
    $this->nav ) )
          
    $out .= $this->nav->__toString();
        
        return 
    $out;
      }

    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  10. #10
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,804
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    Logic I really do appreciate all your input.

    But you see, the problem is, your class/objects are poorly designed.
    It will not work like you expect it to work.
    Am really experimenting with something so yeah its going to seem like horrendous code. ( am not dealing with HTML output exact, but nested information storage.. think of it as Russian dolls... DOLL (Level X) belongs to DOLL (level X-1), not any other and can have any number of DOLL(Level X+1)s.. but not any other type. This would be simple (in an awkward way enough if I merely wanted to know the LEVEL of the object for knowing the levels sake). For that I could assign a variable to to the class of parentLevel+1. But what I want is the child objects to have acess to the information (attributes) of the parent OBJECT ( even if they have been changed)

    when I use parent:: it doesnt let me get OBJECT values, just CLASS static constants.
    If I try t access a method , via parent::foo(), any $this->whatever within the foo is interpreted as the $this->whatever in the child not the parent 's.


    * The goal of my experiment is to STORE each node rather than output it.
    * The 'TREE' can have TRUNKS, BRANCHES, AND LEAVES.. so its not just a simple parent-child; tho each lower level should be able to know where it is "stored'
    * Dymanic /recursive-able.. that means hard coding $a->branchFoo()->branchFoo()->branchFoo()->branchFoo()
    * With that being said , the mechanism is internal; it's the object itself that 'knows' at which level its at and not the user/programmer .

    Maybe attempting to create things via NESTING is what you mean by poor construction... I just thought it would be more intuitive if i could do it that way

    I am trying to run your example. .but it says : Invalid argument supplied for foreach() in - on line 19 I will toy around with it tho

  11. #11
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    The child should not know where it is stored.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  12. #12
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,804
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    The child should not know where it is stored.
    I suppose that's all that I was looking for. I have learned or developed patterns for most things. I t seems pretty simple and normal to start from the the outermost and go inwards but the reverse is what i was trying to accomplish, if it was possible. In other words, sure I can get the parent to return a child object... but not the child object to return a parent.

    I suppose I was crazy for trying... had to give it a shot

  13. #13
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    What you need is another layer. You have the tree, with its parents and child relations. Within the tree no one really knows where they are in the tree. To manage the tree you have a second layer, this layer knows where everything is, who is the parent of this object, etc. Good example would be a file system, directories and files have no concept of their location, or where they are in the hierarchy of the file system. What manages that is, well at least in NTFS, you have the Master File Table whichs keeps track of relationships. The files and dictionaries themselves have no concept of those relationships.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  14. #14
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,804
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    Thats a good idea. I suppose you mean that this layer would be on the same level or independent from the tree? I guess I am unclear as to how this would be structured how would that be structured in PHP and could child elements access this second layer.

  15. #15
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,276
    Mentioned
    18 Post(s)
    Tagged
    0 Thread(s)
    I didn't quite follow everyone's thought process throughout this thread, so please forgive me if I repeat something that's already been communicated.

    The code in the first post seems to be confusing sublcassing with object composition. You shouldn't be creating a subclass to represent a depth in the tree. All you really need is one class with references to child nodes and a parent node.

    PHP Code:
    class TreeNode
    {
        private 
    $childNodes = array();
        private 
    $parentNode;

        
    // a name for this node; for demo purposes
        
    private $name;

        public function 
    __construct($name)
        {
            
    $this->name $name;
        }

        public function 
    addChild($childNode)
        {
            
    $this->childNodes[] = $childNode;
            
    $childNode->parentNode $this;
        }

        public function 
    getParent()
        {
            return 
    $this->parentNode;
        }

        public function 
    __toString()
        {
            return 
    $this->name;
        }
    }

    $root = new TreeNode('root');

    // depth 1
    $leafA1 = new TreeNode('A1');
    $root->addChild($leafA1);

    $leafA2 = new TreeNode('A2');
    $root->addChild($leafA2);

    // depth 2
    $leafB1 = new TreeNode('B1');
    $leafA1->addChild($leafB1);

    // echo lineage
    echo $leafB1// B1
    echo $leafB1->getParent(); // A1
    echo $leafB1->getParent()->getParent(); // root 

  16. #16
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,804
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    Jeff, I don't think that's what LogicEarth had in mind with his multi layer suggestion.

    However...

    public function addChild($childNode)
    {
    $this->childNodes[] = $childNode;
    $childNode->parentNode = $this;
    }
    I was thinking of the same thing . But I never bothered to pursue that avenue as I am afraid that containing the parent within the child would have serious recursive issues? maybe even memory leaks?

    A=>B=>A=>B=>A=>...

    I know that PHP is intelligent enough to avoid an 'infinite loop' in this case. Still, it seems risky?

  17. #17
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,276
    Mentioned
    18 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dresden_phoenix View Post
    Jeff, I don't think that's what LogicEarth had in mind with his multi layer suggestion.

    However...



    I was thinking of the same thing . But I never bothered to pursue that avenue as I am afraid that containing the parent within the child would have serious recursive issues? maybe even memory leaks?

    A=>B=>A=>B=>A=>...

    I know that PHP is intelligent enough to avoid an 'infinite loop' in this case. Still, it seems risky?
    Memory leaks shouldn't be an issue. The garbage collector can identify and reclaim circular references.

    As for recursive issues... true, as written, the code doesn't stop the programmer from doing silly things, such as making two nodes each other's parent. If we were going to use this code, we'd have to develop it a little further to add checks that protect the programmer from himself.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •