erikla Posted July 25, 2014 Share Posted July 25, 2014 I have been reading in Larry Ullmans book "Visual QuickPro Guide PHP 6 and MySQL 5" and I find it well-written. Since it is from 2008, it does not contain anything about MySQL PDO, but rather does it in the mysqli_* way. Larry suggest placing the secret database password and more along with a database connection script in a connect.php file, placed above the webroot if possible. Then later, when he is creating queries and executing them in other php files, he includes the connect.php file before making the queries. Now I know it is very important to be careful with the Error handling, so the script won't output errors, which could reveal something about the database making it less secure. Therefore I am wondering how to structure things when using PDO. I need to write error-handling scripts for the following situations: a) Connection to the database doesn't succeed b) The execution of the queries doesn't succeed c) User input in HTML forms are not appropriate and probably more. The recommended way of handling errors when using PDO seems to be writing some try-catch code. But then I don't see how I can keep the connection to the database completely inside the connect.php file. Either I will need to use a die() or exit() inside this file or I will need to give up my idea to keep everything which concerns the connection to the database in the file mentioned AND write nested try-catch sentences - first make sure the connection works, then make sure the query will execute properly. I don't like either of those approaches. Firstly I have been told that using exit() is bad programming and secondly it seems to get more complicated using nested try-catch code and to let database connection take part in diverse php-files. Maybe somebody have a smart, convenient and secure way to do it? Erik Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/ Share on other sites More sharing options...
kicken Posted July 25, 2014 Share Posted July 25, 2014 The recommended way of handling errors when using PDO seems to be writing some try-catch code. But then I don't see how I can keep the connection to the database completely inside the connect.php file. All you have to do is make sure the include statement is within the try block. <?php try { include 'connect.php'; //rest of your query code. } catch (PDOException $e){ echo 'Database operation failed'; } If the code in your connect.php file, or any of the other code in the block throws a PDOException then it will be handled by the catch block. Throwing and catching errors is not file specific, you can throw an error in one file and catch it in another one. All that matters is that the throw is contained (directly or indirectly via includes/function calls) within a try block at some level of execution. If you route all your requests through a single front-end file, it is generally a good idea to include a try/catch for generic exceptions at that level and output some simple error page. <?php try { //start request processing //Include whatever file will handle this request include 'whatever.php'; //cleanup after the request } catch (Exception $e){ //output a generic error page. //and log the error somewhere } Then you can just let your database code throw an exception and it will be caught at the top level and cause a generic error page to be displayed. If in some instance you want to know if the database throws an exception and handle it you can use another try/catch block within the requests file's code to catch it rather than letting it bubble up to the top. 1 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486139 Share on other sites More sharing options...
erikla Posted July 25, 2014 Author Share Posted July 25, 2014 (edited) Thanks, it helps a lot! I tried your suggestions and now it works. It is actually a guestbook. File 1 contains the connection details (connect.php), File 2 is containing a html form, which is supposed to be filled out by the user and the input is posted to File 3, which will try to insert the contribution from the user, including details, into the database table - guestbook. When this is accomplished, the php code will redirect to File 4, which will then display the content of the guestbook. Here is the php code of File 3, that you helped me write: <?php header('Content-Type: text/html; charset=utf-8'); //Ensuring the correct charset $ip = $_SERVER['REMOTE_ADDR']; //Collecting users IP address $name = $_POST['name']; //Data from input form etc. $email = $_POST['email']; $contribution = $_POST['contribution']; $antispam = $_POST['antispam']; try { require("connect.php"); try { $stmt = $db->prepare("INSERT INTO guestbook(`time`, `ip`, `name`, `email`, `contribution`) VALUES(NOW(), ?, ?, ?, ?)"); $stmt->execute(array($ip, $name, $email, $contribution)); //Inserting the new contribution with details into Guestbook $db = NULL; //Closing database header("Location: show_content.php"); //Redirecting to the page which will show the content of the Guestbook } catch(PDOException $ex) { echo 'Could not insert into Guestbook'.'<br/>'; } } catch(PDOException $ex) { echo 'Could not connect to database'.'<br/>'; } ?> I have yet another question: As you can see, I have added a try-catch inside the first one to take into account if the connection to the database will succeed, but the insert query will not succeed. Am I right when I assume that this is a possible scenario even if you don't make any syntactical errors? I don't really know how the database behave ... I know I should write some log file to collect information for debugging purposes. Besides, my next step will be to handle the user input. I need to validate if the user input is appropriate (in the name, email and contribution fields). The user could have forgotten to fill out a field or he could have entered malicious code. Now I know PDO is not vulnerable to sql-injection, but would it be a good thing to put the contribution through a mysqli_real_escape_string() anyway? Third question: would it be better to use require_once(connect.php) instead of just require(connect.php)? I will be delighted if you could clarify my last three questions above. Then I will use some of the technique explained in Ullmans book to accomplish the validation. Again thanks a lot! Erik Edited July 25, 2014 by erikla Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486158 Share on other sites More sharing options...
kicken Posted July 25, 2014 Share Posted July 25, 2014 I have yet another question: As you can see, I have added a try-catch inside the first one to take into account if the connection to the database will succeed, but the insert query will not succeed. Am I right when I assume that this is a possible scenario even if you don't make any syntactical errors? I don't really know how the database behave ...It is a possibility yes. The insert could fail for various reasons. You do not need a separate try/catch for that however unless you want to provide detailed error messages back to the user, which is unnecessary. All the user needs is a generic 'Something went wrong' error, while you would just log the detailed exception data for you to look at else where. All you need is the outer most try/catch in your code. The inner one can be removed. Now I know PDO is not vulnerable to sql-injection, but would it be a good thing to put the contribution through a mysqli_real_escape_string() anyway?No, you do not want to do any escaping when using prepared statements with bound parameters. Escaping would only result in mangled data. Third question: would it be better to use require_once(connect.php) instead of just require(connect.php)? Wouldn't hurt, but unless you might call require 'connect.php' again somewhere else in the code it doesn't make any real difference which you use. 1 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486159 Share on other sites More sharing options...
Jacques1 Posted July 26, 2014 Share Posted July 26, 2014 You generally don't catch exceptions at all, not on the top level and especially not at random locations in the code. I wonder why so many people believe that they should clutter their scripts with try-catch blocks. The purpose of this statement is to handle errors. In some rare cases, you may indeed be able to recover from an error or at least do something useful. But most of the time, you really cannot do anything about the problem. For example, if a query fails, there's either a bug in your code or an issue with the database server. Neither can be fixed from within PHP, so the correct reaction is to leave the exception alone and let PHP do its standard error procedure. And, no, you do not tell your users about a failed database connection or a crashed query. What are they supposed to do with this information? It's none of their business. A big try-catch block on the top level doesn't make sense either, because most PHP errors are not exceptions, which means they aren't affected by this at all. And again: Why not just use the standard error procedure? Yes, PHP itself is perfectly capable of dealing with errors. It generates detailed messages with all relevant information, it can display those messages to ease development, it can log them in production, and it can emit the right HTTP error code so that the webserver may display a user-friendly error page. The only reason why you'd write your own error handling procedure is if you want to do something special. Is that the case? What do you want to do apart from logging the message and displaying a friendly error page? 2 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486168 Share on other sites More sharing options...
erikla Posted July 26, 2014 Author Share Posted July 26, 2014 (edited) Thanks to both of you! I have now removed one of the try-catch blocks and added code for validating user input in the fields name, email and contribution and one more: antispam. The latter is a precaution I have used earlier to prevent spam entered into the guestbook by code - after actually having encountered it! I just ask people to write "seven" as a number in an additional field in the form. I have tried Captchas earlier but don't really like them - they can be hard to figure even for a human! It works perfectly with this easy question. Because of your comments, kicken, I avoided using the mysqli_real_escape_string(). I am however still a bit worried that although malicious code can not do any harm when entered using the PDO prepared statement, it still is entered unchanged into the database, and eventually could cause harm later, when it is handled in the database by maybe non prepared statements, or are these worries unfounded? I mean when I later want to display all contributions in the guestbook in File 4, I assume I cannot do the SELECT query as a prepared statement, since there are no parameters present? Regarding using require or require_once, I will actually need to use the database connection again later, when the content of the database is displayed - via another php page (File 4). So maybe I better use just require? Is the require_once a security measure? Why not just use require all the time? Jacques1, I understand your point that it is important that any error messages should be useful for the user, not just for the person, who wrote the script. I hope it is better now? <?php $ip = $_SERVER['REMOTE_ADDR']; //Collecting users IP address $name = trim($_POST['name']); //Data from input form etc. $email = trim($_POST['email']); $contribution = $_POST['contribution']; $antispam = $_POST['antispam']; //Collecting an answer to prevent spam $errors = array(); //An array to collect input errors from the form. Here it is initialised if ($antispam != 7) {$errors[] = 'Your answer in the antispam field is incorrect or missing.';} if (empty($name)) {$errors[] = 'You forgot to enter your name.';} if (empty($email)) {$errors[] = 'You forgot to enter your email address.';} if (empty(trim($contribution))) {$errors[] = 'You forgot to deliver a contribution.';} if (empty($errors)) { //If no errors from the form, we proceed to the database to enter details ... try { require("gb_connection_guestb.php"); $stmt = $db->prepare("INSERT INTO guestbook(`time`, `ip`, `name`, `email`, `contribution`) VALUES(NOW(), ?, ?, ?, ?)"); $stmt->execute(array($ip, $name, $email, $contribution)); //Inserting the new contribution with details into Guestbook $db = NULL; //Closing database header("Location: gb_show_content.php"); //Redirecting to the page which will show the content of the Guestbook } catch(PDOException $ex) { echo 'Could not enter your contribution in the database. We apologize for the inconvenience!'.'<br/>'; } } else { //If errors they are displayed and the user encouraged to use the back-button in the browser ... echo '<h1>Fejl!</h1><p>The following error(s) occurred:</p></br>'; foreach ($errors as $msg) {echo $msg.'</br>';} echo '</br>'.'Use the Back button in the Browser and correct your input in the form.'; } ?> Notice that I have used the trim operation to remove any white spaces before and after name and email address, also to handle errors better ... A big try-catch block on the top level doesn't make sense either, because most PHP errors are not exceptions, which means they aren't affected by this at all. And again: Why not just use the standard error procedure? I am not completely sure about what you mean here, Jacques1? Should I still change something? I am a little unsure how to handle eventual error messages for my own debugging purposes? Again big thanks for your advice! Erik Edited July 26, 2014 by erikla Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486184 Share on other sites More sharing options...
Jacques1 Posted July 29, 2014 Share Posted July 29, 2014 Because of your comments, kicken, I avoided using the mysqli_real_escape_string(). I am however still a bit worried that although malicious code can not do any harm when entered using the PDO prepared statement, it still is entered unchanged into the database, and eventually could cause harm later, when it is handled in the database by maybe non prepared statements, or are these worries unfounded? I mean when I later want to display all contributions in the guestbook in File 4, I assume I cannot do the SELECT query as a prepared statement, since there are no parameters present? Several things. First of all, prepared statements are only immune against SQL injections if you've set the PDO::ATTR_EMULATE_PREPARE attribute to false and use a constant query string without any dynamic values. You cannot use mysqli_real_escape_string() at all. Like the name already says, this is a MySQLi function. PDO and MySQLi are two entirely different extensions which have nothing to do with each other. If you want to do manual escaping in PDO, you need to use PDO::quote(). However, there seems to be a general misunderstanding about how escaping works. You do not store “pre-escaped” strings. The database is supposed to hold the actual unaltered data. If a person has the lastname “O’Sullivan”, you store that as “O’Sullivan”, not “O\’Sullivan”, “O'Sullivan” or whatever. Storing escaped data is an awful idea. What if you need to use it in a different context? For example, what if you want to display your SQL-escaped string in your HTML document? Then you first need to revert the SQL-escaping, retrieve the original value and finally apply HTML-escaping. Hell, you couldn't even query the database for names of a certain length, because the escaping characters are in the way. But what's even worse: Using “pre-escaped” strings means that you blindly trust your database content. What if one of the values is not escaped? Maybe there's a bug, maybe an admin has manually inserted the data. In any case, you now have an SQL injection vulnerability or at least a bug. Escaping is always done ad hoc, never in advance. Regarding using require or require_once, I will actually need to use the database connection again later, when the content of the database is displayed - via another php page (File 4). So maybe I better use just require? Is the require_once a security measure? Why not just use require all the time? There seems to be a misunderstanding. Once the database logic is loaded, you can use it anywhere in the current script context (including sub-scripts) and as often as you want. Using require would make absolutely no sense, because you'd constantly reconnect to the database while overwriting the current connection. The database part is supposed to be executed only once per script execution. Jacques1, I understand your point that it is important that any error messages should be useful for the user, not just for the person, who wrote the script. I hope it is better now? You don't understand. My point is that it's nonsensical to have an error-handling procedure for every single error. In general, you always want to do the same two things: Log the internal error message. Have the webserver display a generic error page. Those are standard features of PHP and your webserver. If you just let the software do its job, you probably don't have to write a single line of code. What is the point of telling the user about your database issues? They cannot fix them, can they? All they need to know is that the application failed. So in general, you do not catch exceptions. Just let PHP handle this. The only time when you catch an exception is when you actually want to solve the problem or do something special with the error. OK, let's say it's absolutely crucial to tell the user that their data hasn't been inserted (as opposed to some other problem). Then you still wouldn't stop the whole error procedure. You'd add your information and then rethrow the exception. But again: In general, you do not catch exceptions. They work just fine without human intervention. 1 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486363 Share on other sites More sharing options...
erikla Posted July 29, 2014 Author Share Posted July 29, 2014 Thanks, Jacques1, for pinpointing my (many) misunderstandings. I am a mathematician trying to 'dig' into PHP/MySQL without any formal education in this language. Regarding sql injection I now understand better. It can only occur if the query contains dynamic parameters. It also helped reading the Wikipedia article about the subject. Here an explicit example is being displayed in which the user can make a certain input, which unintentionally would change the query completely, typically from a limited SELECT query to a SELECT query involving all records from the database. For example a user in a usergroup would be able to retrieve not just his own data, but the data from all user! Prepared statements then solve the problem of having the user's input "glued" together with the servers part of the query to make an unfortunate query, by handling the servers part and the users input separately. Regarding try-catch, then I am unsure if I am understanding what you mean: Should I avoid using the try-catch operation at all? If so, I know of no way to take care of the situation in which one cannot connect to the database (Maybe the webhotel is down?) or I have accidentally delivered a wrong password or the like. Without using try-catch the user will receive an error message from the server, which is quite complicated and which could reveal something about the filenames and more ... Now I am actually considering going back using mysqli instead of PDO, because Ulmann's book is using exactly that and PDO is so new, there does not seem to be many books about it (if any) yet. I am simply missing some material (books, articles or pdf files on the Internet) containing practical code in real-World problems to be able to really getting to grips with it. The PDO Tutorial for MySQL Developers on Hashphp.org is pretty good as an overview article, but I need more examples on how to use PDO. I haven't been able to find anything useful, though. It is a pity, because I was adviced to use PDO on this site ... Erik Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486387 Share on other sites More sharing options...
kicken Posted July 29, 2014 Share Posted July 29, 2014 Regarding try-catch, then I am unsure if I am understanding what you mean: Should I avoid using the try-catch operation at all? If so, I know of no way to take care of the situation in which one cannot connect to the database (Maybe the webhotel is down?) or I have accidentally delivered a wrong password or the like. Without using try-catch the user will receive an error message from the server, which is quite complicated and which could reveal something about the filenames and more Depending on how you have PHP setup with the server, how PHP is configured, and how the server is configured then not catching an exception could range from getting a stack trace printed to the screen to a simple 500 error message with no useful information printed. I believe what Jacques1 is suggesting is that you should make sure PHP logs the error rather than reports it, and then returns the 500 error. You could then configure the server to send back a nicer page for the 500 error by using it's error document configuration That's all fine and dandy if you have that level of control over your setup, but you may not (ie, shared hosting) so I personally dis-agree and would rather perform a generic try/catch at the top level and generate an error page manually with PHP. It's less prone to mis-configuration issues and does not add a lot of extra programming work or overhead. ... Now I am actually considering going back using mysqli instead of PDO, because Ulmann's book is using exactly that and PDO is so new, there does not seem to be many books about it (if any) yet. I am simply missing some material (books, articles or pdf files on the Internet) containing practical code in real-World problems to be able to really getting to grips with it. The PDO Tutorial for MySQL Developers on Hashphp.org is pretty good as an overview article, but I need more examples on how to use PDO. I haven't been able to find anything useful, though. It is a pity, because I was adviced to use PDO on this site ... I can't speak to the availability of physical books with PDO as I've not touched a PHP book, but there is plenty of information on the internet regarding how it is used, and the manual is an excellent reference. I would highly recommend you stick with PDO, primarily because it's API is much simpler when it comes to doing prepared queries with parameters compared to MySQLi's. 1 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486406 Share on other sites More sharing options...
Jacques1 Posted July 29, 2014 Share Posted July 29, 2014 Definitely stick to PDO. You already know all the important parts, and switching to MySQLi would be a huge step backwards. Also, the current issues have nothing to do with PDO in particular. I understand now why you're struggling with exceptions. You think that every uncaught exception will dump the internal error message on the screen. This is not the case. How PHP deals with errors (which includes exceptions) depends on the configuration. During development, it makes a lot of sense to display the error messages on the screen, so you turn display_errors on. In a live environment, you want to log the errors instead of displaying them, so you turn display_errors off and log_errors on. The only thing left to do is set up a user-friendly error page in the webserver. How this works depends on your webserver and the architecture you're using (CGI? FastCGI?). If you need help with this, you should create a new thread. 1 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486407 Share on other sites More sharing options...
Jacques1 Posted July 29, 2014 Share Posted July 29, 2014 That's all fine and dandy if you have that level of control over your setup, but you may not (ie, shared hosting) so I personally dis-agree and would rather perform a generic try/catch at the top level and generate an error page manually with PHP. It's less prone to mis-configuration issues and does not add a lot of extra programming work or overhead. Again: Only a small part of PHP errors are exceptions, so your global try-catch doesn't get you anywhere. If at all, you'd use an error handler to catch all errors, not just exceptions. However, if your hoster gives you absolutely no control over the configuration, the solution is to switch to one that does rather than try to come up with strange workarounds. In fact, global error handling at runtime doesn't even work, because it obviously only covers errors which happen after the initialization. What about the others? Error handling needs to be done by the webserver outside of the script. This can partially be emulated with the auto_prepend_file directive. But before we do all kinds of speculation, let's hear about the OP's setup. 1 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486409 Share on other sites More sharing options...
erikla Posted July 29, 2014 Author Share Posted July 29, 2014 Depending on how you have PHP setup with the server, how PHP is configured, and how the server is configured then not catching an exception could range from getting a stack trace printed to the screen to a simple 500 error message with no useful information printed. I believe what Jacques1 is suggesting is that you should make sure PHP logs the error rather than reports it, and then returns the 500 error. You could then configure the server to send back a nicer page for the 500 error by using it's error document configuration That's all fine and dandy if you have that level of control over your setup, but you may not (ie, shared hosting) so I personally dis-agree and would rather perform a generic try/catch at the top level and generate an error page manually with PHP. It's less prone to mis-configuration issues and does not add a lot of extra programming work or overhead. That's exactly what I like to hear kicken! Right, I have no control over my Web hotels configuration at the moment, so I rather prefer to have my php code make an exception in order NOT to have the web server write out a lot of garbage, which could confuse the user and maybe even reveal something which would make my database less secure. Maybe later, if I manage to get more knowledge about how to turn off error reporting at the server at my web hotel, I will think about doing it in another way. And I promise, Jacques1, to ask in another thread then, so the this thread won't turn out too 'bulky' so to say . Also - since both of you advice me to - I will stay with PDO and try making it work. I am currently working on displaying the content of my questbook in File 4 and hope I will succeed. One question: I am a bit puzzled about the term 'catching an exception at the top level'. At the moment when working on File 4, I have a big section of code (in fact all of it) included inside the try section. One can easily loose the overview, but I try to make comments along the way. I have been looking for ways to handle the try thing with a function/procedure call, but have not found an obvious way to do so. Maybe it is good enough the way I do it ... Again I appreciate your replies. I feel I am getting closer to the goal! Erik Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486413 Share on other sites More sharing options...
mogosselin Posted July 29, 2014 Share Posted July 29, 2014 One question: I am a bit puzzled about the term 'catching an exception at the top level'. At the moment when working on File 4, I have a big section of code (in fact all of it) included inside the try section. One can easily loose the overview, but I try to make comments along the way. I have been looking for ways to handle the try thing with a function/procedure call, but have not found an obvious way to do so. Maybe it is good enough the way I do it ... 'Catching an exception at the top level' means not trying to do anything with the exception right away when it was raised and let the error 'bubble up'. If, on your server, a custom error page is displayed when an error is thrown, it's good enough in most of the cases, except if you can do something about the exception. For example, imagine that you have a sidebar on your website that displays your last twitter updates. The data comes from php classes that you are using. These classes throws exception like 'TwitterUnavailableException' when twitter cannot be reached. Displaying a complete error page to your users when twitter is down isn't really good. So, in that case, you could catch the 'TwitterUnavailableException' and hide the box that displays the twitter statuses in your sidebar. But, if your database doesn't work at all and your website is 99% displayed with data coming from your database, even if you catch it, what can you do about it? Nothing much... So you just display an error page to your users and log the error. Also, don't use 'die()' nor 'exit()'... if you ever have to use these kind of functions, use trigger_error(). And, what do you mean by... I have been looking for ways to handle the try thing with a function/procedure call, but have not found an obvious way to do so. Maybe it is good enough the way I do it ... ?? Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486415 Share on other sites More sharing options...
Jacques1 Posted July 29, 2014 Share Posted July 29, 2014 That's exactly what I like to hear kicken! Right, I have no control over my Web hotels configuration at the moment, so I rather prefer to have my php code make an exception in order NOT to have the web server write out a lot of garbage, which could confuse the user and maybe even reveal something which would make my database less secure. I think this thread is turning into a very, very wrong direction. I'm not sure why kicken even came up with this try-catch stuff, because this is objectively wrong, and he should definitely know that. Exceptions are only a small fraction of possible errors. In fact, they're a fairly recent addition to the PHP core and are only used in the “new”, object-oriented parts of PHP (PDO being one of them). All other functions use classical errors (notices, warnings, fatal errors etc.). So this big try-catch block catches maybe 5% of the errors and lets the other 95% through. This is nonsense. It's actually downright harmful if your error messages are indeed printed on the screen, because that means your users will see all the notices, warnings, fatal errors etc. You want a quick-and-dirty solution? OK, let's assume the administrator of your system is an evil bastard who has activated display_errors on your live server (which no sane admin would ever do) and prevents you from turning it off (which no sane admin would ever do). What you would do then is turn this setting off at runtime and register a shutdown function to display an error page: <?php /* * This is *not* a correct solution. It's a workaround for dealing with a * hypothetical evil admin who has misconfigured PHP and now won't let you * touch the configuration. */ // overwrite error settings at runtime ini_set('display_errors', 0); ini_set('log_errors', 1); ini_set('error_log', '/path/to/logfile'); function handle_fatal_errors() { if (http_response_code() == 500) { echo 'Sorry, there was a technical problem.'; } } register_shutdown_function('handle_fatal_errors'); The script only works in PHP 5.4 and above. If your hoster doesn't even offer that, this is getting silly. Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486432 Share on other sites More sharing options...
kicken Posted July 29, 2014 Share Posted July 29, 2014 So this big try-catch block catches maybe 5% of the errors and lets the other 95% through. This is nonsense. It's actually downright harmful if your error messages are indeed printed on the screen, because that means your users will see all the notices, warnings, fatal errors etc. function exception_error_handler($errno, $errstr, $errfile, $errline ) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } set_error_handler("exception_error_handler"); There, now you've converted most (but yes, not all) the traditional errors into an exception. That will cause even something like an E_NOTICE to throw an exception, if you want to avoid that then you'd have to add some extra logic to the error handler. The manual page for ErrorException has some extended implementations in the user comments or one could DIY it. For the final few percent make sure to configure display_errors off and set error_log to log them somewhere. Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486437 Share on other sites More sharing options...
Jacques1 Posted July 30, 2014 Share Posted July 30, 2014 Error handlers cannot catch fatal errors, but that's exactly the type we want to catch. In fact, catching anything other than fatal errors is a bad idea, because you're likely to run into a partially rendered page. In addition to that, you now have this strange double error handling: You first catch some errors to turn them into exceptions, and then you catch all exceptions to do the actual error handling. In fact, you need a third stage (rethrowing the exception) if you don't want to do the error logging manually. And let's not forget that the try-catch must be repeated for every single script which is accessed directly. Why spend five times as much effort on an approach which only works halfway? Only to keep the beloved try-catch statement? On the other hand, the shutdown handler above catches all relevant errors with a single function. This is actually an emulation of what a properly configured setup would do: PHP automatically triggers a 500 response code in case of a fatal error, and the webserver (or in our case PHP) displays an error page. Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486445 Share on other sites More sharing options...
erikla Posted July 30, 2014 Author Share Posted July 30, 2014 (edited) I disagree with you Jacques1, when you say that this thread is heading in the wrong direction. I can say, because it was me starting this thread. This topic about error handling (the words should probably have been indicated in the thread title) is in the core of my attention. When earlier using mysql_' and mysqli_* it seemed easier to handle the situations when problems occurred in connection with the database, because you could create a function (procedure) which could connect to the database if possible and just stopped with a die() if it couldn't. To me that was logically easier. Now I realize from what people tell me here, that using exit() and die() is in fact something which you should not use. Then here comes in the new way with PDO, which besides from having several important advantages regarding security, is handling database problems with exceptions. To learn to use PDO I have only seen small snippets of code. I think this fact made me put more emphasis on this catching exceptions than is really appropriate. I guess that is what Jacques1 is trying to tell me (please tell me if I am wrong). What I am really missing is watching a longer piece of code dealing with PDO. It could be a real-World solution of a guestbook, registration at a website or the like. I have been pre-ordering a book at Amazon, but it won't be ready in half a year or so. I need to see how people really are paying attention to error-handling, database errors as well as php errors. If you know of any source I would be happy to watch it. At the moment the structure in my show_content.php file, showing the content of the guestbook, is the following: <?php try { //A big block of code: Interaction with the database and php to manipulate it } catch(PDOException $ex) { //echo "Could not show content in guestbook"; } ?> It is maybe not the best way to do it, but it will catch any problem with the database. I mean: Any problem with the database not being able to connect or to insert or retrieve data will be handled with an exception and not with some server error messages, which I fear. I wish I could just put the try-catch block around only the code which has to do with database interaction, making it more readable, but if I do and there is a database problem, the code below the try-catch block will get executed after the exception and it will likely cause php errors. Therefore I see no other way than putting all of inside the try section. Is that "catching the exception at top level"? I am sorry that I have confused my intentions in this thread, probably due to my lack of experience and overview. My questions haven't been accurate and concise, I now see. Maybe you got the impression that I was looking for a very sophisticated kind of error-handling. I don't want to over-do things, though. On the other hand I don't want the server to write any database error messages which could be confusing and maybe reveal something about the database. I feel I can better control errors caused by the php code, because I am debugging things thoroughly locally using Xampp and it is more of a logical problem - although I can of course overlook something here too, which could eventually result in php errors. Thank you, Jacques1, for the code to force the server to handle errors in a specific way. I now see it is also mentioned in Ullman's book. Good to know even if I won't use it now. Also thanks for the error-handling function, kicken. Finally I watched your website, mogosselin. Looks good. I will look at it later ... Erik Edited July 30, 2014 by erikla Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486476 Share on other sites More sharing options...
Solution Jacques1 Posted July 30, 2014 Solution Share Posted July 30, 2014 Erik, the problem is that you happily adopt any nonsense which matches your expectations, but you have a very hard time giving up a wrong expectation for the sake of a good solution. Do you think you can put aside all the expectations for a minute and just be open-minded? Forget about exceptions for now. In PHP, we're dealing with errors. Exceptions are just a subset of errors, and they're useful when you start to program object-oriented. But at this point, they're completely irrelevant. Forget about the try-catch statement. Strike it from your memory. OK, now we're talking about errors. There are many different types of them (15, to be exact), and if your PHP setup is misconfigured, they'll all be printed on the screen. You don't want this, so you need to suppress the error messages. This is done with ini_set('display_errors', 0). Now your users will see a blank screen instead of an error. This better but not perfect. You actually want an error page instead of a blank screen, so you need PHP to execute a custom function in case of an error. The obvious solution would be an error handler, but this doesn't work, because error handlers cannot catch fatal errors (which are the most important ones). What you need is a shutdown function. And while you were busy catching exceptions, I already wrote down a solution. You must have missed it. If you just cannot give up your old ideas and try something new, I'm OK with that. At this point, it doesn't matter, because it's all just for fun. Your users probably won't mind too much if they're bombarded with PHP errors. But in the long run (especially if you plan to do this professionally), you need to reconsider your approach. Making a mistake is OK. Making the same mistake over and over again even if you know that it's wrong is a problem. 1 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486491 Share on other sites More sharing options...
erikla Posted July 31, 2014 Author Share Posted July 31, 2014 You are right, Jacques1, I am a stubborn chap. Thanks to your patience you finally broke through my shell I have tested your suggestions by adding your code pieces and commented out the try-catch parts. Then I changed the password to a wrong one and executed the page. It is correct that without the error handler, I received a blank page, and when I included it, I got the error message without any bad messages. I like this better far better than creating exceptions. What I don't understand is then, why these tutorials (both in print and YouTube videos) pay so much attention to these exceptions. At least when it is only error reporting, and it is in most cases, I guess, it seems obsolete ... NB! I haven't tested if my web hotel has v. 5.4+ of php, but I assume it has. Again thanks a lot! Erik Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486509 Share on other sites More sharing options...
Jacques1 Posted July 31, 2014 Share Posted July 31, 2014 You are right, Jacques1, I am a stubborn chap. Thanks to your patience you finally broke through my shell Cool. What I don't understand is then, why these tutorials (both in print and YouTube videos) pay so much attention to these exceptions. At least when it is only error reporting, and it is in most cases, I guess, it seems obsolete ... It's a sad fact that many people who write PHP tutorials have absolutely no idea what they're doing. You'd think they're experts you can learn from, but in reality, they're often just parotting the same nonsense that has been around for years. PHP is somewhat infamous for bad tutorials. One of the core developers once described it as “the blind leading the blind”, and this is very true. So while tutorials may give you some ideas and inspiration, you should be very critical and question everything. Just because thousands of PHP programmers use a certain practice doesn't mean that it makes sense. Error handling in particular seems to be extremely difficult for many people. Hell, even the PHP manual can't get it right: In their example code for establishing a PDO connection, they immediately catch the exception, print the raw error message on the screen and then continue script execution. That's ... not intelligent. One might try to explain this away as a kind of demonstration, but the PHP developers should know that the exact code will be copied and pasted around for the next 30 years. So you should indeed question everything, even example code from the PHP manual. Of course you cannot possibly take care of every little detail while you're still learning the language. But whenever you have the chance for doing research and thinking about a problem, do it. NB! I haven't tested if my web hotel has v. 5.4+ of php, but I assume it has. If not, it's just a few lines of extra code. But then you definitely need a new hoster. Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486510 Share on other sites More sharing options...
erikla Posted July 31, 2014 Author Share Posted July 31, 2014 It's a sad fact that many people who write PHP tutorials have absolutely no idea what they're doing. You'd think they're experts you can learn from, but in reality, they're often just parotting the same nonsense that has been around for years. I completely agree with you. I have been wondering while going from one tutorial to another: I often immediately get a feeling I have somehow seen this before. Sometimes it is even the very same examples they use, maybe only shuffled around a bit. It is a pity when people offering tutorials don't think for themselves and show their own experiences, rather than mimicing others. I feel I get better information from books (also larger web solutions), although they may probably also copy other peoples bad taste from time to time. Then it is great to have a Forum like this, where things can be questioned and you can eventually read about different solutions from different developers. I see there are a few tutorials at phpfreaks.com. Unfortunately some of them dealing with MySQL are outdated, since using predecated stuff like mysql_*. Also there have been no new tutorials since 2010. With your experience and knowledge you should consider writing one with a typical database problem in PDO - if you have time and like to of course. It could be very helpful and people here could refer to it when people ask similar questions. It should not just be code snippets, but a little larger application to show the user the bigger picture. Typical examples would be a guestbook or registration in a usergroup (intermediate degree of difficulty, I guess). I myself is maintaining a couple of webpages with mathematical content. Here is a link to the only page I have written in English. The rest is in Danish, my native language. But it is a large page: http://www.matematiksider.dk/enigma_eng.html. In fact my guestbook isn't working properly here and that's why I am posing all these questions here NB! My web hotel is www.one.com. I guess it has the necessary setup. Thanks, Erik Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486522 Share on other sites More sharing options...
erikla Posted July 31, 2014 Author Share Posted July 31, 2014 (edited) Sorry I am getting back, Jacques1, but I have encountered a problem, which I hope you can resolve: I have been using your suggestion, placing the following code at the top of my php page (the page showing the content of my guestbook): <?php function handle_fatal_errors() { if (http_response_code() == 500) {echo 'A Technical error ocurred';} } register_shutdown_function('handle_fatal_errors'); ini_set('display_errors', 0); As I told you yesterday, that if I changed the password to a wrong one and updated the page, it did correctly show the phrase "A Tecnical error ocurred", as expected. If I however in Dreamweaver start a new instant of Internet Explorer by hitting Preview in Browser > Preview in Internet Explorer, then an error page is shown named "An Internal Http 500 server error ocurred" and not a page with the desired text above. This is really strange: If creating a new page when the password is wrong, an error page is displayed, but when updating a page in which the script has been executed with the correct password previously, the correct phrase is shown. When I make previews in Firefox and Chrome, it works properly in both situations, however. Can you explain this behavior and tell me a fix to make it work in Explorer too? Erik Edited July 31, 2014 by erikla Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486529 Share on other sites More sharing options...
Jacques1 Posted July 31, 2014 Share Posted July 31, 2014 This is one of those silly quirks of Internet Explorer: The size of the error page must exceed a certain limit, or else the browser will ignore it and instead display some default error message. The numbers from the article are still true, so you need at least 513 bytes of content. You can either create a complete HTML error page right now or ignore Internet Explorer until you have one. 1 Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486539 Share on other sites More sharing options...
erikla Posted July 31, 2014 Author Share Posted July 31, 2014 Thanks, Jacques1! This is about the most silly thing I have ever heard. Imagine you have used a lot of time to create the most lean code and feeling really satisfied about it. Then you need to fill it up with garbage to make IE eat it properly! I assume you prefer Firefox over IE? Unfortunately we need to take into account that a majority of people still use that browser. You can either create a complete HTML error page right now or ignore Internet Explorer until you have one. I don't know what you mean with a "complete HTML error page or how much work it will take? Erik Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486552 Share on other sites More sharing options...
Jacques1 Posted July 31, 2014 Share Posted July 31, 2014 I'm talking about a graphical error page with formatted text, images etc. Something like the Wikipedia error page. I mean, that single line of plaintext above was just for testing. In reality, it should be a proper page with a bit of visual appeal. Internet Explorer is indeed a pain in the ass. This has improved over the years, but occasionally you still encounter the special IE brainfarts. Quote Link to comment https://forums.phpfreaks.com/topic/290112-structuring-database-connections-and-queries/#findComment-1486561 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.