So I need some help on building out one of my methods for retrieving twitter lists using IDs. Below, I will describe and go into detail on what it's returning.
Code:
public static function get_list($list_id)
{
$lists = self::get_lists();
$params = [
'list.fields' => 'created_at,follower_count,member_count,private,description,owner_id',
'user.fields' => 'created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,withheld'
];
try {
$list = $lists->get($list_id, $params);
} catch (\GuzzleHttp\Exception\ClientException $e) {
return $e;
}
return $list;
}
When $lists->get() has an issue, it throws the following items object(GuzzleHttp\Exception\ClientException)#1640 (10) { ["request":"GuzzleHttp\Exception\RequestException":private]=> error.
What I'd like to achieve:
Return $e so that I can read the error (Unable to get this to work).
If I switch out return $e for return 'Hello', I still see the object and not the string.
The IDE suggests that it #throws GuzzleException.
Does anyone see anything wrong in how I'm handling my exception and why I'm unable to properly return the exception error?
Try to use exception hierarchy to catch any exception. ClientException only catches status code between 400x-499. To catch other exception or catch within the same Exception you can use RequestException.
public static function get_list($list_id)
{
$lists = self::get_lists();
$params = [
'list.fields' => 'created_at,follower_count,member_count,private,description,owner_id',
'user.fields' => 'created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,withheld'
];
try {
$list = $lists->get($list_id, $params);
if($list->getStatusCode() == 200)){
$return_list = json_decode($list->getBody(),true);
}
} catch (\GuzzleHttp\Exception\ClientException $e) {
$error['error'] = $e->getMessage();
$error['request'] = $e->getRequest();
if($e->hasResponse()){
// you can pass a specific status code to catch a particular error here I have catched 400 Bad Request.
if ($e->getResponse()->getStatusCode() == '400'){
$error['response'] = $e->getResponse();
}
}
return $error;
} catch(\GuzzleHttp\Exception\RequestException $se){
$error['error'] = $e->getMessage();
$error['request'] = $e->getRequest();
return $error;
} catch(Exception $e){
//other errors
}
return $list;
}
Related
I have this code:
try{
firstMethod()
secondMethod()
}
catch(Exception $e){
....
}
What I want is execute all try/catch block functions but capturing if one throws exception, without skipping the following methods
a possible but not pretty code would be:
try{
firstMethod();
}
catch(Exception $e){
....
}
try{
secondMethod();
}
catch(Exception $e){
....
}
I am assuming you might have a lot of those if you are looking for more convenient way than "not pretty" take?
I would say just loop through them:
foreach ( [ 'firstMethod', 'secondMethod' ] as $callable ) {
try {
$callable();
}
catch ( Exception $e ) {
}
}
Why not write try catch in each function and log the exceptions somewhere.
function firstMethod() {
try {
//code
}
catch (Exception $e) {
logException($e);
}
}
function secondMethod() {
try {
//code
}
catch (Exception $e) {
logException($e);
}
}
function mainMethod() {
firstMethod();
secondMethod();
}
This will help in doing something like this:
function someOtherMethod() {
secondMethod();
}
I have a script that looks like this:
require ("class-pdowrapper.php");
$db = new DB();
$baddata = 'abc'; //should be an integer!!
$db->bind("myinteger", $baddata);
$sql = "INSERT INTO t_numbers (theinteger) VALUES (:myinteger)";
$result = $db->query($sql);
if ($result == 1) {
echo "success.";
} else {
echo "didn't work..."; //question relates to this line
}
If $baddata is "abc" i.e. a string, the class will handle the exception and output something like this:
Unhandled Exception.
SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'abc' for column 'theinteger' at row 1
You can find the error back in the log
The class does this by something like:
private function query($statement) {
try {
// stuff
}
catch (PDOException $e) {
echo $this->ExceptionLog($e->getMessage(), $query);
die();
}
}
private function ExceptionLog($message, $sql = "") {
$exception = 'Unhandled Exception. <br />';
$exception .= $message;
$exception .= "<br /> You can find the error back in the log.";
if (!empty($sql)) {
$message .= "\r\nRaw SQL : " . $sql;
}
return $exception;
}
So the question is, how can a script acknowledge the exception thrown and handled in the class and use the knowledge to do something. In my case, I could show the user an error or email the administrator to show that something isn't working with the database-related code.
If you catch the exception, then it is stopped from travelling up the stack, so you do not have the opportunity to »re-catch« it.
Basically you can either »re-throw« an Exception of a custom type, by creating a custom Error type like so:
class DataInsertException extends Exception {}
and than later:
try {
// stuff
}
catch (PDOException $e) {
echo $this->ExceptionLog($e->getMessage(), $query);
throw new DataInsertException();
}
That way you can »filter« exceptions within the try catch statement:
try {} catch (DataInsertException $error) {}
whenever you deal with the database. All other Errors wont be caught by that block.
Or you can also add a $errors property to your DB class.
class DB {
private $errors;
public function __construct(){
$this->errors = [];
}
public function insert(){
try {}
catch($error) {
array_push($this->errors, $error);
}
}
public function getErrors() {
return $this->errors;
}
}
That way, you can check the $db Object after each Transaction if it has Errors and react on that.
I would prefer a custom Error
You need validate all your variables before you send it to server
it is right way because you don't send incorrect request to server side.
like this (it is only sample)
<?php
class sampleClass
{
public function __construct($data) {
if ($this->validateData($data)) {
//do something
$this->runRequest($data);
} else {
//parse errors
//var_dump($data);
}
}
private function validateData($data) {
foreach($data as $currentData) {
if ($currentData['type'] == 'integer' && is_int($currentData['value'])) {
return false;
}
if ($currentData['type'] == 'string' && is_string($currentData['value'])) {
return false;
}
}
return true;
}
private function runRequest($data) {
}
}
$data = [
'correct_age' => [
'type' => 'integer',
'value' => 88
],
'incorrect_age' => [
'type' => 'integer',
'value' => 'abc'
],
'incorrect_name' => [
'type' => 'string',
'value' => 111
]
];
$test = new sampleClass($data);
There are many options here. Here're some of them:
You can rethrow an Exception in you catch (PDOException $e) { block and make another try ... catch ... in your script. So you would handle logging in your query method and then handle application-related logic in the script file itself:
try {
$result = $db->query($sql);
} catch (AnotherException $e) {
...
}
You can return complex result from query(), like this (it's only a draft):
$result = array(
'status' => true|false (or 'error' => true|false),
'data' => ... (valid data on success, error details data on error)
)
And then you can handle this result with no problems.
I'm working on an api, it handles the requests which comes from clients, then gets the response from server(developed using codeigniter 3) and forwards that back to client.
But, in case of any database errors, like duplicate id, or null values, the model class cannot handle that error to display a proper error message. I've tried the try catch block but not succeeded yet.
Here's the model:
public function add() {
try {
$this->db->trans_start(FALSE);
$this->db->insert('users', $preparedData);
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE) {
throw new Exception("Database error:");
return false;
}
return TRUE;
} catch (Exception $e) {
log_message('error: ',$e->getMessage());
return;
}
}
One thing to mention, I've set db_debug to FALSE.
Any help would be appreciated.
As for CI 3, below code gets database error code and error message. db_debug is set to FALSE.
public function add() {
try {
$this->db->trans_start(FALSE);
$this->db->insert('users', $preparedData);
$this->db->trans_complete();
// documentation at
// https://www.codeigniter.com/userguide3/database/queries.html#handling-errors
// says; "the error() method will return an array containing its code and message"
$db_error = $this->db->error();
if (!empty($db_error)) {
throw new Exception('Database error! Error Code [' . $db_error['code'] . '] Error: ' . $db_error['message']);
return false; // unreachable retrun statement !!!
}
return TRUE;
} catch (Exception $e) {
// this will not catch DB related errors. But it will include them, because this is more general.
log_message('error: ',$e->getMessage());
return;
}
}
Refer to documentation at https://www.codeigniter.com/userguide3/database/queries.html#handling-errors
saying
If you need to get the last error that has occurred, the error() method will return an array containing its code and message.
It is a bit incomplete in my opinion because it does not show error code and error message in the example code.
I just lost an hour trying to figure out why I can't get the error in my code. You have to check for an error after each statement! Working solution:
function insertUpdate($data) {
$order = $data->order;
$order_products = $data->order_products;
$this->db->trans_start();
$order->user_id = $this->session->user_id;
$error = "OK";
if (!$this->db->insert('_order', $order)) {
$error = $this->db->error()["message"];
}
$id = $this->db->insert_id();
foreach ($order_products as $row) {
$row->order_id = $id;
if (!$this->db->insert('_order_product', $row)) {
$error = $this->db->error()["message"];
break;
}
}
$order_code = substr(md5($id), 0, 6);
if (!$this->db->where('order_id', $id)) {
$error = $this->db->error()["message"];
}
if (!$this->db->update('_order', ["order_code" => $order_code])) {
$error = $this->db->error()["message"];
}
$this->db->trans_complete();
return [
'result' => $error, 'order_code' => $order_code
];
}
Suggestion in above code
Remove line $this->db->trans_complete();
If we see $this->db->error() after completing transaction it will be always empty
Remove semicolon - log_message('error :',$e->getMessage());
return;
public function add()
{
try {
$this->db->trans_start(FALSE);
$this->db->insert('users', $preparedData);
// documentation at
// https://www.codeigniter.com/userguide3/database/queries.html#handling-errors
// says; "the error() method will return an array containing its code and message"
$db_error = $this->db->error();
if (!empty($db_error)) {
throw new Exception('Database error! Error Code [' . $db_error['code'] . '] Error: ' . $db_error['message']);
return false; // unreachable return statement !!!`enter code here`
}
return TRUE;
} catch (Exception $e) {
// this will not catch DB related `enter code here`errors. But it will include them, because this is more general.
log_message('error ',$e->getMessage());
return;
}
}
public function edit($body){
try
{
$stmt=$this->db->prepare("UPDATE news SET body=:body");
$stmt->bindparam(":body",$body);
$stmt->execute();
return true;
}
catch(PDOException $e)
{
echo $e->getMessage();
return false;
}
}
It always saving missed data when data too long for column 'body' I want to catch exception.
I need to rollback transaction and send correct response to the client if anything in the try block fails so I do it like that:
try {
$wf = $this->createWordForm($requestParams);
$wfl = $this->createWordFormLink($requestParams, $wf);
$wordList = $this->bindWordFormOrLinkToTextWord($requestParams, $wf, $wfl);
$db->commit();
} catch (Kohana_ORM_Validation_Exception $e) {
$exceptionHasOccured = TRUE;
return JsonResponse::ValidationFail($this->response, $e->errors());
} catch (Exception $e) {
$exceptionHasOccured = TRUE;
return JsonResponse::Error($this->response, $e->getMessage());
} finally {
if ($exceptionHasOccured) {
$db->rollback();
}
}
As you can see I'm using finally construction to rollback transaction. Is this correct approach?
You could catch all exceptions in one catch block, as long as your not specifically using the exception type for any purpose.
try {
$wf = $this->createWordForm($requestParams);
$wfl = $this->createWordFormLink($requestParams, $wf);
$wordList = $this->bindWordFormOrLinkToTextWord($requestParams, $wf, $wfl);
$db->commit();
} catch (Exception $e) {
$db->rollback();
if($e instanceof Kohana_ORM_Validation_Exception ) {
return JsonResponse::ValidationFail($this->response, $e->errors());
} else {
return JsonResponse::Error($this->response, $e->getMessage())
}
}