I have had no formal teaching in coding and was hoping if anyone could tell me if I was being to cautious with my code?
// Insert info to the db
if ($stmt = $db_connect->prepare("INSERT INTO db (col1, col2) VALUES (?, ?)")) {
if(!$stmt->execute([$val1, $val2])) {
exit("1:Faild to create deal");
}
// Get last id
$id = (int)$db_connect->lastInsertId();
$stmt->closeCursor();
} else { exit("0:Faild to create deal"); }
// Create the folder
if(!mkdir("folder/folder".$id)) {
if($stmt = $db_connect->prepare("DELETE FROM db WHERE id=?")) {
if(!$stmt->execute([$id])) {
exit("1:Faild to create the directory -> Faild to remove the row from the database");
}
exit("Faild to create the directory");
}
exit("0:Faild to create the directory -> Faild to remove the row from the database");
}
I repeat the create folder statement 2 more times with the same layout. It's just repeatable code that looks to be overkill.
Note: The package I have with my host only has MyISAM tables so I can't use Rollback.
If something fails I want to undo everything that has passed.
Could someone please give me some guidance to best practices or am I doing it right?
i re-structured and extended your code plus added a bit of simple error handling by using exceptions.
first you should set your PDO error handling to exception mode:
$db_connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
then i have capsulated your actions into functions, which you can put into a separate file and include it, or even nest them into classes:
/*** FUNCTIONS ***/
// insert info to the db
function dbInsertInfo($db_connect, $val1, $val2)
{
$stmt = $db_connect->prepare("INSERT INTO db (col1, col2) VALUES (?, ?)");
$stmt->execute([$val1, $val2]));
}
//-------------------------------
// get the last insert id
function dbGetId($db_connect)
{
$id = (int)$db_connect->lastInsertId();
$stmt->closeCursor();
return $id;
}
//-------------------------------
// delete db-entry
function dbDeleteId($db_connect, $id)
{
$stmt = $db_connect->prepare("DELETE FROM db WHERE id=?");
$stmt->execute([$id]);
}
//-------------------------------
// create the folder
function createFolder($id)
{
if(!mkdir("folder/folder".$id)) throw new Exception("Failed to create the directory");
}
//-------------------------------
then here is your procedure with all the try{ } catch{ } sections for the error handling by exceptions:
/* PROCEDURE */
// 01 | try to insert into db
try
{
dbInsertInfo($db_connect, $val1, $val2);
}
catch(PDOException $e)
{
//if exception thrown, do not continue the script:
echo "Unable to insert into DB: ".$e->getMessage();
exit();
}
//-------------------------------
// 02 | try to get last insert id
$id = false;
try
{
$id = dbGetId($db_connect);
}
catch(PDOException $e)
{
//if exception thrown, do not continue the script:
echo "Unable to get last insert id from DB: ".$e->getMessage();
exit();
}
//-------------------------------
// 03 | try to create folder // if it fails -> try to delete db entry
try
{
createFolder($id);
}
catch(Exception $e)
{
// if exception caught, try to remove the corresponding DB entry:
echo $e->getMessage();
echo "<br />";
echo "trying to remove DB entry now";
// try to delete db entry
try
{
dbDeleteId($db_connect, $id);
}
catch(PDOException $e)
{
//if exception thrown, do not continue the script:
echo "Unable to delete from DB: ".$e->getMessage();
exit();
}
}
//-------------------------------
/* Everything worked fine if you get to this point of the code*/
just might seem like an technical overkill for you now, but i think it's much more structured and better to read it, once you got into it. plus, it's only divided into 3 steps.
Related
I'm currently working on a proyect on cakephp 2.0 where i need to insert multiple users to a sql server database.
I need to make a rollback if something fails, but not necessarilly if the stored procedure failed, but if something within the php file logic fails throws an exception to make the rollback.
The code works like this:
try {
...$this->db->beginTransaction();//The connection to the DB is already on.
foreach($users as $user){
//some logic
if(something) {
throw new Exception('blah blah');
}
$query = $this->sqlsrv->prepare('storedProcedure1');
//bind parameters
if(!$query->execute()) {
throw new Exception('blah blah');
}
//some logic...
if(something) {
throw new Exception('blah blah');
}
$query = $this->sqlsrv->prepare('storedProcedure2');
bind parameters
if(!$query->execute()) {
throw new Exception('blah blah');
}
}
$this->db->commit();
}
catch (Exception $e){
$this->db->rollBack();
}
I dont know if something like this may be possible, the functions return true, but the succesfull inserts from the stored procedures are still there, and i would like to tollback all of those even when they were succesfull.
I'm using the following function from CS50 2014 and it's working when I SELECT but it's not working when I try to UPDATE. Here's the query and the function:
query(
"UPDATE users
SET pwtxt = ?, pass = ?, dt = ?, reset = ?
WHERE usr = ?",
NULL,
"compass",
NULL,
0,
1
);
function query(/* $sql [, ... ] */)
{
// SQL statement
$sql = func_get_arg(0);
// parameters, if any
$parameters = array_slice(func_get_args(), 1);
// try to connect to database
static $handle;
if (!isset($handle))
{
try
{
// connect to database
$handle = new PDO("mysql:dbname=" . DATABASE . ";host=" . SERVER, USERNAME, PASSWORD);
// ensure that PDO::prepare returns false when passed invalid SQL
$handle->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch (Exception $e)
{
// trigger (big, orange) error
trigger_error($e->getMessage(), E_USER_ERROR);
exit;
}
}
// prepare SQL statement
$statement = $handle->prepare($sql);
if ($statement === false)
{
// trigger (big, orange) error
// trigger_error($handle->errorInfo()[2], E_USER_ERROR); need to fix array issue
exit;
}
// execute SQL statement
$results = $statement->execute($parameters);
// return result set's rows, if any
if ($results !== false)
{
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
else
{
return false;
}
}
it appears you can no longer update with NULLS
When your are Updating rows you can't use the fetch methods. That's why it's working only with Select queries.
With PDO, how can I make sure that an UPDATE statement was successful?
You have to use the rowCount method to see how many have been affected by your query. By the way I don't think it's a good idea to try to mix up different queries types in only one method. Return values for a select, an update, an insert or a delete are not the same. You can't sum up these in one same function.
If you want to centralize your database connection, I invite you to create a child class of PDO where you can hard code your DB credentials. Or you can create a global PDO object or better, use a singleton. That way, you will be able to use your PDO instance anywhere without duplicating your DB credentials all around and using PDO native methods for your preparations.
I'm using a class for database connection, this class holds the CRUD methods, and also the database connection methods.
It's basically the core of all other classes that uses the DB.
I'm currently facing a problem on dealing with duplicate entry in unique columns, when inserting a record.
Database.class.php insertDB method:
class Database {
(...)
public function insertDB($sql,$params=null){
$con=$this->connect();
$query=$con->prepare($sql);
$query->execute($params);
$rs = $con->lastInsertId();
return $rs;
self::__destruct();
}
(...)
}
There is another class, PersonDAO.class.php, which is a class that inherits Database.class.
PersonDAO.class.php has its own method for inserting a record, which finally uses Database.class.php InsertBD method.
PersonDAO.class.php insert method: (notice it calls insertDB at the end).
class PersonDAO extends Database{
(...)
public function insert ($fields, $params=null) {
$numparams="";
for($i=0;$i<count($params);$i++) $numparams .= ",?";
$numparams=substr($numparams, 1);
$sql = "INSERT INTO Person ($fields) VALUES ($numparams)";
$t=$this->insertDB($sql,$params);
return $t;
}
(...)
}
The problem occurs in the registration form register.php, when I instantiate PersonDAO and use its insert method for inserting a duplicate entry into a column set as unique.
(...)
$person= new PersonDAO();
$fields="email,name";
$email="john#doe.com"; //already existing record. email column set as unique
$name="John Doe";
$params=array($email,$name);
try {
$rs = $person->insert($fields,$params);
} catch (PDOException $e) {
if ($e->errorInfo[1] == 1062) {
echo "Cannot insert record. Duplicate entry";
}
}
(...)
It's not catching duplicate entry exception, as if there was no errors.
var_dump($rs) contains:
string(1) "0"
But should not it catch PDOException and print "Cannot insert record. Duplicate entry"?
Is there any "Uncaught Exception ..." message ? Perhaps, You first need to catch the Exception in your Database.class.php insertDB method and then throw it.
class Database {
(...)
public function insertDB($sql,$params=null){
try{
$con=$this->connect();
$query=$con->prepare($sql);
$query->execute($params);
$rs = $con->lastInsertId();
return $rs;
self::__destruct();
}
catch(Exception $e){
throw $e;
}
}
(...)
}
Or if there is no error at all. Check
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
I want to check whether the user has changed the Document image in the edit form. If the user changed the image, I have to delete the old one from database and filesystem, then I have to add the new one (in both db and filesystem).
Problem: if I edit a Document which has already got an image on the DB (so if $oldImage = $this->getImageByDocumentId($docId) actually returns $oldImage), everything works. But if the Document hasn't got any $oldImage, something goes wrong and it doesn't insert the new Image on DB (but It saves it on filesystem!)
This is part of my MySQLDocumentService:
public function editDocument($document) {
try {
$conn = $this->getAdapter();
$conn->beginTransaction();
$sql = "UPDATE Documents d
SET d.name=:name, d.description=:description, d.content_id=:contentId, d.category_id=:categoryId, d.sharer_id=:sharerId, d.rating_id=:ratingId, d.price=:price
WHERE d.document_id=:id";
$prepStatement = $conn->prepare($sql);
$prepStatement->execute(array(':id' => $document->getId(),
':name' => $document->getName(),
':description' => $document->getDescription(),
':contentId' => rand(1,2000),
':categoryId' => $document->getCategory()->getId(),
':sharerId' => 1,
':ratingId' => 1,
':price' => $document->getPrice()));
// If image has been changed, take the old image name
if (!is_null($document->getImage())) {
$image = $document->getImage();
$docId = $document->getId();
$oldImage = $this->getImageByDocumentId($docId); // Here's the problem: if it doesn't find the oldImage, it doesn't insert the new one
if (!is_null($oldImage)) {
// If previous method succeeded, delete oldImage from DB and filesystem
$oldImageName = $oldImage->getName();
$this->deleteImageByName($oldImageName);
}
// Save new image (chosen on form) on db and filesystem
if (file_exists("uploads/img/" . $image->getName())) {
echo $image->getName() . " already exists. ";
return false;
} else {
move_uploaded_file($image->getTempName(), "uploads/img/" . $image->getName());
}
// Saves image path on DB
// If I edit a Document which has already got an image on the DB, everything works. But if the Document hasn't got any oldImage, something goes wrong and it doesn't insert the new Image on DB (but It saves it on filesystem!)
$sqlImage = 'INSERT INTO Images (name, alt_name, position, description, type, size, document_id)
VALUES ("name", "altName", 2, "description", "type", "size", 2)';
$prepStatementImg = $conn->prepare($sqlImage);
$prepStatementImg->execute();
}
$conn->commit();
return true;
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}
}
public function getImageByDocumentId($docId) {
try {
$conn = $this->getAdapter();
$conn->beginTransaction();
$sql = 'SELECT i.image_id, i.document_id, i.name, i.alt_name, i.position, i.description, i.type, i.size
FROM Images i
WHERE i.document_id=:id';
$prepStatement = $conn->prepare($sql);
$prepStatement->execute(array(':id' => $docId));
$result = $prepStatement->fetch();
if ($result) {
$image = new Image();
$image->setName($result['name']);
$image->setId($result['image_id']);
$image->setAltName($result['alt_name']);
$image->setDescription($result['description']);
$image->setPosition($result['position']);
$image->setType($result['type']);
$image->setSize($result['size']);
// Manca la costruzione del relativo documento, ma non penso serva
$conn->commit();
return $image;
} else {
return null;
}
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}
}
public function deleteImageByName($imgName) {
try {
$imgName = str_replace( array( '..', '/', '\\', ':' ), '', $imgName );
unlink( "uploads/img/" . $imgName );
} catch (Exception $fsEx) {
echo "Failed: " . $fsEx->getMessage();
}
try {
$conn = $this->getAdapter();
$conn->beginTransaction();
$sql = 'DELETE FROM Images
WHERE name=:name';
$prepStatement = $conn->prepare($sql);
$prepStatement->execute(array(':name' => $imgName));
$conn->commit();
return true;
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}
}
If I comment $oldImage = $this->getImageByDocumentId($docId) it commits the INSERT of the new Image on DB and everything works.
I thought it could have been an issue with nested transactions, but it's strange since everything works when $oldImage is correctly found on db. (I also created a class that extends PDO class, as written on this guide).
What can I do?
EDIT: In one of the kind answers below (by Soyale), arose doubts about nested methods and multiple transitions. I thereby paste my MyPDO class, which should avoid multiple transitions (I hope so, at least). It's taken by bitluni's comment on PDO::beginTransaction manual page.
class MyPDO extends PDO {
protected $transactionCounter = 0;
function beginTransaction()
{
if(!$this->transactionCounter++)
return parent::beginTransaction();
return $this->transactionCounter >= 0;
}
function commit()
{
if(!--$this->transactionCounter)
return parent::commit();
return $this->transactionCounter >= 0;
}
function rollback()
{
if($this->transactionCounter >= 0)
{
$this->transactionCounter = 0;
return parent::rollback();
}
$this->transactionCounter = 0;
return false;
}
}
As Soyale stated,
parent::openTransaction [I think it's a typo for beginTransaction()] isn't good idea too. Or maybe if you have some flag that one of transaction was opened already it could pass the exam.
I think that transactionCounter could be the flag you're talking about. In my mind, this will let me commit and rollback properly. Am I wrong?
in my opinion You have mistake in this method: getImageByDocumentId.
You don't commit transaction in this fragmenty:
if ($result) {
$image = new Image();
$image->setName($result['name']);
$image->setId($result['image_id']);
$image->setAltName($result['alt_name']);
$image->setDescription($result['description']);
$image->setPosition($result['position']);
$image->setType($result['type']);
$image->setSize($result['size']);
// Manca la costruzione del relativo documento, ma non penso serva
$conn->commit();
return $image;
} else {
$conn->commit(); //Add this line :)
return null;
}
I'm wondering why are so many transactions there? It should be in one transaction so if one query fails then you can rollback all of them.
Some more words about transactions:
Lets look at your code:
public function editDocument($document) {
$conn = $this->getAdapter();
$conn->beginTransaction(); // 1-st open transaction
$this->getImageByDocumentId(...); // 2-nd opened transaction
$this->deleteImageByName(...); // And the third one
}
public function getImageByDocumentId($docId) {
$conn = $this->getAdapter();
$conn->beginTransaction();
//This method mainly select some data from DB so do you need transaction here ?
//Query in this method does not affect any data
//Data remains unchanged
//So you can use sth like this
$conn = $this->getAdapter();
//$conn->beginTransaction(); //-> tyhis line is useless
$sql = 'SELECT i.image_id, i.document_id, i.name, i.alt_name, i.position,
i.description, i.type, i.size
FROM Images i
WHERE i.document_id=:id';
$prepStatement = $conn->prepare($sql);
$prepStatement->execute(array(':id' => $docId));
$result = $prepStatement->fetch();
//(...) rest of code
}
public function deleteImageByName($imgName) {
$conn = $this->getAdapter();
$conn->beginTransaction();
}
as You can see every of yours method contains beginTransaction() It's a bit messy and lead to nested transactions and commits. I'm working mainly with Firebird DB and there if new transaction opened is the old one is moved down (we receive new resource handler).
Most interesting is deleteImageByName() method. As you can see there is already open one transaction (from editDocument()). Now You are opening the second one. Now you have delete your image deleteImageByName() has return true and commit transaction.
public function deleteImageByName($imgName) {
//In my opinion this fragment should go after successfully deleted from database
//and insert new image (prevent data loss)
try {
$imgName = str_replace( array( '..', '/', '\\', ':' ), '', $imgName );
unlink( "uploads/img/" . $imgName );
} catch (Exception $fsEx) {
echo "Failed: " . $fsEx->getMessage();
}
//here you are deleting db record
try {
$conn = $this->getAdapter();
$conn->beginTransaction();
$sql = 'DELETE FROM Images
WHERE name=:name';
$prepStatement = $conn->prepare($sql);
$prepStatement->execute(array(':name' => $imgName));
//And you are commiting this (bad idea if there is more than only delete task)
$conn->commit();
return true;
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}
}
Now if from some reason the insert fails, then you don't have new image nor the old one.
If there will be only one transaction (in main method editDocument()) you can rollback transaction and don't delete old image.
parent::openTransaction isn't good idea too. Or maybe if you have some flag that one of transaction was opened allready it could pass the exam.
Generally you should open transaction for one task. Lets suppose that your task is: editDocument. editDocument isn't simple action. It consist of bunch of other actions so the transaction (only one transaction from master method) should include all of these actions. (in your case delete old image and insert new one). Stomething like this:
public function editDocument() {
$conn = $this->getAdapter();
$conn->beginTransaction();
//1. $this->deleteOldImage();
//2. $this->insertNewOne();
//3. $this->deleteFileWithOldImage();
//Of every method should consist fail statement: $conn->rollback(); and throw exception
$conn->commit();
}
Sorry for my english :)
Edit: -> Why your class isn't so good
#KurtBourbaki This extension looks nice but it isn't. Please note that if you forgot to commit opened transaction then you continued with mess. In your question there was one mistake. Missing line. Please try to use your class with that bug. How it works ? Lets analize it:
class MyPDO extends PDO {
protected $transactionCounter = 0;
//1. Increment counter regardless of whether it was set
//2. PDO::beginTransaction() only if counter was 0
function beginTransaction()
{
if(!$this->transactionCounter++)
return parent::beginTransaction();
return $this->transactionCounter >= 0;
}
//This is interesting
//1. decrement counter
//2. PDO::commit() but only when decrement counter == 0
//So there is a core place because even with that class your primary bug will occur
//because You have omitted exactly this one command.
function commit()
{
if(!--$this->transactionCounter)
return parent::commit();
return $this->transactionCounter >= 0;
}
//rollback transaction looks good
}
I don't know why this answer was voted so high on php.net.
I saw there better solution than that. There is solution with simply private boolean flag posted by drm at melp dot nl on http://pl1.php.net/manual/en/pdo.begintransaction.php.
I prefer this one because it really doesn't allow to open multiple transaction.
EDIT:
As Kurt pointed out my choice isn't good either.
So as I have written in my last comment. My preferred solution is to never open nested transaction. There are some informations about transactions in documentation for DBMS. Most popular DB MySQL
try replacing, inside getImageByDocumentId function,
if($result)
by
if($prepStatement->rowCount()>0)
I think you're entering into the if when $prepStatement is executed, whether it has results or not, so your image is being empty, causing your script to break
If you insert data directly in your query you must have a $pdo->query not $pdo->prepare, well that's what I think
I believe your query should be
// Saves image path on DB
// If I edit a Document which has already got an image on the DB, everything works. But if the Document hasn't got any oldImage, something goes wrong and it doesn't insert the new Image on DB (but It saves it on filesystem!)
$sqlImage = 'INSERT INTO Images (name, alt_name, position, description, type, size, document_id)
VALUES (:name, :altName, :position, :description, :type, :size, :id)';
$prepStatementImg = $conn->prepare($sqlImage);
I have a page on my website (high traffic) that does an insert on every page load.
I am curious of the fastest and safest way to (catch an error) and continue if the system is not able to do the insert into MySQL. Should I use try/catch or die or something else. I want to make sure the insert happens but if for some reason it can't I want the page to continue to load anyway.
...
$db = mysql_select_db('mobile', $conn);
mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'") or die('Error #10');
mysql_close($conn);
...
Checking the documentation shows that its returns false on an error. So use the return status rather than or die(). It will return false if it fails, which you can log (or whatever you want to do) and then continue.
$rv = mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'");
if ( $rv === false ){
//handle the error here
}
//page continues loading
This can do the trick,
function createLog($data){
$file = "Your path/incompletejobs.txt";
$fh = fopen($file, 'a') or die("can't open file");
fwrite($fh,$data);
fclose($fh);
}
$qry="INSERT INTO redirects SET ua_string = '$ua_string'"
$result=mysql_query($qry);
if(!$result){
createLog(mysql_error());
}
You can implement throwing exceptions on mysql query fail on your own. What you need is to write a wrapper for mysql_query function, e.g.:
// user defined. corresponding MySQL errno for duplicate key entry
const MYSQL_DUPLICATE_KEY_ENTRY = 1022;
// user defined MySQL exceptions
class MySQLException extends Exception {}
class MySQLDuplicateKeyException extends MySQLException {}
function my_mysql_query($query, $conn=false) {
$res = mysql_query($query, $conn);
if (!$res) {
$errno = mysql_errno($conn);
$error = mysql_error($conn);
switch ($errno) {
case MYSQL_DUPLICATE_KEY_ENTRY:
throw new MySQLDuplicateKeyException($error, $errno);
break;
default:
throw MySQLException($error, $errno);
break;
}
}
// ...
// doing something
// ...
if ($something_is_wrong) {
throw new Exception("Logic exception while performing query result processing");
}
}
try {
mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'")
}
catch (MySQLDuplicateKeyException $e) {
// duplicate entry exception
$e->getMessage();
}
catch (MySQLException $e) {
// other mysql exception (not duplicate key entry)
$e->getMessage();
}
catch (Exception $e) {
// not a MySQL exception
$e->getMessage();
}
if you want to log the error etc you should use try/catch, if you dont; just put # before mysql_query
edit :
you can use try catch like this; so you can log the error and let the page continue to load
function throw_ex($er){
throw new Exception($er);
}
try {
mysql_connect(localhost,'user','pass');
mysql_select_db('test');
$q = mysql_query('select * from asdasda') or throw_ex(mysql_error());
}
catch(exception $e) {
echo "ex: ".$e;
}
Elaborating on yasaluyari's answer I would stick with something like this:
We can just modify our mysql_query as follows:
function mysql_catchquery($query,$emsg='Error submitting the query'){
if ($result=mysql_query($query)) return $result;
else throw new Exception($emsg);
}
Now we can simply use it like this, some good example:
try {
mysql_catchquery('CREATE TEMPORARY TABLE a (ID int(6))');
mysql_catchquery('insert into a values(666),(418),(93)');
mysql_catchquery('insert into b(ID, name) select a.ID, c.name from a join c on a.ID=c.ID');
$result=mysql_catchquery('select * from d where ID=7777777');
while ($tmp=mysql_fetch_assoc($result)) { ... }
} catch (Exception $e) {
echo $e->getMessage();
}
Note how beautiful it is. Whenever any of the qq fails we gtfo with our errors. And you can also note that we don't need now to store the state of the writing queries into a $result variable for verification, because our function now handles it by itself. And the same way it handles the selects, it just assigns the result to a variable as does the normal function, yet handles the errors within itself.
Also note, we don't need to show the actual errors since they bear huge security risk, especially so with this outdated extension. That is why our default will be just fine most of the time. Yet, if we do want to notify the user for some particular query error, we can always pass the second parameter to display our custom error message.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
I am not sure if there is a mysql version of this but adding this line of code allows throwing mysqli_sql_exception.
I know, passed a lot of time and the question is already checked answered but I got a different answer and it may be helpful.
$sql = "INSERT INTO customer(FIELDS)VALUES(VALUES)";
mysql_query($sql);
if (mysql_errno())
{
echo "<script>alert('License already registered');location.replace('customerform.html');</script>";
}
To catch specific error in Mysqli
$conn = ...;
$q = "INSERT INTO redirects (ua_string) VALUES ('$ua_string')";
if (mysqli_query($conn, $q)) {
// Successful
}
else {
die('Mysqli Error: '.$conn->error); // Show Error Complete Description
}
mysqli_close($conn);
Use any method described in the previous post to somehow catch the mysql error.
Most common is:
$res = mysql_query('bla');
if ($res===false) {
//error
die();
}
//normal page
This would also work:
function error() {
//error
die()
}
$res = mysql_query('bla') or error();
//normal page
try { ... } catch {Exception $e) { .... } will not work!
Note: Not directly related to you question but I think it would much more better if you display something usefull to the user. I would never revisit a website that just displays a blank screen or any mysterious error message.
$new_user = new User($user);
$mapper = $this->spot->mapper("App\User");
try{
$id = $mapper->save($new_user);
}catch(Exception $exception){
$data["error"] = true;
$data["message"] = "Error while insertion. Erron in the query";
$data["data"] = $exception->getMessage();
return $response->withStatus(409)
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
if error occurs, you will get something like this->
{
"error": true,
"message": "Error while insertion. Erron in the query",
"data": "An exception occurred while executing 'INSERT INTO \"user\" (...) VALUES (...)' with params [...]:\n\nSQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for integer: \"default\"" }
with status code:409.