My question is about the correct way to catch exceptions in PHP.
Based on the accompanying examples of the PHP MongoDB driver, I
have created the following script:
<?php
try {
$mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
$query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);
$rows = $mng->executeQuery("testdb.cars", $query);
foreach ($rows as $row) {
echo "$row->name : $row->price\n";
}
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
echo "In file:", $e->getFile(), "\n";
echo "On line:", $e->getLine(), "\n";
}
?>
The example is educational and meant to be run on the PHP CLI. In PHP CLI, we get all the exceptions on the console, but for didactic purposes, I wanted to catch exceptions in the try/catch block.
I have seen more Java code than PHP and therefore, catching a generic MongoDB\Driver\Exception\Exception does not look good to me. In Java, we catch specific exceptions and have multiple try/catch blocks for different kinds of exceptions.
The driver has the following Exceptions:
MongoDB\Driver\Exception\AuthenticationException
MongoDB\Driver\Exception\BulkWriteException
MongoDB\Driver\Exception\ConnectionException
MongoDB\Driver\Exception\ConnectionTimeoutException
MongoDB\Driver\Exception\Exception
MongoDB\Driver\Exception\ExecutionTimeoutException
MongoDB\Driver\Exception\InvalidArgumentException
MongoDB\Driver\Exception\LogicException
MongoDB\Driver\Exception\RuntimeException
MongoDB\Driver\Exception\SSLConnectionException
MongoDB\Driver\Exception\UnexpectedValueException
MongoDB\Driver\Exception\WriteException
Is this a kosher way to catch exceptions in PHP?
How about placing a switch statement in the catch part, and determine the exception's type with the instanceof language construct or the get_class() function?
For example:
[...]
} catch(\Exception $e) {
switch (get_class($e)) {
case 'MongoDB\Driver\Exception\AuthenticationException':
// do stuff
break;
case 'MongoDB\Driver\Exception\BulkWriteException':
//etc, etc...
}
}
At first, I would examine the return values of get_class(), to make sure you I'm comparing the result with the exact exception names.
You can add multiple catch statements
<?php
try {
$mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
$query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);
$rows = $mng->executeQuery("testdb.cars", $query);
foreach ($rows as $row) {
echo "$row->name : $row->price\n";
}
} catch (MongoDB\Driver\Exception\AuthenticationException $e) {
echo "Exception:", $e->getMessage(), "\n";
} catch (MongoDB\Driver\Exception\ConnectionException $e) {
echo "Exception:", $e->getMessage(), "\n";
} catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
echo "Exception:", $e->getMessage(), "\n";
}
?>
Adding multiple catch statement I think it's a better approach than switch. However, what if the exception isn't from these classes with a switch you should have a default case and also if you do it with multiple catches.
try {
$mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
$query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);
$rows = $mng->executeQuery("testdb.cars", $query);
foreach ($rows as $row) {
echo "$row->name : $row->price\n";
}
} catch (MongoDB\Driver\Exception\AuthenticationException $e) {
echo "AuthenticationException:", $e->getMessage(), "\n";
} catch (MongoDB\Driver\Exception\ConnectionException $e) {
echo "ConnectionException:", $e->getMessage(), "\n";
} catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
echo "ConnectionTimeoutException:", $e->getMessage(), "\n";
}catch (\Exception $e) {
echo "Exception:", $e->getMessage(), "\n";
}
Related
When I try and unserialize the following string:
a:3:{i:0;s:19:\"Sales+%2F+Customers\";i:1;s:78:\"Micro+Business+%28less+than+10+employees+%26+turnover+under+%C2%A32+million%29\";i:2;s:13:\"Manufacturing\";}
It returns false and I get the following warning:
WARNING: Error at offset 9 of 158 bytes
It was generated by calling serialize on an array though and looks valid to me though, I don't understand what the problem is?
The slashes aren't valid in this case, use stripslashes(). Demo code below:
<pre>
<?php
$x = "a:3{i:0;s:19:\"Sales+%2F+Customers\";i:1;s:78:\"Micro+Business+%28less+than+10+employees+%26+turnover+under+%C2%A32+million%29\";i:2;s:13:\"Manufacturing\";}";
echo "unserializing $x: " . PHP_EOL;
try {
print_r(unserialize($x));
echo PHP_EOL;
} catch (\Exception $e) {
echo $e->getMessage() . PHP_EOL;
}
$y = "a:3{i:0;s:19:\\\"Sales+%2F+Customers\\\";i:1;s:78:\\\"Micro+Business+%28less+than+10+employees+%26+turnover+under+%C2%A32+million%29\\\";i:2;s:13:\\\"Manufacturing\\\";}";
echo "unserializing $y: " . PHP_EOL;
try{
print_r(unserialize($y));
echo PHP_EOL;
} catch (\Exception $e) {
echo $e->getMessage() . PHP_EOL;
}
echo "unserializing stripslashes($y): " . PHP_EOL;
try{
print_r(unserialize(stripslashes($y)));
} catch (\Exception $e) {
echo $e->getMessage() . PHP_EOL;
}
?>
</pre>
I have a video file to probe with the use of FFPROBE, I'm trying to catch the error so that instead of just throwing the error it updates the DB row first, setting it to state 2 (processed 0 = default, processed 0 = done, processed 2 = error).
I've tried this first:
$user = Auth::user()->id;
$video = Video::find($videoUploaded->video->id);
$playlist = $video->playlist->id;
...
try {
//Line 39 $seconds
$seconds = $ffprobe->format(config('cf.video_disk') . "/$user/$playlist/$video->ts_name")->get('duration');
} catch (\Exeption $err) {
$video->processed = 2;
$video->name = $err->getMessage();
$video->url = $err->getMessage();
$video->update();
event(new VideoUpdated($video));
return $err->getMessage();
}
And also suppressing the error with # and moving the DB update in the try:
try {
//Line 39 $seconds
$seconds = #$ffprobe->format(config('wondermark.video_disk') . "/$user/$playlist/$video->ts_name")->get('duration'); //Line 39
if (FALSE === $seconds) {
$video->processed = 2;
$video->name = $err->getMessage();
$video->url = $err->getMessage();
$video->update();
}
} catch (\Exeption $err) {
event(new VideoUpdated($video));
return $err->getMessage();
}
Both return the error on line #39 (see above comment) and the DB does not get updated :(
It seems there's only a mistake in spelling Exception, So i guess this will work:
try {
$seconds = $ffprobe->format(config('cf.video_disk') . "/$user/$playlist/$video->ts_name")->get('duration');
// if no errors
} catch (\Exception $err) {
// if error happens
return $err->getMessage();
}
And it is more recommended that you catch throwables (PHP: Throwable - Manual) instead of exceptions:
try {
$seconds = $ffprobe->format(config('cf.video_disk') . "/$user/$playlist/$video->ts_name")->get('duration');
// if no errors
} catch (\Throwable $throwable) {
// if error happens
return $throwable->getMessage();
}
I am using php and mongodb. I want to use findandmodify. My field is { "_id" : ObjectId("58d37e612d4ffa498b99c2d4"), "userid" : "1234", "active_time" : "hai" }
I want to modify active_time. For example change the value "hai" to "1234"
I am using MongoDB\Driver\Manager.
try {
$mng = new MongoDB\Driver\Manager("mongodb://username:password#localhost:27017/db");
$userid = '1234';
$retval = $mng->findAndModify(
array("userid" => $userid), // searchQuery
array('$set' => array('active_time' => "kkk")) // UpdateQuery
);
$command = new MongoDB\Driver\Command($retval);
$cursor = $manager->executeCommand('db.online', $command);
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
echo "In file:", $e->getFile(), "\n";
echo "On line:", $e->getLine(), "\n";
}
It shows the error is
Fatal error: Uncaught Error: Call to undefined method MongoDB\Driver\Manager::findAndModify()
in line
$retval = $mng->findAndModify(
array("userid" => $userid), // searchQuery
array('$set' => array('active_time' => "kkk")) // UpdateQuery
);
How it possible? please help me?
I got the answer. Change the findAndModify to update. The modified code is shown below.
$bulk->update(
array("userid" => '1234'), // searchQuery
array('$set' => array('active_time' => "kkk")) // UpdateQuery
);
$mng->executeBulkWrite("browser.online", $bulk);
if(!empty($mng)) {
echo "success";
} else {
echo "not";
}
I've got a Search class, which has
public function __construct($isNewIndex = false) {
setlocale(LC_CTYPE, 'ru_RU.UTF-8');
$analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive();
$morphy = new Isi_Search_Lucene_Analysis_TokenFilter_Morphy('ru_RU');
$analyzer->addFilter($morphy);
Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');
//if it's true, then it creates new folder to the path in $_indexFieles;
if ($isNewIndex) {
$this->_indexes[$this->_key] = Zend_Search_Lucene::create(Yii::getPathOfAlias('application.' . $this->_indexFiles), true);
} else {
$this->_indexes[$this->_key] = Zend_Search_Lucene::open(Yii::getPathOfAlias('application.' . $this->_indexFiles));
}
}
public function find($query, $eventId)
{
try
{
Zend_Search_Lucene_Search_QueryParser::setDefaultOperator(Zend_Search_Lucene_Search_QueryParser::B_AND);
$query = "($query) AND (event_id:$eventId)";
Zend_Search_Lucene::setResultSetLimit(self::ACCREDITATION_LIMIT);
return $this->_indexes[$this->_key]->find("{$query}");
}
catch (Zend_Search_Lucene_Search_QueryParserException $e)
{
echo "Query syntax error: " . $e->getMessage() . "\n";
}
catch (Exception $e)
{
echo $e->getMessage(). "\n";
}
}
I've got a record with name Test, when I'm looking for Test it works, but can't find this record with request test
Code example:
$s = new Search();
$s->find('test', 1232);//no results
I found a solution, the problem was that I was saving fields (name, etc.) as keyword, I changed it to text, and now it's working perfectly.
How to catch an error from a SOAP?
How can I avoid the fatal error and convert it to my own error.. In this example it's a SERVER_BUSY
code
class Validate_vatno {
private $client = null;
private $options = array(
'debug' => false
);
public function __construct(){
$this->client = new SoapClient('http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl', array('trace' => true));
}
public function check($country, $vatno){
$result = $this->client->checkVat(array(
'countryCode' => $country,
'vatNumber' => $vatno
));
if(!empty($this->options['debug'])){
echo '<pre>'.htmlentities($this->client->__getLastResponse()).'</pre>';
}
if($result->valid){
list($denomination, $name) = explode(' ', $result->name, 2);
return array(
'denomination' => utf8_decode($denomination),
'name' => ucwords(utf8_decode($name)),
'address' => ucwords(utf8_decode($result->address)),
);
}
else{
return array();
}
}
}
$vatValidation = new Validate_vatno();
if($return = $vatValidation->check('DK', 33214944)){
echo '<h1>valid one!</h1>';
echo 'denomination: ' . $return['denomination']. '<br/>';
echo 'name: ' . $return['name']. '<br/>';
echo 'address: ' . $return['address']. '<br/>';
}
else{
echo '<h1>Invalid VAT</h1>';
}
error
Fatal error: Uncaught SoapFault exception: [soapenv:Server] { 'SERVER_BUSY' } in /var/www/
Review how to handle exceptions
Throwing and Catching a Exception
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
else return 1/$x;
}
try {
echo inverse(5) . "\n";
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
// Continue execution
echo 'Hello World';
?>