Правильный способ обработки возвращаемых типов PHP 7

Я занят созданием приложения, и я хочу использовать возвращаемые типы PHP 7. Теперь я прочитал на php.net, что было конструктивным решением о том, что ему не разрешено возвращать null когда определен тип возврата.

Каков правильный способ справиться с этим?

Одним из вариантов является блок try … catch:

 public function getMyObject() : MyObject { return null; } try { getMyObject(); } catch(Exception $e) { //Catch the exception } 

У меня нет хорошего представления об этом, потому что мой код будет огромной попыткой … catch block, так как мне нужно написать try … catch block для каждого метода, который возвращает объект.

Шаблон нулевого объекта является хорошим решением для этого, но мне не нравится идея создания NullObject для каждого объекта в моем приложении. Есть ли правильный способ сделать это?

У меня нет хорошего представления об этом, потому что мой код будет огромным блоком try / catch, так как мне нужно написать блок try / catch для каждого метода, который возвращает объект.

Альтернативой (с вашим кодом) было бы всегда проверять возвращаемое значение для null чтобы не получить ошибки от использования null в качестве объекта.

Использование исключений более выразительно и делает ошибки видимыми рано, что хорошо. Поэтому либо убедитесь, что ваш метод всегда возвращает объект, либо генерирует исключение, если он не может выполнить свой контракт. В противном случае тип возврата не имеет реального значения.

Если ваш код ожидает возврата экземпляра класса, в данном случае MyObject , но это не так, то это действительно исключение и должно рассматриваться как таковое.

Однако вы должны выбросить это исключение самостоятельно.

 public function getMyObject() : MyObject { throw new MyCustomException("Cannot get my object"); } 

Затем вы можете поймать это конкретное исключение и действовать соответствующим образом.

Вы можете использовать тип данных Option .

Это тип, который имеет что- Something или Nothing как завернутое значение.

Вы можете найти более подробное описание здесь и одну из открытых реализаций в PHP здесь

PS, пожалуйста, не используйте исключения, параметры или дополнительные методы для такой логики, это неправильный инструмент для работы.

В настоящее время это невозможно, хотя, как уже упоминалось, есть RFC, которые могут решить проблему для будущих версий.

На данный момент ваши варианты:

1.Заверните тип возврата из вашей сигнатуры метода:

 public function getMyObject() { return null; } 

2.Throw и поймать исключение (в соответствии с ответом @ NiettheDarkAbsol):

 public function getMyObject() : MyObject { throw new MyCustomException("Cannot get my object"); } 

3.Refactor для двух методов:

 private $myObject; //TODO think of a better method name public function canGetMyObject() : bool { $this->myObject = new myObject(); return true; } public function getMyObject() : MyObject { if(!$this->myObject){ throw new MyCustomException("Cannot get my object"); } return $this->myObject; } 

Код звонка:

 if($cls->canGetMyObject()){ $myObject = $cls->getMyObject(); } - if($cls->canGetMyObject()){ $myObject = $cls->getMyObject(); } 

4.Используйте тип возврата bool и параметр out:

 public function tryGetMyObject(&$out) : bool { $out = new myObject(); return true; } 

Код звонка:

 $myObject = null; if($cls->tryGetMyObject($myObject)){ $myObject->someMethod(); //$myObject is an instance of MyObject class } - $myObject = null; if($cls->tryGetMyObject($myObject)){ $myObject->someMethod(); //$myObject is an instance of MyObject class } 

3-й и 4-й варианты действительно заслуживают рассмотрения в тех случаях, когда ожидается нулевой возврат и частота, так что накладные расходы исключений являются фактором. Вероятно, вы обнаружите, что это фактически не применяет все это часто, а исключения – это путь вперед

Я собирался попросить об этом. Я не вижу большого смысла для этого.

Если у меня есть следующий пример кода, чтобы найти пользователя по имени:

 <?php class User { protected $name; /** * User constructor. * * @param $name */ public function __construct(string $name) { $this->name = $name; } /** * @return mixed */ public function getName() : string { return $this->name; } } function findUserByName(string $name, array $users) : User { foreach ($users as $user) { if ($user->getName() == $name) { return $user; } } return null; } $users = [ new User('John'), new User('Daniel') ]; $user = findUserByName('John', $users); echo $user->getName()."\n"; $user2 = findUserByName('Micheal', $users); 

Я хотел бы сообщить Php, что я могу получить либо Пользователь, либо null. Теперь мне нужно обернуть его всегда в блок catch catch, и я не вижу смысла объявлять тип возвращаемого значения в этом случае. С другой стороны, если моя функция findUserByName будет сложной, я могу случайно вернуться, например, к имени пользователя вместо полного пользовательского объекта, поэтому я хотел бы иметь тип возвращаемого типа.

Я думаю, что гораздо более разумным было бы определение нескольких типов возврата для функций. Иногда вы создаете функцию, возвращающую один объект или массив объектов, и было бы неплохо определить, эта функция должна возвращать, например, User или массив пользователей: User[] .

В случае OP (а также my) мы могли бы объявить возвращаемый тип как User, null и это решило бы проблему.

Начиная с PHP7.1, вы можете использовать типы возвращаемых значений:

 public function getMyObject(): ?MyObject { return null; } 

http://php.net/manual/en/migration71.new-features.php