2010-02-06 3 views
47

У меня есть этот код. Возможно ли, чтобы конструктор объекта User каким-то образом потерпел неудачу, так что $this->LoggedUser присваивается значение NULL, и объект освобождается после возврата конструктора?PHP-конструктор для возврата NULL

$this->LoggedUser = NULL; 
if ($_SESSION['verbiste_user'] != false) 
    $this->LoggedUser = new User($_SESSION['verbiste_user']);  
+7

Великий первый вопрос, кстати. –

+0

Я видел некоторую популярную CMS, которая возвращает FALSE в конструкторе. Что с этим?!?! – loungerdork

+1

Просто подумал, что я звоню здесь ради документации. Поскольку дата так далеко назад, возможно, что CMS, которую вы видите, была построена для PHP4. PHP4 используется для того, чтобы разрешить много плохих вещей, не в последнюю очередь позволяющих пользователю переписать $ this в именованном конструкторе (например, $ this = false). – techdude

ответ

62

Предполагая, что вы используете PHP 5, вы можете бросить исключение в конструкторе:

class NotFoundException extends Exception {} 

class User { 
    public function __construct($id) { 
     if (!$this->loadById($id)) { 
      throw new NotFoundException(); 
     } 
    } 
} 

$this->LoggedUser = NULL; 
if ($_SESSION['verbiste_user'] != false) { 
    try { 
     $this->LoggedUser = new User($_SESSION['verbiste_user']); 
    } catch (NotFoundException $e) {} 
} 

Для ясности, вы можете обернуть это в статике заводской метод:

class User { 
    public static function load($id) { 
     try { 
      return new User($id); 
     } catch (NotFoundException $unfe) { 
      return null; 
     } 
    } 
    // class body here... 
} 

$this->LoggedUser = NULL; 
if ($_SESSION['verbiste_user'] != false) 
    $this->LoggedUser = User::load($_SESSION['verbiste_user']); 

Как в стороне, некоторые версии PHP 4 позволили вам установить $ this в NUL L внутри конструктора, но я не думаю, что это когда-либо официально санкционировалось, и «функция» была в конечном итоге удалена.

+4

+1 IMO, это правильный способ OO, указывающий на неспособность построить объект. –

+1

Это зависит от характера отказа. Если это было исключением, да. Если параметр конструктору не соответствует критерию, на мой взгляд нет. –

+5

Пекка, я не уверен, какие «плохие параметры» не будут исключением? Если вы не можете создать допустимый объект с определенным набором параметров, безусловно исключительным, и должны вызывать исключение? Можете ли вы привести пример, чтобы прояснить различие, о котором вы думаете? (Я вижу, что вы делаете в ответ ниже, это было бы полезно здесь, но я не могу отредактировать ваш комментарий!) –

11

AFAIK это не может быть сделано, new всегда возвращает экземпляр объекта.

Что я обычно делаю, чтобы обойти это:

  • Добавление ->valid булева флаг на объект, который определяет, был ли успешно загружен или не является объект. Конструктор будет установлен флаг

  • Создание функции-оболочки, которая выполняет команду new, возвращает новый объект на успех или на неудачу разрушает его и возвращает false

-

function get_car($model) 
     { 
     $car = new Car($model); 
     if ($car->valid === true) return $car; else return false; 
    } 

Мне было бы интересно узнать об альтернативных подходах, но я не знаю.

+0

Спасибо за разъяснение. Так что в принципе я мог бы просто создать новую команду в попытке ...catch и затем создать исключение в конструкторе? – Tibor

+1

Хороший вопрос! Я думаю, вы * можете *, но это на самом деле не подходит для меня. Если я создам объект автомобиля с моделью «Форд», просто может быть, что в базе данных нет модели этой модели. Это не совсем то, для чего были разработаны * исключения *. Это скорее ожидаемое условие. Мне было бы интересно узнать, какие другие ответы возникают, что рассматривается как «правильный» способ справиться с этим. –

+0

это делает вещь грязным способом, проверьте ответ @ jaz303 – minhajul

3

Когда конструктор не работает по какой-либо неизвестной причине, он не вернет значение NULL или FALSE, но оно выдает исключение. Как и все с PHP5. Если вы не обрабатываете исключение, скрипт прекратит выполнение с ошибкой Uncaught Exception.

+1

Когда конструктор выдает исключение? Когда он возвращает false? Или вы имеете в виду, что конструктор должен генерировать исключение, если определенное условие не может быть выполнено'? –

+1

Ваш конструктор должен исключить исключение. – Tom

5

Рассматривайте это так. Когда вы используете new, вы получаете новый объект. Период. То, что вы делаете, - это функция, которая ищет существующего пользователя и возвращает ее при обнаружении. Лучше всего это выразить, вероятно, статическую функцию класса, такую ​​как User :: findUser(). Это также можно расширить, когда вы получаете классы из базового класса.

+0

Это звучит наиболее логично, да. Я только начал программирование OO в PHP, поэтому я не совсем уверен, как правильно обрабатывать вещи. – Tibor

3

может быть что-то вроде этого:

class CantCreateException extends Exception{ 
} 

class SomeClass { 
    public function __construct() { 
     if (something_bad_happens) { 
      throw (new CantCreateException()); 
     } 
    } 
} 

try{ 
    $obj = new SomeClass(); 
} 
catch(CantCreateException $e){ 
    $obj = null; 
} 
if($obj===null) echo "couldn't create object"; 
//jaz303 stole my idea an wrap it into a static method 
4

Завод может быть полезным здесь:

class UserFactory 
{ 
    static public function create($id) 
    { 
     return (
      filter_var( 
       $id, 
       FILTER_VALIDATE_INT, 
       [ 'options' => [ 'min_range' => 1, ] ] 
      ) 
       ? new User($id) 
       : null 
     ); 
    } 
} 
Смежные вопросы