Intereting Posts
Как установить cookie в wordpress? MongoDB: запрос нескольких коллекций с двумя запросами? Я не могу подключить свою страницу PHP к моему тестовому серверу SQL и базе данных Нажатие текстового тега для генерации нового хэша mysqli – вызов ошибки fetch_Array для функции-члена fetch_array () для не-объекта mysqli Подтверждение ввода пользователя, на стороне клиента или на стороне сервера? urlencode только каталог и имена файлов URL-адреса Как передать массив из контроллера для просмотра (Laravel 5)? php сравнить два вложенных массива и предсказать разницу PHP array_key_exists и UTF 8 как проверить несколько файлов типа ввода с помощью модуля проверки правильности jquery Zend Framework 2 – стратегия Hydrator для отношений Doctrine не работает Как обновить файл на Google Диске v3 PHP PHP Может ли клиент когда-либо устанавливать переменные $ _SESSION? Ошибка аутентификации почты PEAR при отправке писем

Возврат значения в функции конструктора класса

Пока у меня есть класс PHP с конструктором

 public function __construct ($identifier = NULL) { // Return me. if ( $identifier != NULL ) { $this->emailAddress = $identifier; if ($this->loadUser() ) return $this; else { // registered user requested , but not found ! return false; } } 

функциональность loadUser – это поиск базы данных для определенного адреса электронной почты. Когда я устанавливаю идентификатор на какой-то адрес электронной почты, я уверен, что его нет в базе данных; первый IF будет принят, и переходит к первому ELSE. здесь конструктор должен возвращать FALSE; но вместо этого он возвращает объект класса со всеми значениями NULL!

как я могу предотвратить это? благодаря

РЕДАКТИРОВАТЬ:

спасибо всем за ответы. это было довольно быстро! Я вижу, что путь ООП заключается в том, чтобы выбросить исключение. Так что бросить один, мой вопрос меняется, что я должен делать с исключением? Руководство php.net довольно запутанно!

  // Setup the user ( we assume he is a user first. referees, admins are considered users too ) try { $him = new user ($_emailAddress); } catch (Exception $e_u) { // try the groups database try { $him = new group ($_emailAddress); } catch (Exception $e_g) { // email address was not in any of them !! } } 

Конструкторы не получают возвращаемых значений; они служат целиком для создания класса.

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

 public function __construct ($identifier = NULL) { $this->emailAddress = $identifier; $this->loadUser(); } private function loadUser () { // try to load the user if (/* not able to load user */) { throw new Exception('Unable to load user using identifier: ' . $this->identifier); } } 

Теперь вы можете создать нового пользователя таким образом.

 try { $user = new User('user@example.com'); } catch (Exception $e) { // unable to create the user using that id, handle the exception } 

Конструктор предположительно создает объект. Поскольку в php булевы не считаются объектами, единственным вариантом является null. В противном случае используйте обходной путь, то есть напишите статический метод, который создает фактический объект.

 public static function CheckAndCreate($identifier){ $result = self::loadUser(); if($result === true){ return new EmailClassNameHere(); }else{ return false; } } 

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

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

 // error status property public $error = NULL; public function __construct ($identifier = NULL) { // Return me. if ( $identifier != NULL ) { $this->emailAddress = $identifier; if (!$this->loadUser() ) { // registered user requested , but not found ! $this->error = "user not found"; } } 

Когда вы создаете экземпляр объекта, вы можете проверить, имеет ли он статус ошибки:

 $obj = new MyObject($identifier); if (!empty($obj->error)) { // something failed. } 

Другая (возможно, лучшая) альтернатива заключается в том, чтобы выдать исключение в конструкторе и обернуть экземпляр в try/catch .

Лучшее, что вы можете сделать, это то, что предложил Стив. Никогда не создавайте конструкторы, которые выполняют любую другую работу, а затем назначают параметры конструктора свойствам объекта, возможно, создают некоторые по умолчанию, но ничего больше. Конструкторы предназначены для создания полностью функционального объекта. Такой объект должен всегда работать так, как ожидалось, после его создания. У пользователя есть электронная почта, имя и, возможно, некоторые другие свойства. Когда вы хотите создать экземпляр объекта пользователя, дайте все эти свойства его конструктору. Выбросы исключений тоже не очень хорошие. Исключение должно быть выбрано в исключительных условиях. Просить пользователя по электронной почте ничего исключительного, даже если вы в конечном итоге выясните, что такого пользователя нет. Исключение может быть, например, если вы попросите пользователя по электронной почте = '' (если только это не является обычным состоянием в вашей системе, но идентификатор скорее предполагает, что сообщения электронной почты являются нулевыми в этих случаях). Чтобы получить все эти свойства для объекта пользователя, у вас должен быть объект (или репозиторий, если вы предпочитаете) объект (да, объект – это плохая практика использовать статические все). Частный конструктор – это плохая практика (вы будете все равно нужен статический метод, и, как я уже сказал, статика очень плохая)

поэтому результат должен быть примерно таким:

 class User { private $name; private $email; private $otherprop; public function __construct($name, $email, $otherprop = null) { $this->name = $name; $this->email = $email; $this->otherprop = $otherprop; } } class UserRepository { private $db; public function __construct($db) { $this->db = $db; //this is what constructors should only do } public function getUserByEmail($email) { $sql = "SELECT * FROM users WHERE email = $email"; //do some quoting here $data = $this->db->fetchOneRow($sql); //supose email is unique in the db if($data) { return new User($data['name'], $data['email'], $data['otherprop']); } else { return null; } } } $repository = new UserRepository($database); //suppose we have users stored in db $user = $repository->getUserByEmail('whatever@wherever.com'); if($user === null) { //show error or whatever you want to do in that case } else { //do the job with user object } 

Видеть? без статики, без исключения, простых конструкторов и очень читаемых, проверяемых и модифицируемых

Почему бы просто не передать результаты в конструктор, необходимый для создания объекта, а не пытаться иногда скомпрометировать конструктор?

Даже если вы иногда можете его терпеть, вам все равно нужно будет проверить после вызова конструктора, чтобы убедиться, что он действительно создал, и в этих строках вы можете просто вызвать -> loadUser () и передать результаты в конструктор.

Хороший намек, который кто-то мне сказал, «всегда дает конструктору то, что ему нужно для создания объекта, не заставляйте его искать его».

 public function __construct ($emailInTheDatabase, $otherFieldNeeded) { $this->emailAddress = $emailInTheDatabase; $this->otherField = $otherFieldNeeded; } 

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

 // Setup the user ( we assume he is a user first. referees, admins are considered users too ) try { $him = new user ($_emailAddress); // check the supplied password $pass_ok = $him->auth($_Password); // check the activation status $active_ok = $him->makeActive(); } catch (Exception $e_u) { // try the groups database try { $him = new group ($_emailAddress); // check the supplied password $pass_ok = $him->auth($_Password); //var_dump ($pass_ok); // check the activation status $active_ok = $him->makeActive(); } catch (Exception $e_g) { // email address was not in any of them !! $pass_ok = false; $active_ok = false; } } 

Я бы не стал слишком много в конструкции. Вы должны рассмотреть статический функционал, который создает пользователя (фабрику) вместо того, чтобы помещать все в конструктор. Таким образом, вы все равно можете использовать свой пользовательский объект, не требуя неявной функции загрузки. Это избавит вас от боли.

 public function __construct(){} public function setIdentifier($value){ $this->identifier = $value; } public function load(){ // whatever you need to load here //... throw new UserParameterNotSetException('identifier not set'); // ... // if user cannot be loaded properly throw new UserNotFoundException('could not found user'); } public static function loadUser($identifier){ $user = new User(); $user->setIdentifier($identifier); $user->load(); return $user; } 

Использование образца:

 $user = new User(); try{ $user->setIdentifier('identifier'); $user->load(); } catch(UserParameterNotSetException $e){ //... } catch(UserNotFoundException $e){ // do whatever you need to do when user is not found } // With the factory static function: try{ $user2 = User::loadUser('identifier'); } catch(UserParameterNotSetException $e){ //... } catch(UserNotFoundException $e){ // do whatever you need to do when user is not found } 

Я очень удивлен, что в течение 4 лет ни один из 22-ки зрителей не предложил создать частный конструктор и метод, который пытается создать такой объект:

 class A { private function __construct () { echo "Created!\n"; } public static function attemptToCreate ($should_it_succeed) { if ($should_it_succeed) { return new A(); } return false; } } var_dump(A::attemptToCreate(0)); // bool(false) var_dump(A::attemptToCreate(1)); // object(A)#1 (0) {} //! new A(); - gives error 

Таким образом вы получаете либо объект, либо false (вы также можете вернуть его null). Ловить обе ситуации сейчас очень легко:

 $user = User::attemptToCreate('email@example.com'); if(!$user) { // or if(is_null($user)) in case you return null instead of false echo "Not logged."; } else { echo $user->name; // eg } 

Вы можете проверить это прямо здесь: http://ideone.com/TDqSyi

Я считаю, что мое решение более удобно использовать, чем бросать и ловить исключения.