I want to catch PDOException in symfony 2.6, especially ConnectionException.
For instance if I stop my MySQL server I want to catch that exception and return a customised message to the user, but it seem that it's uncatchable in customised kernel.exception listner, and either in try catch block, i don't know if it's a symfony problem or something must be done.
I also tried out to customise error page like said in documentation but usselssly, I seached in web for solution, but I found nothing except something about redefining a controller in frameworkbundle whish is responsable of converting Exception into error page.
But I really don't want to go for that solution since i'm new with symfony.
You can do this by creating an exception listener and catch Pdo exception :
service.yml:
kernel.listener.your_pdo_listener:
class: Acme\AppBundle\EventListener\YourExceptionListener
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onPdoException }
Then the listener class :
YourExceptionListener
UPDATED
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
class YourExceptionListener
{
public function onPdoException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof \PDOException || $exception->getPrevious() instanceof \PDOException) {
//now you can do whatever you want with this exception
}
}
}
Snippets from : Catching database exceptions in Symfony2
I have done more test, so the test i made first was making a query to the database, that's why i got pdoexception as first exception but sometime it can be a twig exception as you know twig throw runtime exception if it couldn't contact database but hopefully we can get the previous exception also and this can work with other exceptions which can be thrown after the PDO ones, so hopefully it will work for you as expected so i edited the code to check if previous exception is a PDOException also.
Related
Since upgrading to meteor 1.8.0.2 from 1.6.x I've noticed that any method call that results in an error is printed on the server console as:
Exception while invoking method 'login' [object Object]
Exception while invoking method 'customMethodByMe' [object Object]
This happens both on development on my mac and deployed on Galaxy.
Before, the whole stack trace was printed, but this Object object logging doesnt help me figure out the actual problem. My solution so far has been to wrap method implementation in a try catch statement that logs the original exception and rethrows it for the client to know.
Meteor.methods({
'customMethodByMe'() {
try {
return customMethodByMeImpl();
} catch (e) {
console.log(e)
throw e;
}
}
});
In this case, since the error is on the login method which is in a package, I cannot update it to print the real problem. On the client, all I get on any error is that there was a 500 error on the server, so no root cause either.
{"isClientSafe":true,"error":500,"reason":"Internal server error","message":"Internal server error [500]","errorType":"Meteor.Error"}
Any ideas on how to temporarly solve this? I've been searching for a server level error handler but so far have found nothing.
thanks
I did not get to experience this directly, but when I need to print an object, I usually use JSON.stringfy.
Meteor.methods({
'customMethodByMe'() {
try {
return customMethodByMeImpl();
} catch (e) {
console.log(JSON.stringify(e));
throw e;
}
}
});
This should resolve so that you can at least read the error log.
Is there a way to handle all errors, from my symfony controllers, for example, if I get this error:
In my controller is there a way using try/catch to get this error?. For example:
class SomeClass extends Controller
{
public function doSomethingAction(Request $request){
//do something
try {
//do something
}
catch(\Exception $e){
dump("ERROR:".$e->getMessage()); //<--this is not dumping anithing
}
}
}
I get allways the red screen message in the network call preview:
Instead of something like:
"ERROR: Type error: Argument 1 passed to.....
With PHP 7 you are able to handle PHP errors like TypeErrors from mismatching types (like in your example) as well as exceptions by catching their shared interface Throwable.
You should be careful with this, especially outside controllers, as this could prevent you from seeing unexpected errors which can lead to problems down the line or you not seeing when parts of your application are entirely broken. At the very least you should have proper logging in place.
In summary, you can catch errors along with exception like this:
try {
...
} catch (\Throwable $error) {
...
}
EDIT: The question is about why using setAutoCommit(false) is a solution for the "there is no active transaction" exception. Forget this question since this is not the correct solution (at least in my case). I will leave the question here in case somebody encounters the same problem. See my answer below for more details.
================
The following code worked fine in Symfony 2.7, but after an update to Symfony 2.8 (and to the latest DoctrineBundle version), a There is no active transaction exception is thrown:
private function getSynchronization() {
$lock_repo = $this->entityManager->getRepository('MyAppBundle\Entity\DBLock');
$this->entityManager->getConnection()->beginTransaction();
try {
$sync = $lock_repo->findOneByUser($this->getUser());
if (!$lock) {
$lock = new DBLock();
} else {
if ($lock->isActive()) {
// ... Exception: Process already running
}
$expected_version = $lock->getVersion();
$this->entityManager->lock($lock, LockMode::OPTIMISTIC, $expected_version);
}
$sync->setActive(false);
$this->entityManager->persist($sync);
$this->entityManager->flush();
$this->entityManager->getConnection()->commit();
// EXCEPTION on this line
$this->entityManager->lock($lock, LockMode::NONE);
}
catch(\Exception $e) {
$this->entityManager->getConnection()->rollback();
throw new ProcessException($e->getMessage());
}
...
}
After some searching I found a solution in another post. After adding the following line everything works fine:
private function getSynchronization() {
$lock_repo = $this->entityManager->getRepository('MyAppBundle\Entity\DBLock');
$this->entityManager->getConnection()->beginTransaction();
// ADDED LINE
$this->entityManager->getConnection()->setAutoCommit(false);
try {
...
So, the question is not how to solve the problem, but how the solution works...
I am quite confused by the Doctrine docs of the setAutoCommit() method:
To have a connection automatically open up a new transaction on
connect() and after commit() or rollBack(), you can disable
auto-commit mode with setAutoCommit(false)
I do not understand this.
Does this mean, that the transaction that was started/created with beginTransaction() is now automatically closed when using commit()? So in order to be able to use lock(...) after using commit() I have to begin a new transaction first. I can either do this manually by calling beginTransaction() again, or auotmatically by setting setAutoCommit(false) before. Is that correct?
Is this a change in on of the latest Doctrine versions? I did not found anything about in in the updates notes and before the update of Symfony/Doctrine the code worked just fine.
Thank you very much!
As described before I encountered the problem, that calling lock($lock, LockMode::NONE) suddenly threw a There is no active transaction exception after the Update from Doctrine 2.4 to 2.5.
My solution was to add setAutoCommit(false), which automatically created a new transaction after calling commit(). It worked and the exception did not occur again. However, this is not the real/correct solution, it creates other problems as side effects.
After re-reading the Doctrine Update Notes I found out, that the correct solution is to use lock($lock, null) instead of lock($lock, LockMode::NONE). This is BC Break between Doctrine 2.4 and 2.5.
Maybe my question and answer helps someone else who encounters the same problem.
I've a try-catch statement code inside an action of a controller:
public function MyAction(){
...
try{
...
}
catch(MyException $e){
...
}
....
}
But the exception is intercepted by symfony, show me the twig template of exception detected. It means my catch statemant is never executed, right?
Why? (inside the try i'm just calling a method of another object)
What's wrong?
How Can I do symfony execute my own exceptions?
(I think it's really strange, beacuse it's similar the try-catch em->persist/flush)
I've just forgot the use statetament or the full namespace path and so php can't find MyExceptionClass.
resolve as
catch(path\to\MyException $e){...}
or
use path\to\MyException;
....
...
catch(MyException $e){
I am trying to catch exceptions inside an Action in a Controller in Symfony2.3 application during entity persistance.
try {
$em->persist($firm);
} catch(\Exception $e){
.........
}
I expected that all errors will be handled by my code inside catch statement, instead I got following errors:
[2/2] DBALException: An exception occurred while executing 'INSERT INTO ...
...
[1/2] PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry
...
CRITICAL - Uncaught PHP Exception Doctrine\DBAL\DBALException
If I throw exception inside try statement it is cought and handled properly by code inside catch
try {
throw new \Doctrine\ORM\ORMException;
//or throw new \Doctrine\DBAL\DBALException;
//or throw new \PDOException;
} catch(\Exception $e){
.......
}
My question is: How one should properly handle Doctrine2 inside Symfony2 controller.
Thanks.
Possible that you have got exception from line $em->flush() which doesnt wrapped with try-catch statement.
Integrity constraint violation: 1062 Duplicate entry
In your case you should check for uniqueness before persisting your entity using the UniqueEntity validator.
If the form does not validate - just don't persist in order to avoid this exception.