Page 1 of 2

Connecting Objects in OOP ? How ?

Posted: Fri Nov 03, 2006 11:04 pm
by christian_phpbeginner
Hello folks,

I am confuse about how to connect objects within PHP. I have here class.Address.php, class.PhoneNumber.php, and class.Contact.php.

Then, I need to connect them somehow in class.ObjectConnector.php (I guess). Here is where I am confuse….should I instantiate the Contact, Address, and PhoneNumber object within the ObjectConnector class or should I call for their parent, for example “Contact::__getName()” ???

Thanks,
Chris

Posted: Fri Nov 03, 2006 11:10 pm
by feyd
How do they relate to ObjectConnector?

Posted: Sat Nov 04, 2006 12:11 am
by christian_phpbeginner
Hi feyd,

Well, what I want to do is combine them all: address, contact, and phonenumber within the ObjectConnector class. So then, later when I want to create an Object of Employee for example, I can extend the ObjectConnector. What I want to do later when the objects are assembled (the system is finished) actually something like:

Code: Select all

<?php
   $employee = new Employee();
   $employee->addAddress();
   $employee->editAddress();
?>
Thank you,
Chris

Posted: Sat Nov 04, 2006 12:17 am
by feyd
If ObjectConnector doesn't specifically need them to function, then there's no reason to attach them to it that I can see.

Posted: Sat Nov 04, 2006 12:44 am
by jmut
christian_phpbeginner: Using PHP 5 or 4?

Posted: Sat Nov 04, 2006 4:05 am
by christian_phpbeginner
jmut wrote:christian_phpbeginner: Using PHP 5 or 4?
Oh, I forgot to mention it...I am using PHP 5.

Today, I lent a book from my university. The book's title: PHP 5 professional. I saw their UML for creating ContactManager system. It's the same as my logic at the first place. They have separated the Address, EmailAddress, PhoneNumber, and Contact class.

Now, I don't know if I am already on the right track. Please tell me if I use OOP in the right manner by taking a look at my code below ?

For example:

The address class:

Code: Select all

<?php
   class Address {
      
     private $_addressID;
     private $_street;

     public function __construct($addressID) {
         $this->_addressID = $addressID;
     }

     public function __getAddressID() {
         return $this->_addressID;
     }

     public function __setStreet($street) {
        $this->_street = $street;
     }
     
     public function __getStreet() {
        return $this->_street;
     }

   }   
?>
This is the Contact Class:

Code: Select all

<?php
   class Contact {
      
     private $_contactID;
     private $_name;

     public function __construct($contactID) {
         $this->_contactID= $contactID;
     }

     public function __getContactID() {
         return $this->_contactID;
     }

     public function __setName($name) {
        $this->_name = $name;
     }
     
     public function __getName() {
        return $this->_name;
     }

   }   
?>
Now, this is the Entity class:

Code: Select all

<?php
   require_once ('class.Contact.php');
   require_once('class.Address.php');
   
   class Entity {
   
      public function __construct ($name) {
         
         //call the parents
         Contact::__construct('null');
         Contact::__setName($name);
      }

      public function addAddress($streetAddress) {
             //call the parents
            Address::__construct('null');
            Address::__setStreet($streetAddress);
      }
   }
?>
Using this, I intend to create a new class, for example Applicant class by extending the entity class.

Code: Select all

<?php
   require_once('class.Entity.php');
   
   class Applicant extends Entity {
      private $_applicantID;
      private $_name;
      private $_userType;

      public function __construct($applicantID, $name) {
      
         $this->_applicantID = $applicantID;
         $this->_name = $name;
         $this->_userType = "Applicant";

      }      
   }
?>
Then, making use of the system:

Code: Select all

<?php
   require_once ('class.Applicant.php');
   
   $applicant = new Applicant('null', 'Christian');
   $applicant->addAddress('21 Jump Street');
?>
Yes, it's lame....I am new to this language and start to learn it now....I dunno if the OOP approach I did above is good, or there is much better way to do it ?

Thank you very much,
Chris

Posted: Sat Nov 04, 2006 5:02 am
by Ollie Saunders
Only use underscore underscore prefix on method when you want a reserved magic method such as __construct, __destruct, __sleep, __wakeup etc. i.e. don't use them for the hell of it.

There is no point in this:

Code: Select all

class Foo
{
    private $_value;
    public function getValue()
    {
          return $this->_value;
    }
    public function setValue($value)
    {
        $this->_value = $value;
    }
}
is, functionality, exactly the same as:

Code: Select all

class Foo
{
    public $value;
}
except its more work and slower. Getter and setter methods are very very useful and you will use them all the time but, again, not just for the hell of it.
Have you tried executing any of the code you posted last because I think you'll have parse errors on that Entity class of yours.

Posted: Sat Nov 04, 2006 7:16 am
by Cameri
The only reason you should use a "setter" is if you want to add some kind of checking the content that is trying to be set is correct, like some kind of filtering. If you are just going to pass a value directly, then do as ole says.

Code: Select all

<?php
   class Address {
     private $addressID;
     public $street;

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

     public function getAddressID() {
         return $this->addressID;
     }
// no need for getters and setters if there's no input checking and filtering
   }   
?>

Code: Select all

<?php
   class Contact {
     private $contactID;
     public $name;

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

     public function getContactID() {
         return $this->contactID;
     }
     // no need for getters and setters if there's no input checking and filtering
   }

Code: Select all

require_once ('class.Contact.php');
   require_once('class.Address.php');
   
   class Entity {
     private $address; //object of class Address
     private $contact; //object of class Contact
   
      public function __construct (Address $address=null,Contact $contact=null) {
         //parent::__construct('null');  //<-- ok, Entity does NOT have a parent, no need for this? huh?
         if ($address instanceof Address)
             $this->addAddress($address);
         if ($contact instanceof Contact)
             $this->addContact($contact);
      }

      public function addAddress(Address $address) {
            $this->address = $address;
      }

      public function addContact(Contact $contact) {
            $this->contact = $contact;
      }

      public function getStreet(){
         if ($this->address instanceof Address){
            return $this->address->street;
          }
      }

     //no need for Entity::setName or Entity::getName, $contact object already holds the name
      public function getName(){
          if ($this->contact instanceof Contact){
              return $this->contact->name;
          }
      }
   }
?>

Code: Select all

<?php
   require_once('class.Entity.php');
   
   class Applicant extends Entity {
      private $applicantID;
      private $userType;

      public function __construct($applicantID,Address $address=null,Contact $contact=null) {
         parent::__construct();
         $this->applicantID = $applicantID;
         $this->userType = "Applicant";
      }
   }
?>

Posted: Sat Nov 04, 2006 7:32 am
by jmut
Hm..."interesting" book.
christian_phpbeginner wrote:....Please tell me if I use OOP in the right manner by taking a look at my code below ?

For example:

The address class:

Code: Select all

<?php
   class Address {
      
     private $_addressID;
     private $_street;

     public function __construct($addressID) {
         $this->_addressID = $addressID;
     }

     public function __getAddressID() {
         return $this->_addressID;
     }

     public function __setStreet($street) {
        $this->_street = $street;
     }
     
     public function __getStreet() {
        return $this->_street;
     }

   }   
?>
What's the idea behind passing id when building address objects? Are you trying to build some DB mapper or somerhing.
christian_phpbeginner wrote:...
Now, this is the Entity class:

Code: Select all

<?php
   require_once ('class.Contact.php');
   require_once('class.Address.php');
   
   class Entity {
   
      public function __construct ($name) {
         
         //call the parents
         Contact::__construct('null');
         Contact::__setName($name);
      }

      public function addAddress($streetAddress) {
             //call the parents
            Address::__construct('null');
            Address::__setStreet($streetAddress);
      }
   }
?>
Using this, I intend to create a new class, for example Applicant class by extending the entity class.

How calling the constructor statically will make you "object connection"? I dont see the point.

I think this will make more sense.

Code: Select all

class Applicant {
  private $_applicantID;
  private $_userType;

  /**
   * @var Address
   */
  private $_address = null;

  /**
   * @var Contact
   */
  private $_contact = null;


  public function __construct($applicantID, Contact $contact, Address $address) {

     $this->_address = $address;
     $this->_contact = $contact;
     $this->_applicantID = $applicantID;
     $this->_userType = get_class($this);
  }

  public function setStreet($street)
  {
      $this->_address->__setStreet($street);
  }

}

$tom = new Applicant('Tom',new Contact(11),new Address(21));
This is kind of pointless example...but one way to make connection between objects.
Eeach person(applicant whatever) has contact and address (hance keep them in property).

What I just did probably will not make much sense... What exacly is the problem you are trying to describe (to solve).
Then we can think of an OOP model to express it.

Posted: Sat Nov 04, 2006 7:37 am
by jmut
Cameri wrote:The only reason you should use a "setter" is if you want to add some kind of checking the content that is trying to be set is correct, like some kind of filtering. If you are just going to pass a value directly, then do as ole says.

Code: Select all

<?php
   class Address {
     private $addressID;
     public $street;

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

     public function getAddressID() {
         return $this->addressID;
     }
// no need for getters and setters if there's no input checking and filtering
   }   
?>

hm...I would disagree with that one. how will you force using

Code: Select all

$this->getAddressID();
//instead of directly
$this->addressID;

//this makes method getAddressID totaly pointless.
It defeats the whole purpose of accessors. So either you should use get/set apporach or just define public and use directly.
This totally depends on how large the application is to be. set/get adds much more flexibility in usage...it depends.

Posted: Sat Nov 04, 2006 7:43 am
by jmut
Cameri wrote:.....

Code: Select all

require_once ('class.Contact.php');
   require_once('class.Address.php');
   
   class Entity {
     private $address; //object of class Address
     private $contact; //object of class Contact
   
      public function __construct (Address $address=null,Contact $contact=null) {
         //parent::__construct('null');  //<-- ok, Entity does NOT have a parent, no need for this? huh?
         if ($address instanceof Address)
             $this->addAddress($address);
         if ($contact instanceof Contact)
             $this->addContact($contact);
      }
.....

     //no need for Entity::setName or Entity::getName, $contact object already holds the name
      public function getName(){
          if ($this->contact instanceof Contact){
              return $this->contact->name;
          }
      }
   }
?>
Type hinting is enough to ensure objects are of required type. checking with instanceof is not necessary.

Re: Connecting Objects in OOP ? How ?

Posted: Sat Nov 04, 2006 8:46 am
by BDKR
christian_phpbeginner wrote: I am confuse about how to connect objects within PHP. I have here class.Address.php, class.PhoneNumber.php, and class.Contact.php.

Then, I need to connect them somehow in class.ObjectConnector.php (I guess).
OK. I suspect there are better terms to be used here. You don't really connect objects. However, if you need objects to communicate with one another, they
need to be aware of one another. That's taken care of in the examples above.

The act of communicating between objects is called "Message Passing".

It's certainly clear that you have a Java mindset here about Object Hiearchies.

Posted: Sat Nov 04, 2006 9:09 am
by Cameri
jmut wrote:
Cameri wrote:.....

Code: Select all

require_once ('class.Contact.php');
   require_once('class.Address.php');
   
   class Entity {
     private $address; //object of class Address
     private $contact; //object of class Contact
   
      public function __construct (Address $address=null,Contact $contact=null) {
         //parent::__construct('null');  //<-- ok, Entity does NOT have a parent, no need for this? huh?
         if ($address instanceof Address)
             $this->addAddress($address);
         if ($contact instanceof Contact)
             $this->addContact($contact);
      }
.....

     //no need for Entity::setName or Entity::getName, $contact object already holds the name
      public function getName(){
          if ($this->contact instanceof Contact){
              return $this->contact->name;
          }
      }
   }
?>
Type hinting is enough to ensure objects are of required type. checking with instanceof is not necessary.
Well yeah I could probably just use if ($contact), and if ($address), makes perfect sense ^^, since you can decide not to pass the object it can also be null.

As for the Address::getAddressID() method, yeah, you really don't need that, didnt check for that ^^.

But you guys are missing the whole point of this, he's learning how to connect objects from some book with some example that DOES NOT need to be useful, it's just to show him how it's done. I find the example myself as an overkill with all the Address and Contact thingy if all it's going to do it's set and get address/contact.

Posted: Sat Nov 04, 2006 10:17 am
by Chris Corbyn
jmut wrote:
Cameri wrote:.....

Code: Select all

// ... snip ...   
      public function __construct (Address $address=null,Contact $contact=null) {
// ... snip ...
Type hinting is enough to ensure objects are of required type. checking with instanceof is not necessary.
They were already type hinting but then further checking for the actual type of object not just an inherited type. (Sadly) PHP does not support true method overloading so you need to do things like this if you plan on passing mutliple types following a common interface to the same method.

//Swerves back to earlier notes

__<method>() is reserved for future releases of PHP, avoid using it. But as somebody also suggested losing the underscore on private vars my advice is to just use whatever method you think is better. This is a bit of a grey area and stems back to PHP4 not support access control. (Lone) Underscores are still advised on private properties and methods just to make it more obvious but many developers (me included) don't feel the need when you're using PHPDocumentor and actual native PHP access control.

Posted: Sat Nov 04, 2006 12:33 pm
by Ollie Saunders
d11wtq wrote:(Lone) Underscores are still advised on private properties and methods just to make it more obvious but many developers (me included) don't feel the need when you're using PHPDocumentor and actual native PHP access control.
I started using single underscore prefix for private and protected properties and methods since I read the ZF coding standards. However, despite religiously using them, I don't have a particularly strong opinion on them. Do whatever you feel comfortable with.