Jump to content

mac_gyver

Staff Alumni
  • Posts

    5,354
  • Joined

  • Days Won

    173

Everything posted by mac_gyver

  1. that's because there is no error handling in your code for the database statements. the easiest way of handling things like database statement errors are to use exceptions. to enable exceptions of the msyqli statements, add the following lines of code, preferably before you make the database connection so that connection errors will also throw an exception - $driver = new mysqli_driver(); $driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT; // MYSQLI_REPORT_ALL <- w/index checking; w/o index checking -> MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT; then, if you have php's error_reporting set to E_ALL and display_errors set to ON, any database statement errors will throw an exception and be caught by php, which will report a fatal runtime error that contains the actual msyqli error information. after you add the error handling, and find which column name is producing a sql sytnax error, because it is a reserved keyword, you need to use a prepared query to supply the data values to the sql statement, rather than putting them directly into the sql query. the PDO extension is much easier and more consistent than the msyqli extension, especially for prepared queries. if you can, switch to the PDO extension.
  2. um. no you didn't. you still have several mysql_ statements in your code and the mysqli_ statements you do have are incorrect, which would be throwing php errors, if you had php's error_reporting/display_errors/log_errors settings set up correctly. you need make use of the php.net documentation for any php coding you do, so that you will know what each statement requires. also, you should not be manually building JSON encoded data. there's a function to do that - json_encode().
  3. before proceeding with a JOIN'ed query, do you even need two tables? if the UsersRegTable is only for the user online data, yes, you would need it and you would need to join it with the UserInfoTable table. however, based on the name UsersRegTable, this is general user information that happens to have a column to hold the last active time. if this is so, why do you have a second table UserInfoTable that is also holding general user information? if you do need two tables, you should relate them with the user_id, an auto-increment integer column in the primary table, not the username. also, if the UsersRegTable is only for the user online data, you likely have a SELECT query, followed by either an INSERT or the UPDATE query that you posted. this can all be replaced with a single INSERT ... ON DUPLICATE KEY UPDATE query.
  4. ^^^ that's not specific enough. 10 lines of what exactly? will there always be a row with one yellow element at the top and a row with one brown element at the bottom and the entered number of rows is the number of total rows or it it the number of green rows, and will the green rows always be 4 more elements than the proceeding row? you have to define the rules before you can write the code. you would then be calculating the number of elements to output, based on the current row number being output, rather than having the numbers and blocks of code hard-coded. also, your four variables should have meaningful names, and if you use str_repeat() instead of for(){} loops, your code will be clearer to read. your current code would look like this - $white = '<td style="background-color:white"> </td>'; $green = '<td style="background-color:green"> </td>'; $brown = '<td style="background-color:brown"> </td>'; $yellow = '<td style="background-color:yellow"> </td>'; echo "<tr>"; echo str_repeat($white,4); // the 4 would be a calculated value echo str_repeat($yellow,1); echo "</tr>"; echo "<tr>"; echo str_repeat($white,2); // the 2 and 5 in this block, for green rows, would be calculated values echo str_repeat($green,5); echo "</tr>"; echo "<tr>"; echo str_repeat($white,0); // all the green rows would be output inside of a loop, this block of code wouldn't exist echo str_repeat($green,9); echo "</tr>"; echo "<tr>"; echo str_repeat($white,4); // the 4 would be a calculated value echo str_repeat($brown,1); echo "</tr>"; you would basically be calculating the number of white and green elements in each row and the green row(s) would be output inside of a loop.
  5. to convert a design to use ajax, you are basically splitting and moving functionality around between the server-side and client-side code. however, your design should still work if javascript is disabled. therefore, the changes you make to the server-side code should be conditional, so that it produces the same exact output it does now, if javascript is disabled. when you make the ajax requests (one to post the form data and a second to get and display the account listing), the response your code returns needs to be just the data that you expect, not the whole web page. the response when you post the form data would be your $SaveMsgAccount/$msgBox on success, or validation errors or a generic 'cannot perform action' for query errors when it fails. the response when you get the account listing would be the html markup you are producing for that list now. you can detect if a request to a page was made via ajax - // determine if the request was an ajax request define('IS_AJAX_REQUEST', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); the IS_AJAX_REQUEST constant would be used in conditional statement(s) to control what gets output back to the browser. for the account listing, you would need to build the html markup in a php variable, so that you can either output it in the html document, for non-ajax requests, or output it in response to the ajax request. you would move the while(){} loop from where it is in the html document, to right after where you execute the sql query. You would define a variable to hold the markup, then build the markup in that variable - // run the query here... $list_content = ''; while($col = mysqli_fetch_assoc($GetListCategory)) { $list_content .= " <li class='table_row'> <div class='table_section'>{$col['AccountName']}</div> <div class='table_section_last'> </div> </li> "; } right before you start to output the html document, which i am assuming is at your "//Include Global page" code, you would output the response to the ajax request, then halt execution so that the html document is not output - // output content due to an ajax request if(IS_AJAX_REQUEST){ // use a switch/case as a controller $get_action = isset($_GET['action']) ? $_GET['action'] : ''; switch($get_action) { case 'list_content': echo $list_content; break; // add code for other actions here... } exit; // stop execution so that nothing else is output to the browser } in the markup on your page, where the account list content is now, you would replace it with a container with an id so that the javascript can set the content from the ajax request. you would also echo the $list_content here for non-ajax requests - <ul class="responsive_table"> <li class="table_row"> <div class="table_section"><?php echo $Account; ?></div> <div class="table_section"> </div> </li> <div id='list_content'> <?php echo $list_content; ?> </div> </ul> in the javascript, you would write a function, that when called, uses an ajax request to get the account list and display it in the correct place on the page - <script> function get_list() { $.ajax({ url: "accounts.php?action=list_content", cache: false }) .done(function(html) { $( "#list_content" ).html(html); }); } </script> you would then simply call this function inside your existing ajax post form success: handler.
  6. no, the number of entries in the array definition is not related to the bindValue() list of parameters. you must know, by reading the php.net documentation, what parameters the bindValue() method takes, in order to understand what the code is doing and why there are three parameters. to search more columns, yes, you only add them to the $search_fields array.
  7. if your code isn't using the database, those lines of code would have no affect on what your code does. however, if you are using a database, there are some inconsistencies between running an emulated prepared query and running a real prepared query (thanks php) that could be throwing an error, and depending on how you are handling any thrown errors, combined with the error_reporting level you have set in your code, could result in your code halting without showing any error information. don't set error_reporting to zero. it should ALWAYS be set to E_ALL. when debugging problems, you should display errors (set display_errors to ON), otherwise they should be logged (set display_errors to OFF and set log_errors to ON). also, don't use output buffering statements in your code unless you ARE buffering output. they hide messages from your code and php error messages.
  8. the php.net documentation has migration sections in the appendix that lists the major changes that have been made to the language. if your code is dependent on any of the Backward Incompatible Changes, from the starting php version you were using to the final php version you have now, you will need to rewrite that portion of your code. we cannot specifically help you since we don't know what exact method, among all the possibilities available in programming, your code is using. you would need to post enough of your code that reproduces each problem to get specific help.
  9. you would use an UPDATE query with a WHERE clause to control which rows get updated. the following is the UPDATE query syntax definition of the commonly used parts highlighted -
  10. you are missing a $stmt->fetch(); method call to retrieve the data. the PDO extension is much more consistent and straight-forward to use, particularity with prepared queries. if you can, switch from using the mysqli extension to the PDO extension.
  11. you don't even have any code to move the uploaded file in the NEW RECORD logic. are you looking at your code at all? you shouldn't be duplicating the code between the EDIT RECORD and and the NEW RECORD logic. the only thing that's different is the UPDATE query, when you have an id, or the INSERT query when you don't. you should have ONE instance of the logic, then a simple conditional if/else branch to form either the UPDATE or the INSERT query, then back to ONE instance of the logic to execute the query.
  12. this would be another good reason to ascend to a higher plane of programming existence and reuse proven, tested, general purpose code. so that each time you do the same thing, you don't have to beat on the keyboard typing out bespoke code and queries, then find and fix all the typo's and missing or wrong statements. reusing proven, tested, and general purpose code will let you concentrate on the program flow and the goal you are actually trying to accomplish, rather than on the tedious details of each step you take along the way.
  13. there's two reasons you are getting an error at the ->execute() method call - 1) emulated prepared queries are on by default (and not well documented, thanks php). meaning, you are not running real prepared queries. the ->execute() method is forming the complete sql query statement, with the bound data inserted into it, then calling the ->query() method internally to execute the query. when you make the database connection, you need to set emulated prepared queries to false. add this line after the connection - $conn->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); // run real prepared queries and you might as well do something else i stated and add this line - $conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC); // set default fetch mode 2) the error you are getting should contain information about an sql syntax error (type, the name of one of your columns, is a reserved keyword), though the error information at the execute() method is sometimes lacking, more than normal..once you set emulated prepared queries to false, you will be getting an explicate sql syntax error at the ->prepared() method call. you should avoid using reserved keywords as database, table, and column names, but if you must, you can add back-ticks around the $field name in the following line of code (in each place the query is being prepared, or in one place, if you make the general purpose prepared query method as suggested) - $and_terms[] = "`$field` = :$field"; by removing the name='submit' from the submit button in the form. for a get method form, there's no need for a name for the submit button. the form field data will either exist or it won't and your code just needs to check for the field data, not a submit button. you also need to remove the if(isset($_GET['submit'])){ and the matching } from the code. and remove the three lines of code that are right after the if(isset($_GET['submit'])){ statement.
  14. the OP's code is actually setting a default value of 1, if there is no page get parameter, validating the value as an integer (within php's integer range), and is limiting the value between 1 and the total number of pages. don't copy or use code unless you understand it. this bit of code is repetitive and unnecessarily bespoke/hard-coded, and isn't using the correct entity version of an & for links on a page. your code still has a number of unnecessary and problematic things in it, which i am betting you have been informed of most of them in previous threads - 1) use the correct input variables where you expect the data to be. use $_GET, not $_REQUEST. 2) i don't know what your clean() function code is, but i'm betting it isn't effective and is best left out. 3) the try/catch block will catch errors with the prepare/execute methods. this means that there was a sql syntax error or wrong bound parameters. this does not mean that the query ran, but didn't match anything. there's no need for a local try/catch block unless you are specifically handling a type of query error in your code, such as a duplicate key error from and INSERT/UPDATE query. 4) the global keyword only has meaning when used inside a function definition and even there it indicates bad coding. don't use global $var_name; 5) the code to build the WHERE term for the sql query statement should not be repeated. build the term in a variable, then use that variable each place it is needed. 6) the external data you are putting into the WHERE term needs to be handled using a prepared query with bound input parameters. 7) the $start and $end variables are not used in the posted code and should be removed. the sql query statements should be built in a php variable, this supports debugging (you can echo/log the statement, though the pdo statement object has a queryString property you can use) and it leads to writing general purpose code. 9) you need to set the default fetch mode in your connection code, so that you don't need to specify it every time you run a query. 10) the pdostatement object is already traversable. you don't need and shouldn't be applying the new IteratorIterator() to it. 11) for queries that will return a set of data, just fetch all the data using the fetchAll() method. you can then use count() on the data to find how many rows the query matched (the ->rowCount() method doesn't work with SELECT queries for all database types, so, using fetchAll()/count() will work regardless of which type of database you are using.) 12) to produce the pagination output, you need to test how many pages were calculated, not if the data retrieval query returned any rows (there's a condition that's mentioned in the code where you would need to produce the pagination links even if the data retrieval query didn't match any data) 13) your <span> tags are reusing the same id='...' value, which is invalid. if you are doing something unique with each span (which is doubtful), you would need to use unique id values. if you are not doing anything with the span, don't include it in the markup. the following example code shows how you might do this. this code adds the following features - 1) shows how to do a data driven design, where you define somewhere (an array or database table) a set of data that general purpose code operates on. this eliminates repeating block after block of same functioning code. this also has the benefit of helping to implement DRY (Don't Repeat Yourself) programming, since it eliminates the repetitive logic. 2) it implements the suggestion of leaving a particulate field out of the sql query statement when it is the 'ALL' choice or when the choice isn't present at all in the $_GET parameters. 3) shows how you would apply http_build_query() when building each link. // define the possible search fields - this is used to produce a data driven/dynamic design, where you don't write out block after block of code that only differs in the value it operates on $search_fields = array('title','name','description'); $and_terms = array(); // WHERE terms to be AND'ed $params = array(); // bound input parameters for a prepared query foreach($search_fields as $field) { if(isset($_GET[$field]) && $_GET[$field] != 'ALL') // only if the field is set and it's not 'ALL' { // add the search field to the WHERE terms $and_terms[] = "$field = :$field"; $params[] = array(":$field",$_GET[$field],PDO::PARAM_STR); } } $where_term = ''; if(!empty($and_terms)) { $where_term = "WHERE " . implode(' AND ', $and_terms); } // get the total matching rows $query = "SELECT COUNT(*) FROM table $where_term"; // note: the following logic should be in a general purpose prepared query method that you extend the PDO class with if(empty($params)) { // no bound inputs, just execute the query $stmt = $db->query($query); } else { // there are bound inputs, produce a prepared query, bind the inputs, and execute the query $stmt = $db->prepare($query); foreach($params as $param) { $stmt->bindValue($param[0],$param[1],$param[2]); } $stmt->execute(); } $total = $stmt->fetchColumn(); // calculate total number of pages $pages = ceil($total / $per_page); // limit the page number $page = min($pages, filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, array( 'options' => array( 'default' => 1, 'min_range' => 1, ), ))); // calculate starting row for LIMIT $offset = ($page - 1) * $per_page; // add limit values to the array of bound parameters $params[] = array(':per_page',$per_page, PDO::PARAM_INT); $params[] = array(':offset',$offset, PDO::PARAM_INT); // query for the data $query = "SELECT * FROM table $where_term ORDER BY id DESC LIMIT :per_page OFFSET :offset"; // note: the following logic should be in a general purpose prepared query method that you extend the PDO class with if(empty($params)) { // no bound inputs, just execute the query $stmt = $db->query($query); } else { // there are bound inputs, produce a prepared query, bind the inputs, and execute the query $stmt = $db->prepare($query); foreach($params as $param) { $stmt->bindValue($param[0],$param[1],$param[2]); } $stmt->execute(); } $result = $stmt->fetchAll(); if(!count($result)) { // query didn't return any row(s) - this doesn't mean there isn't any matching data, just that the query for the requested LIMIT range didn't return anything (there's a race condition, where if data gets deleted between the COUNT() query and the data retrieval query, queries for data near the end can return nothing) echo '<p>Nothing found.</p>'; } else { // query matched one or more row(s), display the data foreach ($result as $row) { echo $row['id']; } } // if there are any pages, display the pagination if($pages) { echo '<div id="pagination"> <div id="pagiCount">'; $q = $_GET; // get a copy of any existing $_GET parameters - do this once before the start of your pagination links $prevlink = ''; if($page > 1) // not on the first page { $q['page'] = 1; $qs = http_build_query($q,'','&'); $prevlink = "<a href='?$qs' title='First page'>First</a> "; $q['page'] = $page - 1; $qs = http_build_query($q,'','&'); $prevlink .= "<a href='?$qs' title='Previous page'><<</a>"; } $nextlink = ''; if($page < $pages) // not on the last page { $q['page'] = $page + 1; $qs = http_build_query($q,'','&'); $nextlink = "<a href='?$qs' title='Next page'>>></a> "; $q['page'] = $pages; $qs = http_build_query($q,'','&'); $nextlink .= "<a href='?$qs' title='Last page'>Last</a></span>"; } echo "<div id='paging'><p><small>$prevlink Page $page of $pages $nextlink </small></p></div>"; echo '</div></div>'; }
  15. you need to build the query string part of the url (the part after the ?), using http_build_query() and any existing $_GET parameters - $q = $_GET; // get a copy of any existing $_GET parameters - do this once before the start of your pagination links // when you build each link - first, last, previous, next do this - $q['page'] = // set the page value to the value you want for the link you are building from whereever the code is getting the value now $qs = http_build_query($q,'','&'); // build the query string part of the url echo "<a href='?$qs'>the label you want for the link you are building from whereever the code is getting the lable now</a>"; // output the link
  16. Assuming the $alev array and the php code/html markup you have posted is accurate, the problem is in the code that's producing the comma separated value you are storing into the database table, which as already stated, you should not be doing anyway.
  17. you are probably storing some white-space in with the data, which you should be storing not as a comma separated list, but as a separate row in the table for each check box that's checked. what exactly does the $row['hw_lev'] look like using var_dump($row['hw_lev']);
  18. A TEXT column has a maximum length of 65,535. php's mysql extension, i.e. the mysql_xxxxxx() functions, are obsolete and have been removed from the latest php version. the PDO extension/class (which is the best choice to use as a replacement) and the mysqli extension/class (turns out is not the best choice to use, thanks php) are the available replacements when using php with a msyql database. the problem you are currently having may be triggering an error, and having error handling in your code for the execution of the sql query would result in useful information being produced. you ALWAYS need to handle any errors that statements can produce. when debugging problems, you would want to display errors. on a live server, you would want to log errors. the switch between displaying and logging errors can be done automatically if you use php itself to handle the errors, since php's display_errors and log_errors settings will control what happens with the error messages. you would also need to set php's error_reporting to E_ALL, in both cases, so that all errors will be reported. the easiest way of handling errors is to use exceptions, which both the PDO and msyqli extensions/classes supports. if you are going to use the PDO class, you would set the error mode to exceptions, either in the connection statement or as a separate statement right after you make the connection. if you don't catch exceptions in your code, using a try/catch block, php will handle the uncaught exception and produce a fatal error that contains the actual error information. some other things to configure for the PDO connection - 1) set the character encoding of the connection in the connection statement. 2) set emulated prepared queries to false. 3) set the default fetch mode to assoc, since this will (should) be the most common usage in your code. next, you need to use a prepared query to supply input data to an sql query statement, by putting place-holder(s) into the sql statement where the data is to be used and binding the data to the place holder, either explicitly (which is the best general choice) or implicitly (doesn't work in some cases since all data is treated as a string), and supplying the actual data separately for the execution of the prepared sql statement. using a prepared query will ELIMINATE the need to escape string data, which my also be where the current problem is at. your current code is ineffective as escaping data (there would be a query error, from the error handling), since you are first escaping the data, then undoing that escaping with the stripslashes() statements. the problem is more likely because your longer text has sql special characters in it, such as a quote.
  19. you can get the last php error information using - error_get_last() (returns an array of information.). you can also get the last php error message in $php_errormsg, but this also requires that the track_errors setting be set to an on/true value, which you can set in your script.. the phpmailer class has an $ErrorInfo property that would give your script information about the last error that occurred.
  20. in addition to what has previously been listed, here are some specific things this code needs to do or do differently - 1) your search form should use method='get'. a get request should be used to cause your page to display whatever it is designed to display. a post request should only be used to alter (create, update, delete) data values on the server. the programtype, country, and sorthow values should all be carried in the url. this will eliminate the logic at the top of your code for the programtype. you should however ALWAYS validate that programtype (all input data) is a permitted value before using it. 2) don't use $_REQUEST. use the correct $_GET, $_POST, or $_COOKIE variables where you expect the data to be. for what this code is doing, all inputs should be in and use $_GET. 3) the php code that determines what to do on the page, validates inputs, and forms and run sql queries to retrieve data to display on the page should all be grouped together and come before the start of your html document. this will make it easier to write and test your code and to change the database extension that it uses. this code is commonly called the 'business logic.' the result from the business logic would be php variables. the html document would just use the data that's in the php variables. it would not contain any database extension statements. 4) the sorthow select/option menu should be 'sticky' and select the option that was previously picked. if the sorthow value is being used to find data, the way you are putting it into the sql statement won't do anything useful. you are putting a literal string value into the WHERE clause WHERE 'a string' ... if it is being used to produce an ORDER BY ... term, you would need to validate that it only contains a permitted value, you would also need either an ASC or DESC sort direction. then produce the ORDER BY ... part of the sql statement.
  21. since the purpose of this form is to INSERT new data, there's no point in having the check-box as part of the form data. if what you are trying to do is to have one form that works for inserting new data and updating or deleting existing data, you would use a completely different set of array names for the new/dynamically added fields (what you have now) and for the fields for existing data. the fields for existing data would use the id from the database row as the form field array index value. you would process these separately, inserting new data and either updating or deleting existing data. also, you have made the check-box 'required', so, you cannot submit the form, using current browsers, unless all of the boxes are checked. your javascript logic is the reverse of this. you must check the ones to remove and un-check the ones to keep, but then the form won't submit unless you check all the remaining boxes. if what you are trying to do is allow for a row(s) of the dynamically added form fields to be removed, there are two straight-forward ways - 1) only use the check-boxes to control what the 'Remove Attributes' button operates on. don't pre-check the check-boxes and don't make them 'required'. you would check any boxes you want to remove, then click the 'Remove Attributes' button. 2) add a 'Remove' button at the end of each dynamically added row, that just removes that row from the DOM.
  22. i was going through this terrible brute-force-built phpmotion code, trying to figure out what it thinks it is trying to do (i do know what it is trying to do, the Author wasn't so clear on this), and i found why it doesn't work for the validation errors. sorry for the commentary, but this code is so bad and repetitive, i got dizzy looking at it. there's 370 lines of bad code that it would take about 150 lines of good code to accomplish the same thing. the die_with_msg() function is trying to load the template file, but it is referencing the $user_theme variable to form the path. that variable doesn't exist inside the die_with_message() function. there would be a php error about the undefined variable, if php's error reporting was turned fully on and if you turned on the template error setting, you would get an error about not being able to load the template. these same messages either don't work at all for both the original location of the files and the copied location of the files OR you have some sort of symbolic path setup or you have previously duplicated some of the template files, so that the path produced by the missing $user_theme variable matches an actual path for the original location of the files, but not the copied location of the files. so, why are you actually moving these files? if you want to change/test the functionality of the form processing code, you would make a copy of the .php file, in a different location, but use the same template in it's original location. you could actually just make a copy of the .php file in the same location with the original file, but with a different name, but you would need to remove the action='upload_avatar.php' attribute. no action attribute or an empty value submits to the same url that the form is at.
  23. what do you get in your browser for the cases where it doesn't work? and if you get a blank page, what does the 'view source' of the blank page show? what folder(s) exactly did these two files start in? the .php code is looking in a relative folder path - "themes/$user_theme/templates/"; to find the template file. unless you moved (or did you copy it, leaving the original where it was) the template to a new location that has that exact same relative path structure, this shouldn't be able to even display the form. edit: the reason you are not getting anything in the application's log file is because it uses a relative path in the code and when you moved the .php file, it broke the path. there would be php errors about this if php's error reporting was turned full on.
  24. afaik, only database names and table names are ever case sensitive, on case sensitive operating systems. column names are not and referencing a column in a query using a letter case that doesn't match doesn't throw a query error (it would be a problem when trying to fetch the data since the actual column name letter case is what would be present in the data.) what does the result of running the query - SHOW CREATE TABLE `mylogin` produce? add the following to the list above - 19) you should be using php's password_hash() and password_verify() for hashing/testing the hashed password.
  25. first, here's a list of things to consider - 1) all the form processing code needs to be inside the conditional statement that controls the execution of the form processing logic - if(isset($_POST['some_field_name_here'])){ all form processing code goes here... } 2) you should test a (hidden) form field that uniquely identifies, either by field name or the value in a field, which form submitted to the form processing code. 3) if the current visitor is already logged in, you would skip/prevent displaying the registration form and processing the registration form data 4) avoid using the _once form of the require statement. your code should be organized, so that you know when and where it is requiring files and you don't need to use the _once form. php has also had a number of bugs with the include path and correctly resolving the actual file so that the _once part actually works one time. 5) i recommend NOT using UPPERCASE for most things in your code and database queries, i.e. your form field names and database column names should be lower case. only use uppercase when you are calling attention to something. a convention is to use uppercase for defined constants, so that they stand out from any code/text they are surrounded by, and for parts of sql query syntax, i.e. SELECT, FROM, WHERE, ... 6) all your header() redirects need an exit; statement after them to prevent the code from continuing to run. the header() doesn't stop program execution. 7) you should use an array to hold validation error messages. this will let your code detect and display more than one validation error at a time. if only some of the required form fields are empty, one of the other fields doesn't contain an expected value, and the username or email is already in use, you would want to display all these errors at once. the captcha check should make sure that there is a $_SESSION['code'] value and that it's not empty 9) you should validate each 'required' input to insure that it contains either an expected/permitted value or format. 10) you should produce a separate and unique validation error message for each possible validation problem, i.e. don't combine all the empty() checks into one message. 11) you should trim all input data before using it. this will eliminate leading/trailing white-space characters. if you want to allow leading/trailing white-space characters as part of a password, exclude that from what you trim or get an untrimmed copy of the original $_POST data when using the password value. 12) your current code requires the captcha to match before doing any other processing. after making the suggested changes, it should still do that and skip all other processing, even the database connection, if it doesn't match. 13) whenever possible, dynamically process sets of data. your form fields are a set of data. you should avoid writing out line after line of code, repeated for each different form field. because the $_POST data is an array, you can use php's array functions on it when performing the same operation on each field. to do this, you would make an array of the form field names, then loop over this defining array and access the corresponding post data. you can expand on this and dynamically produce the form by including things like the form field type, label for the field, ... in the defining array. 14) only escape data right before using it in an sql query statement (or even better, use a prepared query with bound input parameters.) 15) it's unfortunate that you picked the mysqli extension, rather than the PDO extension. the PDO extension is more constant, easier to use, and has fewer gotchas then the msyqli extension, especially if using prepared queries. 16) running a SELECT query to test if the username/email is already in use allows a race condition where concurrent visitors can try to INSERT the same values. the fix for this is to have those two column defined as UNIQUE indexes, then just run the INSERT query and use the duplicate key index error information that will occur to tell the visitor that the username or email is already in use. the duplicate key error will report the first key that's duplicated, so, if someone does happen to repeat both values, it will take two form submission to detect this OR you could run a SELECT query after the INSERT query to find which or both of the values are duplicated. 17) if you put the form processing code and the form on the same page, it will eliminate all the session variables/header() redirects. the only place you would need a header() redirect is after you have successfully (no errors) processed the form data. you will also be able to repopulate the form fields (except you shouldn't repopulate the password field) when there is a validation error, rather the require the visitor to keep typing in the same information over and over. 18) after successfully, no errors, processing the form data, you should do a header() redirect to the exact same url that the form submitted to. this will cause a get request for the page, which will prevent the brower from throwing an error or trying to resubmit the form data if you reload the page or browse back to the url of the page. as to why your db column name in your sql query statement doesn't match your table definition, i'm betting that your actual db column name isn't spelled exactly as you are using it in the sql query statement.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.