SitePoint Sponsor

User Tag List

Results 1 to 5 of 5

Hybrid View

  1. #1
    SitePoint Member
    Join Date
    Oct 2009
    Posts
    20
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How should this Class be written in php? Composition, Inheritance, Decorator?

    I have a database where people might simultaneously be employees, customers and members of a company. My adminstration system allows me to edit the properties of the Person, Employee, Customer and Member objects on independent pages.

    Now, I'd like to be able to call up a Person but be able to view and edit their employee, customer and member properties on the same page. Creating a view for this scenario is trivial, but I'd like to do it properly with the correct specification of base class, inheritances, compositions and aggregates, etc.

    I do understand that the employees, customers and members can't exist without the person, so for my admin page, I'm thinking I should create a new class, UberDude, that is a composition of the person, employee, customer and member classes. I would also like to use this new class as part of a collection so that I could draw a table of all persons and see whether they are employees, customers or members. Something doesn't seem right and I can't work out the code for the class structure. Any ideas?

  2. #2
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    My own preference would be to make Employee, Customer and Member extend the Person class - because they are a kind of person. I wouldn't personally have a class which represents all three. I would also possibly make the Person an abstract class which can only exist as extensions - the above. What is a person doing on your system if they aren't an Employee, Customer or Member?

    However if you want that, creating a new class isn't necessary; You already have a class which can contain the Employee, Customer and Member objects - the Person class! Those objects can in turn contain the Person object so that you can access public Person methods inside Employee, Customer and Member. However, that would make Employee, Customer and Member have something important in common: They all contain a Person object, so again I would make an abstract class which they extend, for symmetry.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  3. #3
    SitePoint Member
    Join Date
    Oct 2009
    Posts
    20
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Jake, thanks for replying - good points!

    I don't think I was able to fully express in my post the reason I think I need new classes for a combined 'person-employee-customer-member', 'person-employee-member', 'person-employee-customer', 'person-customer-member' etc...

    This particular example is for a sports facility. Say I want to offer employees a customer discount, but they must be members (they have completed basic training as all customers do). That is to say this object is an employee AND a customer AND a member. I would like a 'person-employee-customer-member' class. I'm not aware how I can subtype Person and combine the subtypes?

    Another example is an online shop. Say now I want to offer customers premium membership for a limited time only. They are only customers until they become a member. Then they are a customer AND a member. Again, I'm not sure how extending person would let me combine customer and member into a 'person-customer-member' class?

  4. #4
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Woah, woah, woah. Stop right there :P New classes for every combination is over-complicating everything massively. It also kills the possibility of polymorphism, as a class can only extend one class.

    Ok let's start from the basics - what's your database layout?

    I'm assuming (hoping) it'd be something like:
    Code:
    People
    ID
    Name
    Address
    Etc
    
    Customers
    Person ( = People.ID)
    etc
    
    Members
    Person ( = Customers.ID)
    etc
    
    Employees
    Person ( = People.ID)
    etc
    That way you could have something like:
    PHP Code:
    interface iPerson{
        public function 
    getID();
        public function 
    getName();
        public function 
    getAddress();
        public function 
    setAddress($Address);
        public function 
    isEmployee();
        public function 
    isCustomer();
        public function 
    isMember();
        public function 
    getEmployee();
        public function 
    getCustomer();
        public function 
    getMember();
    }
    class 
    Person implements iPerson{
        protected 
    $ID$Name$Address;
        protected 
    $Employee null$Customer null$Member null;
        public function 
    getID(){
            return 
    $this->ID;
        }
        public function 
    getName(){
            return 
    $this->Name;
        }
        public function 
    getAddress(){
            return 
    $this->Address;
        }
        public function 
    setAddress($Address){
            
    $this->Address $Address;
        }
        public function 
    isEmployee(){
            return !
    isNull($this->Employee);
        }
        public function 
    isCustomer(){
            return !
    isNull($this->Customer);
        }
        public function 
    isMember(){
            return !
    isNull($this->Member);
        }
        public function 
    getEmployee(){
            return 
    $this->Employee;
        }
        public function 
    getCustomer(){
            return 
    $this->Customer;
        }
        public function 
    getMember(){
            return 
    $this->Member;
        }
    }
    class 
    PersonHolder implements iPerson{
        protected 
    $Person;
        public function 
    getID(){
            return 
    $this->Person->getID();
        }
        public function 
    getName(){
            return 
    $this->Person->getName();
        }
        public function 
    getAddress(){
            return 
    $this->Person->getAddress();
        }
        public function 
    setAddress($Address){
            return 
    $this->Person->setAddress($Address);
        }
        public function 
    isEmployee(){
            return 
    $this->Person->isEmployee();
        }
        public function 
    isCustomer(){
            return 
    $this->Person->isCustomer();
        }
        public function 
    isMember(){
            return 
    $this->Person->isMember();
        }
        public function 
    getEmployee(){
            return 
    $this->Person->getEmployee();
        }
        public function 
    getCustomer(){
            return 
    $this->Customer->getCustomer();
        }
        public function 
    getMember(){
            return 
    $this->Member->getMember();
        }
    }
    class 
    Customer extends PersonHolder{
        protected 
    $SomethingCustomerRelated null;
        function 
    __Construct(....){
            
    $this->Person $Person;
        }
        function 
    getSomethingEmployeeRelated(){
            return 
    $SomethingCustomerRelated;
        }
    }
    class 
    Employee extends PersonHolder{
        protected 
    $SomethingEmployeeRelated null;
        function 
    __Construct(....){
            
    $this->Person $Person;
        }
        function 
    getSomethingEmployeeRelated(){
            return 
    $SomethingEmployeeRelated;
        }
    }
    class 
    Member extends PersonHolder{
        protected 
    $SomethingMemberRelated null;
        function 
    __Construct(....){
            
    $this->Person $Person;
        }
        function 
    getSomethingMemberRelated(){
            return 
    $SomethingMemberRelated;
        }

    By doing this, a customer, member and employee can all contain a person object which, once changed, will affect the customer, member and employee objects. It also means that all of them implement the iPerson interface, so passing a customer to a function which expects a person:
    PHP Code:
    function assassinate(iPerson $Person){ ... } 
    You can assassinate (assuming your company is, in fact, an evil organisation) a customer, person or employee in the same way. The Person object also has access to the employee, member and customer objects, if they so exist, and has methods to see if they do or don't exist.

    There may be other ways of going about it, but that seems the most logical to me.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  5. #5
    SitePoint Member
    Join Date
    Oct 2009
    Posts
    20
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Jake - Correct me if I'm wrong in assuming that what you're saying is keep things the way I have (as your code snippets show) so that, for example, the page where I can view 'employee members' and update 'employee-member' specific data uses a separate instance of 'employee' and an instance of 'member' rather than a single 'employee-member' instance. It's down to my 'view' and business logic to compose the idea I have of an 'employee-member' ?


Tags for this Thread

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
  •