View Source

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{zone-template-instance:ZFPROP:Proposal Zone Template}

{zone-data:component-name}
Zend_Exception previous exception - Marc Bennewitz
{zone-data}

{zone-data:proposer-list}
[Marc Bennewitz|http://framework.zend.com/wiki/display/~mabe]
{zone-data}

{zone-data:liaison}
TBD
{zone-data}

{zone-data:revision}
1.0 - 14 July 2009: Initial Draft.
1.1 - 15 July 2009: Zend_Exception::getPrevious have to be final
1.2 - 15 July 2009: changed UC-01 and added UC-02
1.3 - 13 Aug 2009: Milestone 3 & 4 finished
{zone-data}

{zone-data:overview}
Implements the PHP 5.3.0 way of previous exceptions on the Zend_Exceptions class if php version is lower than php 5.3.0
to have the same API for all php versions
{zone-data}

{zone-data:references}
* [Exception|http://www.php.net/manual/en/class.exception.php]
{zone-data}

{zone-data:requirements}
* This component *will* implement the php 5.3 way of previous exceptions.
{zone-data}

{zone-data:dependencies}
there are no dependencies
{zone-data}

{zone-data:operation}
This proposal will implement previous exceptions in php < 5.3 to allow previous exceptions in all supported php versions by zend framework.
{zone-data}

{zone-data:milestones}
* Milestone 1: \[DONE\]: Finish proposal
* Milestone 2: \[DONE\]: Working prototype
* Milestone 3: \[DONE\]: Prototype checked into the incubator
* Milestone 4: \[DONE\]: Unit tests exist finished and component is working
* Milestone 5: \[DONE\]: Initial documentation exists
* Milestone 6: Changed related components
* Milestone 7: Moved to core.
{zone-data}

{zone-data:class-list}
* Zend_Exception
{zone-data}

{zone-data:use-cases}
||UC-01||
{code}
/**
* download data to a temp file and if completed rename this file
*/
function download($url, $file) {
try {
$tmpFile = tempnam("/tmp", "FOO");
if ( !($readFp = @fopen($url, 'rb')) ) {
$lastErr = error_get_last();
throw new Zend_Component_Exception('Failed to open url "'.$url.'": ' . $lastErr['message']);
}
if ( !($writeFp = @fopen($tmpFile, 'wb')) ) {
$lastErr = error_get_last();
throw new Zend_Component_Exception('Failed to open temporary file "'.$tmpFile.'": ' . $lastErr['message']);
}

while ( !foef($readFp) ) {
if ( ($buffer = @fread($readFp, 4096)) === false ) {
$lastErr = error_get_last();
throw new Zend_Component_Exception('Failed to download complete content from "'.$url.'": ' . $lastErr['message']);
}
if ( @fwrite($writeFp, $buffer) === false ) {
$lastErr = error_get_last();
throw new Zend_Component_Exception('Failed to write content to "'.$tmpFile.'": ' . $lastErr['message']);
}
}

if (!@rename($tmpFile, $file)) {
$lastErr = error_get_last();
throw new Zend_Component_Exception('Failed to rename temporary file to "'.$file.'": ' . $lastErr['message']);
}

@fclose($readFp);
@fclose($writeFp);

} catch (Zend_Component_Exception $e) {
@fclose($readFp);
@fclose($writeFp);

// if incomplete download or failed rename -> remove temporary file
// This could be failed and now you have two different exceptions
if (file_exists($tmpFile) && !@unlink($tmpFile)) {
// throw a new exception within the previous exception
$lastErr = error_get_last();
throw new Zend_Component_Exception('Failed to remove temporary file "'.$tmpFile.'": ' . $lastErr['message'], $e->getCode(), $e);
} else {
throw $e;
}
}
}
{code}

||UC-02||
{code}
abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
{

// ....

public function query($sql, $bind = array())
{
// ...

try {
return parent::query($sql, $bind);
} catch (PDOException $e) {
/**
* @see Zend_Db_Statement_Exception
*/
require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception('Query failed by previous exception', $e->getCode(), $e);
}
}

// ...

}
{code}
{code}
try {
$db->query($sql);
} catch (Zend_Db_Statement_Exception $e) {
echo $e->__toString();
}
{code}
{zone-data}

{zone-data:skeletons}
{code}
if (version_compare(PHP_VERSION, '5.3.0', '<')) {

class Zend_Exception extends Exception
{

private $_previous = null;

/**
* Construct the exception
*
* @param string $msg
* @param int $code
* @param Exception $previous
*/
public function __construct($msg = '', $code = 0, Exception $previous = null) {
parent::__construct($msg, $code);
$this->_previous = $previous;
}

/**
* Returns previous Exception
*
* @return Exception|null
*/
final public function getPrevious() {
return $this->_previous;
}

/**
* String representation of the exception
*
* @return string
*/
public function __toString() {
if ($this->getPrevious()) {
return $this->getPrevious()->__toString() . "\n\nNext " . parent::__toString();
} else {
return parent::__toString();
}
}

}

} else {

class Zend_Exception extends Exception
{}

}
{code}
{zone-data}

{zone-template-instance}]]></ac:plain-text-body></ac:macro>