我正在为我的朋友编写一个Web应用程序(PHP),并决定使用Java提供的有限OOP培训。
我的问题是,在我的课程/应用程序中,如果没有真正破坏我的页面,那么特定的关键事项会失败,这是最好的方法。
我的问题是我有一个Object“SummerCamper”,它接受一个camper_id作为参数,将所有必要的数据从数据库加载到对象中。假设某人在查询字符串中指定了一个不存在的camper_id,我将其传递给我的对象构造函数并且加载失败。我目前没有看到从构造函数返回false的方法。
我已经读过我可能会使用Exceptions执行此操作,如果在数据库中找不到任何记录,或者如果从应用程序等输入camper_id时某些验证失败,则抛出异常。
但是,我还没有找到一个很好的方法来警告我的程序对象加载失败。我尝试从CATCH中返回false但是对象仍然存在于我的php页面中。我知道如果加载失败我可以放置变量$ is_valid = false然后使用get方法检查Object但我认为可能有更好的方法。
如果加载失败,实现对象基本终止的最佳方法是什么?我应该从构造函数外部将数据加载到对象中吗?我应该研究一些设计模式吗?
任何帮助都将不胜感激。
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;
}
}
答案 0 :(得分:14)
constructor in PHP将始终返回void
。此
public function __construct()
{
return FALSE;
}
不起作用。构造函数中的Throwing an Exception
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;
}
你可以将上面的代码移到static method的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
。自statics are considered harmful起,您可能希望使用Factory。
另一种选择是将数据库访问与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有点复杂,但它为您提供了解耦代码,最终可维护性和灵活性。看看SO,关于这些主题有很多问题。
答案 1 :(得分:5)
要添加其他人的答案,请记住,您可以从单个方法中抛出不同类型的异常,并以不同方式处理它们:
try {
$camper = new SummerCamper($camper_id);
} catch (NoRecordsException $e) {
// handle no records
} catch (InvalidDataException $e) {
// handle invalid data
}
答案 2 :(得分:1)
从构造函数中抛出异常可能是正确的方法。您可以在适当的位置捕获此信息,并采取必要的操作(例如显示错误页面)。由于您没有显示任何代码,因此不清楚您捕获异常的位置或原因似乎不起作用。
答案 3 :(得分:1)
try {
$camper = new SummerCamper($id);
$camper->display();
} catch (NonexistentCamper $ex) {
handleFailure($ex);
}