【问题标题】:PHP5, Exception in destructorPHP5,析构函数中的异常
【发布时间】:2014-01-21 19:21:26
【问题描述】:

我现在正在阅读“专业的 PHP5”一书,这是 2006 年出版的。在一个例子中,他们在析构函数中抛出异常,很长一段时间我不明白为什么我在析构函数中的最后一个异常不起作用,然后我搜索了一下,发现在 PHP => 5.3 它是 不可用在析构函数中抛出异常。那么,如果在析构函数中,如果变量$needsUpdate = true; 更新我的数据库并关闭我的数据库连接,那么最好的做法是,如果无法更新数据库,我想抛出异常。例如,我在数据库类中抛出异常,但在主文件中捕获它们,如下所示:

它的类Widget:

class Widget {

    private $_id;
    private $_name;
    private $_description; private $_hDB;
    private $_needsUpdating = false;

    public function __construct($widgetID) {

        $this->_hDB = new mysqli('localhost', 'phpbook', 'Un+)J=<AaH', 'phpbook');
        if (! $this->_hDB) {
            throw new Exception('Не удалось подключится к базе данных');
        }
        $sql = "SELECT `name`, `description` FROM widgets WHERE id = '$widgetID'";
        $rs = $this->_hDB->query($sql);

        if (! $rs) {
            throw new Exception("Произошла ошибка при выборе базы данных");
        }

        if (! $rs->num_rows) {
            throw new Exception("Указаная запись в базе данных отсутствует");
        }
        $data = $rs->fetch_assoc();
        $this->_id = $widgetID;
        $this->_name = $data['name'];
        $this->_description = $data['description'];

    }

    public function getName() {
        return $this->_name;
    }

    public function getDescription() {
        return $this->_description;
    }

    public function setName($name) {
        $this->_name = $name;
        $this->_needsUpdating = true;
    }

    public function setDescription($description) {
        $this->_description = $description;
        $this->_needsUpdating = true;
    }

    public function __destruct() {
        if (! $this->_needsUpdating) {
            return;
        }

        $sql = 'UPDAT2E `widgets` SET';
        $sql .= ' `name` = "' . $this->_hDB->real_escape_string($this->_name) . '",';
        $sql .= ' `description` = "' . $this->_hDB->real_escape_string($this->_description) . '" ';
        $sql .= 'WHERE id = ' . $this->_id;


        $rs = $this->_hDB->query($sql);
        if (! $rs) {
            throw new Exception("Произошла ошибка при обновлении базы данных");
        }
        $this->_hDB->close();
    }
}

这是主文件。

try {
    $widget = new Widget(2);
    echo "Name: " . $widget->getName() . "<br />\n";
    echo "Description: " . $widget->getDescription() . "<br />\n";
    $widget->setName("Iphone 4 / 64GB");
    $widget->setDescription("New Phone, black color, blablabla");

} catch (Exception $e) {
    die("An error has occurred: " . $e->getMessage());
}

__destruct() 中的最后一个异常没有起作用。

如果更新数据库失败,有没有一种很好的方法来抛出异常?还是有其他正确的方法,我没看懂?

【问题讨论】:

  • Exceptions seem to work in the destructor 但您并没有在代码中的任何位置销毁该对象 - 那么您的问题到底是什么?
  • 不,它会在运行所有代码后自动销毁,例如,如果不是 throw new Exception("Произошла ошибка при обновлении базы данных"); set echo Произошла ошибка при обновлении базы данных; 这将是 SQL 查询中的工作原因我在 UPDAT2E 中设置了错误,所以为什么 echo 和所有其他工作正常但不能抛出异常,我知道我可以使用模具(“错误”);和类似的东西,但非常有趣的是如何正确地做到这一点。
  • 哦...对不起我的错。我在某处读到,销毁将在所有进程后自动调用,对不起,我刚开始学习 OOP。我在我的代码中添加了unset($widget);,我得到了最后一个异常。例如,谢谢 :) 所以现在我对我的代码是否正确以及最后一个异常有点怀疑。而且我不明白为什么我的所有 SQL 查询都没有这个 unset,但只有在 unset 之后才抛出异常。
  • this solution 有帮助吗?
  • 析构函数中的 SQL DML 代码?你确定这本书是给“专业人士”的吗?为什么要这么做?

标签: php exception destructor


【解决方案1】:

析构函数中的异常(可以)导致致命错误。文档在这里说明了这一点:construct">http://us.php.net/_construct

注意: 尝试从析构函数(在脚本终止时调用)抛出异常会导致致命错误。

在大多数情况下,你会得到这样的结果:

PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0

一个好方法不是重新发明这个轮子并采取例如Doctrine (http://www.doctrine-project.org/) 可以帮助您完成这项任务。即使您不能使用该软件,您也可以查看资源以了解 Benjamin 是如何做到的。查看与您在问题中提到的处理有关的 EntityManager (https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/EntityManager.php) 和 UnitOfWork (https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/UnitOfWork.php)。

【讨论】:

  • 好的,谢谢您的回答。我想这本书后面会出现类似“嘿,伙计,你还记得在第一章中我们在析构函数中抛出异常吗?所以请不要这样做,这是一个不好的例子,只是为了你的理解”。但都一样,谢谢。
猜你喜欢
  • 1970-01-01
  • 2017-08-16
  • 2012-04-11
  • 1970-01-01
  • 2013-08-13
  • 2014-07-06
  • 2015-08-26
  • 2013-11-07
相关资源
最近更新 更多