Is it possible to create classes with two constructors?

Asked

Viewed 3,366 times

6

I am making a class of my connection to PHP Database using the API mysqli_ and I came across the fact that I couldn’t put two builders in the same class.

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

It is possible to have two constructs in the same PHP class?

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;
    }
}
  • What is the intention with this? Use constants if nothing is passed? You can use conditionals within the constructor.

  • The idea is this @bfavaretto. I know so, but it didn’t seem very orthodox...

  • 4

    It is more orthodox than trying to have two constructors, PHP does not allow this kind of Overload.

1 answer

6


Let’s go first to the solution of problem.

You don’t 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 gap in case the person does it:

new MysqliDB( null, 1234 );

Hoping to be changing only the password and keeping the user. Which is why you need a method that checks data integrity before mounting the Mysql object to be used in the context of your class.

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

  • Invoke a method right after the properties are populated to check that 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 named arguments from the method 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 case func_get_args() returns less than the four entries required by it, will give error of offset.

And that’s where you kill two birds with one stone. If you add up (do 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 supply the offsets with some standard value, in the case of its constants:

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

In my opinion this still would not dispense with a method of verification of integrity but it is because I am paranoid.


Now answering directly your question: Yes, it is possible to have two methods builders, but not two class builders. I’ll explain:

PHP4 also had Object Orientation. Kind of weird, but it did. In this version the class constructors were methods with the same class name:

class Foo {

    function Foo() {

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

When PHP5 was launched and PHP Object Orientation rewritten and enhanced, the magic method was introduced __construct() to be a builder.

For 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 in which version of PHP 5 this started to be "forbidden". Quote because this fragment running in my PHP 5.4.14 just fire a Strict Standards saying that it is not possible to redefine an already defined constructor.

  • 4

    According to the manual from the 5.3.3 the method with the same class name is not treated as a constructor.

  • To put code below the list you need 8 spaces. If you want to break the list to be able to code with 4, put a comment <!-- br --> in the middle. It is best explained in the section of Code in the formatting guide.

  • I always curl up when I put code under the list >.<

Browser other questions tagged

You are not signed in. Login or sign up in order to post.