Search code examples
phpclassconstructoroptional-arguments

How do I pass specific optional arguments?


I have 2 cases.

  • Case 1: pass the name and age.
  • Case 2: pass name and gender.

How can I do this?


class User {

    function __construct($name=NULL, $gender=NULL, $age=NULL) {
        ...
    }

}

// How do I pass specific arguments here?
$case_1 = new User("Bob", 34);
$case_2 = new User("James", "m");

Solution

  • You can have optional arguments in PHP, but you cannot have either/or arguments as that would require function overloading which is not supported in PHP. Given your example, you must call the constructor as follows:

    // How do I pass specific arguments here?
    $case_1 = new User("Bob", null, 34);
    $case_2 = new User("James", "m");
    

    If you want to eliminate the optional but required to be null argument, you will need to get clever.

    Option One: Use a factory. This would require a common argument constructor in conjunction with mutator methods for each of the unique arguments.

    class UserFactory {
       public static function createWithGender($name, $gender)
       {
           $user = new User($name);
           $user->setGender($gender);
    
           return $user;
       }
    
       public static function createWithAge($name, $age)
       {
           $user = new User($name);
           $user->setAge($age);
    
           return $user;
       }
    }
    
    $case_1 = UserFactory::createWithAge("Bob", 34);
    $case_2 = UserFactory::createWithGender("James", "m");
    

    The factory doesn't need to be a separate class, you can alternatively add the static initializers to the User class if desired.

    class User {
       function __construct($name = null)
       {
            ...
       }
    
       public static function createWithGender($name, $gender)
       {
           $user = new static($name);
           $user->setGender($gender);
    
           return $user;
       }
    
       public static function createWithAge($name, $age)
       {
           $user = new static($name);
           $user->setAge($age);
    
           return $user;
       }
    }
    
    $case_1 = User::createWithAge("Bob", 34);
    $case_2 = User::createWithGender("James", "m");
    

    Option Two: Do some argument detection. This will only work if the arguments are all unique types.

    class User {
        public function __construct($name, $second = null) {
            if (is_int($second)) {
                $this->age = $second;
            } else {
                $this->gender = $second;
            }
        }
    }
    
    $case_1 = new User("Bob", 34);
    $case_2 = new User("James", "m");