Php 捕获异常时手动终止应用程序?
我有一个连接类,它在我构建数据库时初始化数据库凭据 每当此操作失败时,它会引发一个异常,即无法设置凭据,因为文件为空或未设置变量 现在没有设置变量 但是我仍然可以调用该对象来调用该类中的其他函数,这是我不希望的,因为如果没有变量,这是不可能的。像这样:Php 捕获异常时手动终止应用程序?,php,oop,exception,Php,Oop,Exception,我有一个连接类,它在我构建数据库时初始化数据库凭据 每当此操作失败时,它会引发一个异常,即无法设置凭据,因为文件为空或未设置变量 现在没有设置变量 但是我仍然可以调用该对象来调用该类中的其他函数,这是我不希望的,因为如果没有变量,这是不可能的。像这样: $connection = new Connection(); //Causes exception because variables aren't set $connection->initialize(); //Should not
$connection = new Connection(); //Causes exception because variables aren't set
$connection->initialize(); //Should not be ran, because the variables aren't set. Application shouldn't continue as well.
$connection->doFurtherThings(); //Which shouldn't be run as well, because the application couldn't go further without a db connection
当我捕获异常并且不让值初始化时,发生这种情况的原因是什么
public function __construct() {
try {
require "Configuration.php";
$credentials = new Configuration('config.ini'); //Doesn't matter. just sets the configuration file
$credential = $credentials->getItems(); //Gets the items
if (isset($credential['engine'], $credential['host'], $credential['dbname'], $credential['username'], $credential['password'])) {
$this->engine = $credential['engine'];
$this->host = filter_var($credential['host'], FILTER_VALIDATE_IP);
$this->dbname = $credential['dbname'];
$this->username = $credential['username'];
$this->password = $credential['password'];
} else {
throw new Exception("Login credentials aren't not set");
}
} catch (Exception $e) {
echo $e->getMessage();
}
}
我是否必须自己在
捕获(异常)
的内部die()
应用程序?我认为异常就是这样做的。正如我在评论中所说,应该由调用方决定如何处理异常,而不是被调用的类
在构造函数中,如果出现问题,应该抛出异常,并让调用类决定如何处理该异常
public function __construct() {
require "Configuration.php";
$credentials = new Configuration('config.ini'); //Doesnt matter. just sets the configuration file
$credential = $credentials->getItems(); //Gets the items
if (isset($credential['engine'], $credential['host'], $credential['dbname'], $credential['username'], $credential['password'])) {
$this->engine = $credential['engine'];
$this->host = filter_var($credential['host'], FILTER_VALIDATE_IP);
$this->dbname = $credential['dbname'];
$this->username = $credential['username'];
$this->password = $credential['password'];
} else {
throw new Exception("Login credential's arent not set");
}
}
现在它的调用者决定在发生异常时应该做什么,例如停止执行:
try {
$connection = new Connection(); //Causes exception because variables arent set
$connection->initialize(); //Should not be ran, because the variables arent set. Application shouldnt continue aswell.
$connection->doFurtherThings();
} catch (Exception $e) {
exit($e->getMessage()); // Login credential's arent not set
}
为了更好地说明这一点,我写了一篇文章,作为旁注,您应该真正了解执行流是如何工作的。正如我在评论中所说,如何处理异常应该由调用方决定,而不是被调用的类 在构造函数中,如果出现问题,应该抛出异常,并让调用类决定如何处理该异常
public function __construct() {
require "Configuration.php";
$credentials = new Configuration('config.ini'); //Doesnt matter. just sets the configuration file
$credential = $credentials->getItems(); //Gets the items
if (isset($credential['engine'], $credential['host'], $credential['dbname'], $credential['username'], $credential['password'])) {
$this->engine = $credential['engine'];
$this->host = filter_var($credential['host'], FILTER_VALIDATE_IP);
$this->dbname = $credential['dbname'];
$this->username = $credential['username'];
$this->password = $credential['password'];
} else {
throw new Exception("Login credential's arent not set");
}
}
现在它的调用者决定在发生异常时应该做什么,例如停止执行:
try {
$connection = new Connection(); //Causes exception because variables arent set
$connection->initialize(); //Should not be ran, because the variables arent set. Application shouldnt continue aswell.
$connection->doFurtherThings();
} catch (Exception $e) {
exit($e->getMessage()); // Login credential's arent not set
}
为了更好地说明这一点,我给您写了一封信,作为旁注,您应该真正了解执行流是如何工作的。我知道您在做什么 您正在尝试使用配置对象。这太棒了,这正是你应该做的。然而,你怎么做并不是最好的方法 在使用配置对象的代码之前,您应该先构造配置对象,并检查该对象是否已全部设置且有效,然后再尝试在另一个对象中使用该对象。在您的系统上下文中,消费对象不负责验证来自内部对象的数据 首先也是最重要的是,您的
凭证
对象。我们在这里创建了一个接口,它说“任何凭证对象都必须有一个validate()
方法,如果凭证无效,该方法将抛出一个异常
interface Credentials
{
/**
* @throws CredentialsValidationException
*/
public function validate();
}
为什么会有一个validate()
方法?因为不应该在对象的构造函数中放置业务逻辑。未来的开发人员知道他们可以调用validate()
,这将让他们知道对象是否具有有效的凭据
现在进入您的具体配置。在这个配置
对象中,您声明:“要拥有有效的对象,用户必须提供主机、数据库名称、引擎、用户名和密码
class Configuration implements Credentials
{
protected $host;
protected $engine;
protected $dbName;
protected $username;
protected $password;
/**
* We're NOT validating here, we're just stating that this object requires
* these parameters to become an actual object
*/
public function __construct($host, $engine, $dbName, $username, $password)
{
$this->host = $host;
$this->dbName = $dbName;
$this->engine = $engine;
$this->username = $username;
$this->password = $password;
}
/**
* As our Credentials interface requires, validate everything
*
* {@inheritDoc}
*/
public function validate()
{
// Check this is a valid object
// Consider using a Validation object passed in via Dependency Injection
// If it's not a valid object, throw a CredentialsValidationException
}
}
现在,我们已经将拥有有效凭证的责任转移到配置(凭证)对象本身。下一步是实际使用此对象
class Connection
{
protected $credentials;
/**
* @param Credentials $credentials
*/
public function __construct(Credentials $credentials)
{
$this->credentials = $credentials;
}
}
在连接
对象中,您声明需要实现凭证
接口的任何对象。因此,您不仅获得了在这里使用的能力,而且还将应用程序配置与类分离(您最初尝试做的事情)
你现在也在使用;通过构造函数/方法传入对象,以供消费类使用。这意味着您的代码是解耦的,您可以在应用程序中的任何其他位置或完全不同的库中使用这些对象(如果您愿意)
以下是您现在可以使用的对象API:
$credentials = new Configuration('host', 'engine', 'dbname', 'user', 'pass');
try
{
$credentials->validate();
$connection = new Connection($credentials);
// @todo Whatever else you want to do
}
catch (CredentialsValidationException $e)
{
// @todo Log the error here with a logger object (check out monolog)
// @todo Make sure the user viewing the code gets a nice response back
}
如果您想强制一个有效的连接
对象,只需在使用它的方法中调用Configuration::validate()
(但不是构造函数)。您可以使用工厂来构建对象,并强制调用validate。做你喜欢做的
关于死亡,不要在申请中死亡。做您需要做的事情,让开发人员(您)和用户(您或其他人)以不同的方式了解错误。通常,您将为开发人员登录,并为用户发送消息。捕获异常并回显问题所在
结束语,这是一种方法。您可以使用验证
对象。您可以将validate()
改为isValid()
,然后只返回true/false。您可以进行连接
对象调用validate()
/isValid()
——这取决于您的体系结构和您想要执行的操作。关键是您已经将这两个类解耦,并同时使用了最佳实践
最后一个想法-确保像我在代码中那样添加phpdoc。未来的开发者不会想杀了你。我建议您查看一个IDE,它会抛出一些小提示,比如,当您在代码中做了一些愚蠢的事情时。我知道您在做什么
您正在尝试使用配置对象。这太棒了,这正是你应该做的。然而,你怎么做并不是最好的方法
在使用配置对象的代码之前,您应该先构造配置对象,并检查该对象是否已全部设置且有效,然后再尝试在另一个对象中使用该对象。在您的系统上下文中,消费对象不负责验证来自内部对象的数据
首先也是最重要的是,您的凭证
对象。我们在这里创建了一个接口,它说“任何凭证对象都必须有一个validate()
方法,如果