tl; dr — Не ограничивай себя одним конструктором в классе. Используй статические фабричные методы.
PHP позволяет использовать только один конструктор в классе, что довольно раздражительно. Вероятно, мы никогда не получим нормальную возможность перегрузки конструкторов в PHP, но кое-что сделать все же можно. Для примера возьмем простой класс, хранящий значение времени. Какой способ создания нового объекта лучше:
<?php
$time = new Time("11:45");
$time = new Time(11, 45);
<?php
final class Time
{
private $hours, $minutes;
public function __construct($timeOrHours, $minutes = null)
{
if(is_string($timeOrHours) && is_null($minutes)) {
list($this->hours, $this->minutes) = explode($timeOrHours, ':', 2);
} else {
$this->hours = $timeOrHours;
$this->minutes = $minutes;
}
}
}
<?php
$minutesSinceMidnight = 705;
$time = new Time($minutesSinceMidnight);
<?php
$time = new Time("11", "45");
<?php
final class Time
{
private $hours, $minutes;
public function __construct($hours, $minutes)
{
$this->hours = (int) $hours;
$this->minutes = (int) $minutes;
}
public static function fromString($time)
{
list($hours, $minutes) = explode($time, ':', 2);
return new Time($hours, $minutes);
}
public static function fromMinutesSinceMidnight($minutesSinceMidnight)
{
$hours = floor($minutesSinceMidnight / 60);
$minutes = $minutesSinceMidnight % 60;
return new Time($hours, $minutes);
}
}
<?php
final class Time
{
private $time;
public function __construct($hours, $minutes)
{
$this->time = "$hours:$minutes";
}
public static function fromString($time)
{
list($hours, $minutes) = explode($time, ':', 2);
return new Time($hours, $minutes);
}
// ...
}
<?php
final class Time
{
private $hours, $minutes;
// Не удаляем пустой конструктор, т.к. это защитит нас от возможности создать объект извне
private function __construct(){}
public static function fromValues($hours, $minutes)
{
$time = new Time;
$time->hours = $hours;
$time->minutes = $minutes;
return $time;
}
// ...
}
<?php
$time1 = Time::fromValues($hours, $minutes);
$time2 = Time::fromString($time);
$time3 = Time::fromMinutesSinceMidnight($minutesSinceMidnight);
<?php
$customer = new Customer($name);
// В реальной жизни мы не используем такую терминологию
// Мне кажется, что так будет лучше:
$customer = Customer::fromRegistration($name);
$customer = Customer::fromImport($name);
К сожалению, не доступен сервер mySQL