简体   繁体   中英

instantiate different class based on the object type in PHP

I am searching for a architectural solution in instantiating different child classes based on an object type or extending Base class with the methods of child classes.

To give an example: There is a base class User and several child classes Partner , Client , Moderator which have specific methods an their own constructors. When I am calling

$user = new User($userid);

I want User class

class User
{
  public function __construct($userid) {
    self::initDB(); 

    if ($this->isPartner()) {
        //extend this class with the methods of "Partner" child class and run "Partner" class constructor
    }

    if ($this->isClient()) {
        //extend this class with the methods of "Client" child class and run "Client" class constructor
    }

    if ($this->isModerator()) {
        //extend this class with the methods of "Moderator" child class and run "Moderator" class constructor
    }
  }
}

To return me an object with all of the methods depending on what roles does user have.

I know my logic is broken somewhere and the example I provided is wrong. But the only solution I see now is to build one giant class that has all of the methods for all of the roles - which looks like a mess.

First of all, your database logic should be totally separate from your domain objects (User, etc). Otherwise you are violating the single responsibility principle (SRP).

Set up your classes something like the following (base class User and multiple subclasses):

class User 
{
  private $id;
  // getters and setters go here
}

class Moderator extends User {}
class Partner extends User {}
// etc

Then, create some sort of UserManager class that implements an interface that looks like the following:

interface UserManagerInterface {
  function loadUserById($id);
}

The implementation of that method should load the passed user id's information from the database, look at what type it is (partner, moderator, etc) and then instantiate the appropriate class and hydrate the appropriate information.

The problem is that you cannot call new User and get anything other than a User object.

This sounds like the perfect use-case for the factory pattern.

The simplest form of this uses a static method to invoke the correct constructor.

So you could have code like this:

class User {
    public static function create($userid) {
        // get user from the database

        // set $isPartner to true or false
        // set $isClient to true or false
        // set $isModerator to true or false

        if ($isPartner) {
            return new Partner($userid);
        } elseif ($isClient) {
            return new Client($userid);
        } elseif ($isModerator) {
            return new Moderator($userid);
        } else {
            return new User($userid);
        }
    }
}

You can then call User::create($userid) to get the appropriate object.

If your code is appropriately structured, it may well be possible to have code along the lines of Lusitanian's answer (fleshed out) that would do a better, more flexible job.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM