Is it possible to create classes with two constructors?

6

I'm doing my PHP database connection class using the mysqli_ API, and I came across the fact that I can not put two constructors in the same class.

The idea is to use previously defined constants if nothing is passed as an argument.

Is it possible to have two constructors in the same class in PHP?

define( 'DATA_BASE', 'db_name'   );
define( 'USER_NAME', 'user_name' );
define( 'PASSWORD' , 'password'  );
define( 'HOST'     , 'localhost' );

class MysqliDB
{    
    private $user;
    private $password;
    private $database;
    private $host;

    public function __construct( $user, $password, $database, $host = 'localhost' )
    {
        $this->user     = $user;
        $this->password = $password;
        $this->database = $database;
        $this->host     = $host;
    }

   public function __construct()
    {
        $this->user     = USER_NAME;
        $this->password = PASSWORD;
        $this->database = DATA_BASE;
        $this->host     = HOST;
    }
}
    
asked by anonymous 21.10.2014 / 12:34

1 answer

6

Let's go first to the problem solution.

You do not need two constructors, you just need to do what was done in the last constructor argument:

class MysqliDB {

    public function __construct( $user = USER_NAME, $password = PASSWORD, $database = DATA_BASE, $host = HOST ) {}
}

And if the object is instantiated without arguments, the default values will be used.

However, this opens a loophole for the person to do this:

new MysqliDB( null, 1234 );

Expecting to be just changing the password and keeping the user. And that's why you need a method that checks the integrity of the data before you mount the MySQL object to be used in the context of your class.

There are several ways to do this, but the two most common ones are:

  • Invoke a method right after the properties are populated to check if everything is going well:

    public function __construct( $user = USER_NAME, $password = PASSWORD, $database = DATA_BASE, $host = HOST )
        {
            $this->user     = $user;
            $this->password = $password;
            $this->database = $database;
            $this->host     = $host;
    
            $this -> checkIntegrity();
        }
    
       public function checkIntegrity()
        {
            if( empty( $this -> username ) ) {
                die( 'Usuário MySQL ausente' );
            }
        }
    }
    
  • Remove the named method arguments and use func_get_args() :

    class MysqliDB {
    
        public function __construct()
        {
            list( $user, $password, $database, $host ) = func_get_args();
    
            $this->user     = $user;
            $this->password = $password;
            $this->database = $database;
            $this->host     = $host;
        }
    }
    

The problem with this approach is that list() is half dumb and if func_get_args() returns less than the four inputs required by it, it will give offset error.

And that's when you kill two birds with one stone. If you add (not merge) another array to func_get_args() with the exact amount of arguments expected by list() , if any argument is omitted in the constructor, this array would override the offsets < in> with some default value, in case its constants:

list( $user, $password, $database, $host ) = func_get_args() + array( USER_NAME, PASSWORD, DATA_BASE, HOST );

In my opinion this still would not require a method of integrity checking but it's because I'm paranoid.

Now responding directly to your question: Yes, there may be two methods constructors, but not two class constructors . I explain:

PHP4 also had Object Orientation. His weird way, but he had. In this version the class constructors were methods with the same name as the class:

class Foo {

    function Foo() {

        // No PHP4 esse método era o construtor
    }
}

When PHP5 was launched and the PHP Object Oriented rewritten and improved, the magic method __construct() was introduced to serve as a constructor.

For reasons of backward compatibility with scripts made in PHP4 during this period of introduction of the new model PHP5 still accepted a method of the same name as the class as constructor so yes, it is possible to have something like:

class Foo {

    function Foo() {

        echo __METHOD__, '<br />';
    }

    public function __construct() {

        echo __METHOD__, '<br />';
    }
}

I'm not sure which version of PHP 5 this started to be "banned" from. In quotes because this snippet running in my PHP 5.4.14 only triggers a Strict Standards saying that it is not possible to redefine an already defined constructor.

    
21.10.2014 / 13:40