Исключения PHP в классах

Я пишу веб-приложение (PHP) для своего друга и решил использовать мой ограниченный тренинг OOP с Java.

Мой вопрос – это лучший способ отметить в моем классе / приложении, что определенные критические вещи не удались, не нарушив мою страницу.

Моя проблема заключается в том, что у меня есть объект SummerCamper, который принимает camper_id, поскольку это аргумент для загрузки всех необходимых данных в объект из базы данных. Скажите, что кто-то указывает camper_id в строке запроса, которая не существует, я передаю ее в конструктор объектов и сбой загрузки. В настоящее время я не вижу способа вернуть false из конструктора.

Я прочитал, что могу сделать это с помощью Исключения, выбрасывая исключение, если в базе данных нет записей, или если какая-либо проверка не выполняется при вводе camper_id из приложения и т. Д.

Тем не менее, я действительно не нашел отличный способ предупредить мою программу о том, что загрузка объекта не удалась. Я попытался вернуть false из CATCH, но Object по-прежнему сохраняется на моей php-странице. Я понимаю, что могу поместить переменную $ is_valid = false, если загрузка не удалась, а затем проверить объект с помощью метода get, но я думаю, что могут быть лучшие способы.

Каков наилучший способ достижения существенного завершения объекта, если сбой нагрузки? Должен ли я загружать данные в объект извне конструктора? Есть ли какая-то модель дизайна, на которую я должен смотреть?

Любая помощь будет оценена по достоинству.

function __construct($camper_id){ try{ $query = "SELECT * FROM campers WHERE camper_id = $camper_id"; $getResults = mysql_query($query); $records = mysql_num_rows($getResults); if ($records != 1) { throw new Exception('Camper ID not Found.'); } while($row = mysql_fetch_array($getResults)) { $this->camper_id = $row['camper_id']; $this->first_name = $row['first_name']; $this->last_name = $row['last_name']; $this->grade = $row['grade']; $this->camper_age = $row['camper_age']; $this->camper_gender = $row['gender']; $this->return_camper = $row['return_camper']; } } catch(Exception $e){ return false; } } 

Конструктор в PHP всегда будет возвращать void . Эта

 public function __construct() { return FALSE; } 

не будет работать. Выбрасывание исключения в конструкторе

 public function __construct($camperId) { if($camperId === 1) { throw new Exception('ID 1 is not in database'); } } 

прекратит выполнение скрипта, если вы не поймаете его где-нибудь

 try { $camper = new SummerCamper(1); } catch(Exception $e) { $camper = FALSE; } 

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

 class SummerCamper { protected function __construct($camperId) { if($camperId === 1) { throw new Exception('ID 1 is not in database'); } } public static function create($camperId) { $camper = FALSE; try { $camper = new self($camperId); } catch(Exception $e) { // uncomment if you want PHP to raise a Notice about it // trigger_error($e->getMessage(), E_USER_NOTICE); } return $camper; } } 

Таким образом, вы можете сделать

 $camper = SummerCamper::create(1); 

и получить FALSE в $camper когда $camper_id не существует. Поскольку статика считается вредной , вместо этого вы можете использовать Factory.

Другим вариантом было бы полностью SummerCamper доступ к базе данных от SummerCamper . В принципе, SummerCamper – это Сущность, которая должна SummerCamper только о вещах SummerCamper . Если вы даете ему знания о том, как упорствовать, вы фактически создаете ActiveRecord или RowDataGateway . Вы можете использовать подход DataMapper :

 class SummerCamperMapper { public function findById($id) { $camper = FALSE; $data = $this->dbAdapter->query('SELECT id, name FROM campers where ?', $id); if($data) { $camper = new SummerCamper($data); } return $camper; } } 

и ваше лицо

 class SummerCamper { protected $id; public function __construct(array $data) { $this->id = data['id']; // other assignments } } 

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

Чтобы добавить к ответам других людей, имейте в виду, что вы можете использовать различные типы исключений из одного метода и обрабатывать их по-разному:

 try { $camper = new SummerCamper($camper_id); } catch (NoRecordsException $e) { // handle no records } catch (InvalidDataException $e) { // handle invalid data } 

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

 try { $camper = new SummerCamper($id); $camper->display(); } catch (NonexistentCamper $ex) { handleFailure($ex); }