I'm using Symfony 4 with Doctrine and am handling an entity which will be persisted.
I would like to know how can I have a kind of try\catch handling when an exception occurs while persisting, so that I can send different errors accordingly.
As of now my code looks like this
$user->setUsername($username)
->setEmail($email)
->setPassword($password);
$em->persist($user);
$em->flush();
return $this->json(['msg'=>'some message', 201);
I would like to be able to decide what to send in the Response in case there are errors.
You can catch errors simply as follows, but you will have to check with the conditions.
try {
$user->setUsername($username)
->setEmail($email)
->setPassword($password);
$em->persist($user);
$em->flush();
}
catch(DBALException $e){
$errorMessage = $e->getMessage();
}
catch(\Exception $e){
$errorMessage = $e->getMessage();
}
Related
Need a bit quick help with Kotlin. Here is the pseudocode: When there is a “specialCase” error, throw the exception and Log this exception as “Info”. This is the if statement I have. Does this look like a good approach?
if (error.contains (specialCase))
{
throw specialCaseDoesNotExistException
}
LOGGER.info("WriteSpecialCaseasInfoandNOTError")
Either you log before throwing or you could combine it into a single statement using also (reference):
if (error.contains (specialCase)) {
LOGGER.info("WriteSpecialCaseasInfoandNOTError")
throw specialCaseDoesNotExistException
}
if (error.contains (specialCase)) {
throw specialCaseDoesNotExistException.also {
LOGGER.info("WriteSpecialCaseasInfoandNOTError")
}
}
prinBalAgencyComm.sendKeys(testData.get("agencyCommissionPB"));
prinBalClientRem.sendKeys(Keys.TAB);
prinBalFrom2.sendKeys(testData.get("fromFB2")); //Locator not found
prinBalAgencyCommLast.sendKeys(testData.get("agencyCommissionLastPB")); //how to execute this line without fail
You can handle this by using try catch finally.
try{
//code that can result in an exception
prinBalAgencyComm.sendKeys(testData.get("agencyCommissionPB"));
prinBalClientRem.sendKeys(Keys.TAB);
prinBalFrom2.sendKeys(testData.get("fromFB2"));
}catch(Exception e)
{
//actions you want to take in case your locator isnt found or another exception occurs
System.out.println("Exception occured" + e.getMessage());
}finally
{ //the line to be executed without fail
prinBalAgencyCommLast.sendKeys(testData.get("agencyCommissionLastPB"));
}
you would have to implement a try/catch block
try {
element action
} catch (Exception e) {
//whatever you want to happen when it fails
}`
But I would ask myself why is the test not consistent with every run? Why should this step not pass every time?
One pattern you can use is:
try {}
catch {}
Place your offending code in the try block and any error code in the catch block.
If an exception is raised in the try, the catch block will be called instead of proceeding to the next line in the try
see here: The proper way to do exception handling
say this code:
function changeBookAuthor(int $id, string $newName){
if(!$newName){
throw new MyAppException('No author name was provided');
}
$book = Books::find($id);
if(!$book){
throw new MyAppException('The provided book id could not be found');
}
//..
}
i want to change that to:
function changeBookAuthor(int $id, string $newName){
if(!$newName){
throw new MyAppException('No author name was provided', <SOMEVERYRANDOMNUMBER>);
}
$book = Books::find($id);
if(!$book){
throw new MyAppException('The provided book id could not be found', <SOMEVERYRANDOMNUMBER>);
}
//..
}
can intellij help me in selecting random numbers?
I personally use different types of Exception instead of exception code.
For example:
try{
...
} catch (PDOException e1){
// Show a message that we could not do SQL work
} catch (NumberFormatException e2){
// Show a message that input was not a valid number
} catch (Exception e){
// I'm not sure what was wrong but definitely there was some thing wrong
}
But if you still want random numbers, go to https://www.random.org, there are some number generators, copy values and define them as constants in your code (i guess that you are using PHP)
All I'm trying to do is verify a query.
'SELECT * from table_that_does_not_exist'
Without that erroring out, I'd like to know it failed so I can return a response that states "Error: table does not exist" or the generic error.
The simplest way to catch any sql syntax or query errors is to catch an Illuminate\Database\QueryException after providing closure to your query:
try {
$results = \DB::connection("example")
->select(\DB::raw("SELECT * FROM unknown_table"))
->first();
// Closures include ->first(), ->get(), ->pluck(), etc.
} catch(\Illuminate\Database\QueryException $ex){
dd($ex->getMessage());
// Note any method of class PDOException can be called on $ex.
}
If there are any errors, the program will die(var_dump(...)) whatever it needs to.
Note: For namespacing, you need to first \ if the class is not included as a use statement.
Also for reference:
Laravel 5.5 API - Query Exception
Laravel 8.x API - Query Exception
Wrap the lines of code you wish to catch an exception on using try-catch statements
try
{
//write your codes here
}
catch(Exception $e)
{
dd($e->getMessage());
}
Do not forget to include the Exception class at the top of your controller by saying
Use Exception;
If you want to catch all types of database exceptions you can catch it on laravel Exception Handler
if ($exception instanceof \PDOException) {
# render a custom error
}
for more details about how to use laravel Exception Handler check https://laravel.com/docs/7.x/errors
Laravel 8.x
try {
$model->save(); // Use Eloquent: https://laravel.com/docs/8.x/eloquent
} catch (\Throwable $e) {
return 'My error message';
}
Note* Need to specify \Throwable $e no Throwable $e.
I made a test class against the repository methods shown below:
public void AddFile<TFileType>(TFileType FileToAdd) where TFileType : File
{
try
{
_session.Save(FileToAdd);
_session.Flush();
}
catch (Exception e)
{
if (e.InnerException.Message.Contains("Violation of UNIQUE KEY"))
throw new ArgumentException("Unique Name must be unique");
else
throw e;
}
}
public void RemoveFile(File FileToRemove)
{
_session.Delete(FileToRemove);
_session.Flush();
}
And the test class:
try
{
Data.File crashFile = new Data.File();
crashFile.UniqueName = "NonUniqueFileNameTest";
crashFile.Extension = ".abc";
repo.AddFile(crashFile);
Assert.Fail();
}
catch (Exception e)
{
Assert.IsInstanceOfType(e, typeof(ArgumentException));
}
// Clean up the file
Data.File removeFile = repo.GetFiles().Where(f => f.UniqueName == "NonUniqueFileNameTest").FirstOrDefault();
repo.RemoveFile(removeFile);
The test fails. When I step in to trace the problem, I found out that when I do the _session.flush() right after _session.delete(), it throws the exception, and if I look at the sql it does, it is actually submitting a "INSERT INTO" statement, which is exactly the sql that cause UNIQUE CONSTRAINT error. I tried to encapsulate both in transaction but still same problem happens. Anyone know the reason?
Edit
The other stay the same, only added Evict as suggested
public void AddFile<TFileType>(TFileType FileToAdd) where TFileType : File
{
try
{
_session.Save(FileToAdd);
_session.Flush();
}
catch (Exception e)
{
_session.Evict(FileToAdd);
if (e.InnerException.Message.Contains("Violation of UNIQUE KEY"))
throw new ArgumentException("Unique Name must be unique");
else
throw e;
}
}
No difference to the result.
Call _session.Evict(FileToAdd) in the catch block. Although the save fails, FileToAdd is still a transient object in the session and NH will attempt to persist (insert) it the next time the session is flushed.
NHibernate Manual "Best practices" Chapter 22:
This is more of a necessary practice than a "best" practice. When
an exception occurs, roll back the ITransaction and close the ISession.
If you don't, NHibernate can't guarantee that in-memory state
accurately represents persistent state. As a special case of this,
do not use ISession.Load() to determine if an instance with the given
identifier exists on the database; use Get() or a query instead.