-
Posts
5,494 -
Joined
-
Days Won
184
Everything posted by mac_gyver
-
this is a common assignment, the U (Update) part of - Create, Read, Update, Delete (CRUD) data operations. what did you find when you searched on the web? wouldn't you create an edit link with the id (autoincrement primary index) as a get parameter on the end of the url? the code for your 'edit' form would use the id to query to get the single row of matching data to populate form fields with. then, when that form is submitted, you would detect if a post method form was submitted, trim the submitted data, validate the data, then use the data in an UPDATE query. some suggestions for the posted code - the code for any page should be laid out in this general order - 1) initialization, 2) post method form processing, 3) get method business logic - get/produce data needed to display the page, 4) html document. the existing SELECT query and php code to fetch that data should go in item #3 in the suggest code layout. this will make it easier to test, debug, and maintain your code. use 'require' for things your code must have. if you have more than 2-3 data fields, don't write out line after line of markup/code for every field. this is just an error prone waste of typing. instead, dynamically produce the repeated output, by using a data structure (array, database table) to hold the definition of the fields, then loop over this defining data structure to produce the markup, display the data, validate the input data, and build the UPDATE query. doing this will also let you leave out fields that are not being Updated in the query, such as the password field when a new one hasn't been entered. any field that must be unique, such as the email, must be defined as a unique index in the database table. you must then have exception error handling for any insert/update query to detect if a duplicate index error (number) has occurred for that field(s). if it has, setup a message for the user letting them know that a duplicate value was summitted, let them enter a different value, then submit the form again. the stored password should be hashed. see php's password_hash() and password_verify() functions. therefore, you cannot display the actual password in this code or in the edit form code. you can only, optionally, accept a new password from the edit form. almost every SELECT query that can march more than one row of data should have an ORDER BY ... term so that the rows in the result set are in a specified order. if a select query doesn't match any data, you should output a message stating so, instead of leaving a blank section in the output. don't copy variables to other variables for nothing. just use the original variable(s) that data is in. btw - you have repeated the $euro variable assignment. any dynamic value you output in a html context should have htmlentities() applied to them to help prevent cross site scripting. if you use the short php echo tag - <?= it saves typing in the html document, e.g. <?=$account_type?>
-
an OOP new mysqli() call always returns an object, regardless of if the connection worked or failed. @charlie321, you must always have error handling for database statements that can fail - connection, query, exec, prepare, and execute. adding the mysqli_report() statement i showed should (unknown if this works for such an old php version) enable exceptions for mysqli errors. if that doesn't work for your php version, you will need to add logic to test the value returned by mysqli_connect_error() (even the OOP mysqli::$connect_error property didn't initially work.) you also need to have post method form detecting and error handling for the file upload. if the size of the form data is greater than the post_max_size setting, both the $_POST and $_FILES arrays will be empty. once your has detected that there is $_FILES data, you must test the ['error'] element of the uploaded file information to make sure that the file was successfully uploaded before using the uploaded file data. because you are directly reading the temporary file data, you need to use is_uploaded_file() first, before opening and reading the file.
-
those errors are because the database connection is failing or you have some code that's closing the connection, and you are on a php version so old that's there's no default error handling for database statements that can fail. i also doubt that's the code where these error are coming from, because only the procedural mysqli_query() calls produce warnings. The OOP $connect->query() calls would result in fatal runtime errors (or perhaps the php version is so old that this hasn't been implemented yet.) to get error handling for all the mysqli database statements that can fail - connection, query, exec, prepare, and execute, add the following line of code before the point where you make the database connection (wonder if this has the desired effect on such an old version of php) - mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); also, after you make the database connection, you need to set the character set to match your database tables. add this code after the point where you make the database connection - $connect->set_charset('utf8mb4'); // repleace as needed if this is not the character set you are using
-
Not all quieries from form checkboxes are not being executed
mac_gyver replied to WeBBy421's topic in PHP Coding Help
while your current problem has been addressed above, you should not write out code for every possible data value. this is an error prone waste of your time typing. if you had 30 or a 100 of these, does it seem like it would be a good idea to sit at a computer creating 9, 30, or 100 sets of code that only differs in the value they use? you need to use a data driven design instead, where you have a data structure (array, database table) that defines the expected values. you would then loop over this defining data to produce the html makeup, validate the input data, and perform the processing, letting the computer do this repetitive work for you. because your database table already defines the choices, you should just query it to get the choices to use in the code. here are some other points for the posted code - you should actually be using ids for the submitted values, rather than the actual name. don't use or die() for error handling, ever. as of php8, the msyqli extension uses exceptions for errors and any existing conditional logic in your code testing for errors won't get executed upon an error since execution transfers elsewhere. so, remove any existing database statement error handling logic. the only time you should catch and handle database exceptions in your code are for duplicate or out of range user entered data. for this assignment, this is not user entered data, simply do nothing in your code for database error handling. you need to use a prepared query. don't put quotes around numbers. here's example code showing how to dynamically do this using a data driven design - // since i don't have your database, this example uses an array to define the choices // you would query the database table instead $choices = ['Juste','Chavez-Gris']; // examine the submitted data echo '<pre>'; print_r($_POST); echo '</pre>'; // post method form procesing if($_SERVER['REQUEST_METHOD'] == 'POST') { foreach($choices as $choice) { if(in_array($choice,$_POST['vote']??[])) { $sql = "UPDATE NewBoard SET votes=votes+1 WHERE lname = '$choice'"; mysqli_query($db,$sql); } } } // html document ?> <form method='post'> <?php foreach($choices as $choice) { // pre-check any existing choices $chk = in_array($choice,$_POST['vote']??[]) ? 'checked' : ''; ?> <label><input type="checkbox" name="vote[]" value="<?=$choice?>" <?=$chk?>> <?=$choice?></label><br> <?php } ?> <input type='submit'> </form> -
if the 'view details' link isn't working, there's something wrong with the 'product_url' value. what does the view source of the markup for that link show? you should be using a post method form for the add to cart operation, using a hidden field with the product id in it.
-
i/we don't understand abbreviations like tpu, pu, n, n 2, r, r 2 that would give meaning to the posted information. can you provide some context, in English, for the two examples you have posted? are these different categories of items? ultimately, your task boils down to database normalization. you can search on the web to find out what this means. to start with, you need an item table that holds the unique information about the items, one row per item. at a minimum, this table would have columns for - id (autoincrement primary index), and name. this will establish the item ids that will get used when storing data related to the items. if these various wookbooks are for different categories of items, you also need a category table that holds the unique information about the categories, one row per category. at a minimum, this table would have columns for - id (autoincrement primary index), and name. this will establish the category ids that will get used when storing data related to the categories. if this is the case, the above item table would also have a category_id column that will hold the corresponding category id for each item. since i/we don't know if pricing is per category, per item, or per list of items. i.e. what the extent and scope of the data is, i cannot offer any specific suggestions beyond the above.
-
nope. the t2 alias name is for the - JOIN user_pokemon t2 table, because that's what the code you posted is getting the original $user data elements from. we only see the information you supply and the answers cannot be any better than the posted information. the only query for the trade table in your original posted code is for the trade 'for' data.
-
the sql query error is because the LIMIT x,y values must be numeric. they are strings in your case because you are using emulated prepared queries and are suppling an array of values to the ->execute([...]) call. you need to use true prepared queries, which properly carries the datatype through to the database server when suppling the values to the ->execute([...]) call. when you make the database connection, you need to - set the character set to match your database tables (so that no character conversion occurs over the connection and in the case of emulated prepared queries, so that php can properly escape string data so that any sql special characters in a value cannot break the sql query syntax.) set the error mode to exceptions (this is the default setting now in php8+, but it doesn't hurt to set it.) set the emulated prepared query setting to false (you want to run true/real prepared queries.) set the default fetch mode to assoc (so that you don't need to specify the fetch mode in each fetch statement.)
-
here's example code i came up with for you to examine and learn from. it's tested logically, but obviously not with any query data - <?php // initialization $limit = 50; // pagination rows per page $errors = []; // array to hold user/validation errors // post method form processing - none in this example // get method business logic - get/produce data needed to display the page // inputs: // $_GET['id'] offer id - required // $_GET['page'] pagination requested page - optional, default to 1 // condition the offer id input $offerid = intval(trim($_GET['id']??0)); // validate the input if(!$offerid) { // if you see this error it is either due to a programming mistake or someone submitting their own data or no data, not your data $errors['offerid'] = 'Offer id is required'; } else { // note: if only a logged in user, with ownership or administrator-ship over the offer id values can view this page, you must have a user login system, and you would need to verify ownership of the submitted offer id value // get a count of the total number of offers matching the offer id input $sql = "SELECT COUNT(*) FROM trade_offers WHERE offer_on = ?"; $stmt = $pdo->prepare($sql); $stmt->execute([$offerid]); if(!$total_results = $stmt->fetchColumn()) { // no matching data // since the offer id link/form should have been built from actual offer data, // if you see this error it is either due to a programming mistake or someone submitting their own data, not your data $errors['offerid'] = 'There is no offer data to display'; } else { // there is offer data // produce pagination values $total_pages = ceil($total_results/$limit); // condition the page input $page = intval(trim($_GET['id']??1)); $start = ($page-1)*$limit; // get a page of offer data matching the offer id input // columns used in current output - t1.offer_from, t2.name, t2.type, t2.level, t2.exp, t2.move1-4, t3.id // t1.oid is used to index the data $sql = "SELECT t1.oid, t1.offer_from, t2.name, t2.type, t2.level, t2.exp, t2.move1, t2.move2, t2.move3, t2.move4, t3.id FROM trade_offers t1 JOIN user_pokemon t2 ON t1.pokemon_id = t2.id JOIN pokemon t3 ON t2.name = t3.name WHERE t1.offer_on = ? ORDER BY t1.oid DESC LIMIT ?,?"; // supply start and limit via prepared query place-holders $stmt = $pdo->prepare($sql); $stmt->execute([ $offerid,$start,$limit ]); // index/pivot the data using the oid as the main array index (PDO has a fetch mode to do this, but for clarity, this example uses explicit logic) $data = []; while($row = $stmt->fatch()) { $data[$row['oid']][] = $row; } // get the trade 'for' data corresponding to the offer id input // the name/type data in the trade table should be an id pointing to actual mame/type, not the actual name and type values $sql = "SELECT t1.pokemon_name, t1.pokemon_type, t2.id FROM trade t1 JOIN pokemon t2 ON t1.pokemon_name = t2.name WHERE t1.id=?"; $stmt = $pdo->prepare($sql); $stmt->execute([$offerid]); $trade_for = $stmt->fetch(); } } // html document ?> <div id="scroll" style="overflow-x: visible;"> <div id="content"> <div id="loading" style="height: 1133px; width: 800px; visibility: hidden;"><p style="text-align: center; margin-top: 150px;"><b>Loading</b><br><img src="./Pokémon Vortex - Trade Station_files/pokeball_loading.gif" width="50" height="50"></p></div> <div id="ajax"><h2 class="heading-maroon no-bot-border-rad margin-bottom-3">Trading Station</h2> <?php require_once 'sections/tradenav.php'; ?> <?php // display any errors if(!empty($errors)) { echo '<p>'.implode('<br>',$errors).'</p>'; } ?> <?php // display offer data if(!empty($data)) { // loop over the page of offer data matching the offer id input foreach($data as $oid=>$arr) { // start a new section here // start the table, start the thead, output the tr, end the thead, and start the tbody ?> <table class="table-striped width-100 text-center" cellpadding="10"> <thead> <tr><th></th> <th class="text-left width-200px">Pokémon</th> <th>Level</th> <th>Experience</th> <th>Moves</th> <th>Offer By:</th> <th>Offered On</th> </tr> </thead> <tbody> <?php // loop over the row(s) of data for this section foreach($arr as $row) { // output each row of data in the section // output each tr ?> <tr> <td class="pokeball-small"> <img src="https://ascensionrpg.net/img/pokemon/<?=$row['type']?>/<?=$row['id']?>.png"> </td> <td class="text-left"> <b> <a href="" onclick="pokedexTab('pid=48575929', 1); return false;"> <?=$row['name']?> <i class="ion-male male"></i></a> </b> </td> <td><?=$row['level']?></td> <td><?=$row['exp']?></td> <td><?=$row['move1']?><br> <?=$row['move2']?><br> <?=$row['move3']?><br> <?=$row['move4']?></td> <td><?=$row['offer_from']?></td> <td> <p> <a class="tooltip" href="" onclick="pokedexTab('pid=4627030', 1); return false;"> <img src="https://ascensionrpg.net/img/pokemon/<?=$trade_for['pokemon_type']?>/<?=$trade_for['id']?>.png"> <span class="text-center"><?=$trade_for['pokemon_name']?></span> </a> </p> <form method="post" onsubmit="get('/trade/remove-offer/4627030/1714855885/',''); disableSubmitButton(this); return false;"> <input type="submit" class="button-small button-maroon" value="Remove"> </form> <form method="post" onsubmit="get('/trade/remove-offer/4627030/1714855885/',''); disableSubmitButton(this); return false;"> <input type="submit" class="button-small button-maroon" value="Accept"> </form> </td> </tr> <?php } // end the section // end the tbody and end the table ?> </tbody> </table> <?php } }
-
while you are pondering that, here's a number of points for the posted code - don't use any _escape_string() function when you are using a prepared query. just use a prepared query. don't mix mysqli functions with the PDO extension. if you are converting old code to use the PDO extension, name the PDO connection variable $pdo so that anyone looking at the code or searching in it can determine which extension is being used at any point. the $_GET['id'] input is required. if it's not valid, setup and display an error message instead of running the code that's dependent on that input. don't use strip_tags, ever. don't select all your columns and matching rows of data to get a count of rows for pagination. use a SELECT COUNT(*) ... query instead. if there is no data matching the offer id input, display a message stating so, instead of running the rest of the code trying to produce output from the data. if you set the default fetch mode to assoc when you make the database connection, you won't need to specify it in any of the fetch statements. don't switch/mix fetch modes in your code. rowCount() is not guaranteed to work with a SELECT query. after you change to using a SELECT COUNT(*) ... query, you just fetch the count value from that query. don't use SELECT * in queries. list out the columns you are selecting. as posted in your previous thread, you need to use a single JOIN query to get related data all at once. the posted code can accomplish its work with three queries - 1) to get the count of matching rows for pagination, 2) to get the page of main data, and 3) to get the trade 'for' pokemon data (which you should only do once, not repeatedly inside of a loop.) the javascript onclick and onsubmit code has some hard-coded pid values in it. you will need to get these values from the query to use in the code. when using the short-print tags, you can leave out white-space and the ;, e.g. <?=$row['type']?> is all you need to echo a variable. you need to validate the resulting web pages at validator.w3.org
-
the data layout and the nested foreach loops assume you have done this - code to do that looks like this - // index/pivot the data using the oid value as the main array index (PDO has a fetch mode to do this, but for clarity, this example uses explicit logic) $data = []; while($row = $stmt->fatch()) { $data[$row['oid']][] = $row; }
-
the simplest way of doing this, without adding variables, conditional logic, and repeated code, to start a new section and close out the previous section, only when appropriate, is to index/pivot the data using oid value when you fetch it. this will result in an array of data that looks like this - Array ( [4] => Array ( [0] => Array ( [0] => row of data for oid 4 ) ) [5] => Array ( [0] => Array ( [0] => row of data for oid 5 ) ) [6] => Array ( [0] => Array ( [0] => row of data for oid 6 ) [1] => Array ( [0] => row of data for oid 6 ) [2] => Array ( [0] => row of data for oid 6 ) ) ) you can then loop over this data to produce the output using code like this - foreach($data as $oid=>$arr) { // start a new section here echo "start a section for oid: $oid<br>"; // loop over the row(s) of data for this section foreach($arr as $row) { // output each row of data in the section echo '---a row of data<br>'; } // end the section echo 'end this section<br>'; } which produces this output - start a section for oid: 4 ---a row of data end this section start a section for oid: 5 ---a row of data end this section start a section for oid: 6 ---a row of data ---a row of data ---a row of data end this section
-
this implies you are doing this based on the result of some other query. don't do that. use a single appropriate type of JOIN query to get the data that you want all at once. at the sql query statement level, the syntax is the same for both the mysqli and PDO extensions. i recommend that you build any sql query statement in a php variable, so that the sql query syntax is separated as much as possible from the php syntax - $sql = "SELECT count(*) FROM trade_offers WHERE offer_on = ? GROUP BY offer_on";
-
here's some coding pointers - don't copy variables to other variables for nothing. just use the original variable(s) that data is in. don't write out code for every possible value. use a data-driven design and let the computer operate on each value for you. here's what I came up with. in your initialization section - // define the month number and names (columns) $months = [1=>"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Decm"]; // note: the reason you needed to use decm is because dec is a reserved word. you can use dec if you surround it in back-tacks in any sql statement inside the while(){...} loop - // array to hold the data for the current row $data = []; // loop over the month number and month names foreach($months as $mo=>$month) { // produce the year-month value $ym = $row['Year'] .'-'. str_pad($mo,2,'0',STR_PAD_LEFT); // test if the year-month is between the start and end dates if($ym >= $row['start'] && $ym <= $row['end']) // use whatever you have named the start and end date columns { // put the value into the data array // use zero for any empty value $data[] = $row[$month] == '' ? 0 : $row[$month]; } } // at this point, $data contains the entries to use for the current row of fetched data // examine the result echo '<pre>'; print_r($data); echo '</pre>'; // calculate the average $TotalMark = round((array_sum($data)) / count($data), 2); // examine the result echo $TotalMark; note: you should use a value like 9999-12 for the end date for a person who is still employed
-
since your data isn't normalized, and is stored in month name columns in a single row, you will need to produce a year-month value, e.g. 2023-04, ... for each piece of data so that you can compare if it is BETWEEN the start and end dates OR you could normalize the data, and store each value in its own row in a table. the normalized data table would have columns for - id (autoincrement primary index), Emp_No, date, and amount. i also recommend that you store the dates using a DATE datatype and use 01 as the day part - year-month-01, e.g. 2023-04-10, 2024-06-01, ...
-
that's not what @Barand and I are trying to get you to understand. for the example he asked about - you need to know which if any of the empty/zero - sep, oct, nov, and dec values should be included in the sum/count to produce the average for the year in question. if the end date for that user was 2023-08, you don't included any of those empty values in the average calculation. if the end date is a value greater than 2023-08 or is an empty/null/maximum-value, you would treat some or all of these empty values as zeros and include them in the average calculation for the year in question.
-
i hope that isn't real data with actual password hashes? you need an end date, so that you can only include data that's between the start date and the end date.
-
Experiencing problems with CODE tags
mac_gyver replied to Yesideez's topic in PHPFreaks.com Website Feedback
the correct way of including code in the forum is to use the menu's <> button. -
Connection problems and no error messages output
mac_gyver replied to Yesideez's topic in PHP Coding Help
this is a parse/syntax error. to get php to report and display parse/syntax errors, you must have the php error related settings in the php.ini on your system, so that they are in effect before your php script is parsed, tokenized, and executed. error_reporting should ALWAYS be set to E_ALL. you cannot successfully set display_startup_errors in your code because php has already started by the time your code is running. during development, yes, you should have display_errors set to ON (or 1, e.g. a true value.) when running code on a live/public server, you should have display_errors set to OFF (or 0, e.g. a false value) and log_errors should be set to ON. the only database exceptions you should catch and handle in your code are for user recoverable errors, such as when inserting/updating duplicate or out of range user submitted data values. in these cases, the catch logic should test the error number and setup a message for the user letting them know what was wrong with the data that they submitted. for all other error numbers, just rethrow the exception and let php handle it. for all other query types and all other database statements that can fail, do nothing in your code and let php handle any database exception. when you let php catch and handle the database exception, php will 'automatically' display or log (using the php error related settings) the actual error information for you via an uncaught exception error. -
the limitation is probably in the get or set session methods or in the code displaying or processing the cart. this code is overly complicated. the only data that should be stored in the cart is the quantity and the item id (itemCode) should be used as the cart's array index. once you index the data using the id, you can directly find, test, or reference the data. no looping required. the following is the only code needed to add an item to the cart once you do this - // add to cart code if(!isset($cartItems[$_POST['ItemCode']])) { // if an item isn't in the cart, add it with zero quantity $cartItems[$_POST['ItemCode']] = 0; } // add the submitted quaitity to the cart $cartItems[$_POST['ItemCode']] += $_POST["ItemQty"];
-
i also recommend the much simpler and more modern PDO extension. you can directly fetch data from a prepared query, the same as how you would fetch it for a non-prepared query. if you are going to use the mysqli extension, forget about mysqli_int/mysqli_stmt_prepare. just use mysqli_prepare(). also, forget about the num_rows property. just fetch the data and test if there was any fetched data. if you are querying to find a row of data matching an (active) user, you would not include the password comparison in the WHERE ... term. also, you should be using php's password_hash() and password_verify() for password hashing. php finally realized the it should use exceptions for errors for things like database statement errors. as of php8, the mysqli (and PDO) connection, query, exec, prepare, and execute calls throw exceptions for errors. this means that any conditional error handling logic you have for these statements can be removed since they won't ever get executed upon an error, simplifying the code. there's also generally no need to close prepared query handles, free up result sets, or close database connections in your code, since php destroys all resources when your script ends, simplifying the code. pdo version - $sql="SELECT * FROM users WHERE username=? AND active=1"; $stmt = $pdo->prepare($sql); $stmt->execute([ $uname ]); if($user_data = $stmt->fetch()) { // a row was found // you can reference elements in $user_data, such as $user_data['id'], $user_data['added'], ... } else { // no row was found }
-
you would explode the search term on the space characters, then dynamically build an expression for each word, that get ORed together to build the WHERE ... term. you need to use a prepared query, so that nothing in a value can break the sql query syntax, which is how sql injection is accomplished.
-
forget the word sanitize when dealing with data. also forget about using stripslashes(). when it was needed, it was conditionally applied. the need to do this was removed from php long ago. other than trimming user submitted data, mainly so that you can detect if a value is all white-space characters, you should NOT modify data. you should validate the data to make sure that it meets the business needs of your application. is a required value not empty. is a value that must have a specific format, character range, length, or magnitude valid? if it's valid, use it. if it isn't valid, let the user know what was wrong with it, let them fix it, and resubmit it. security is accomplished by using the data correctly in whatever context it is being used in, e.g. sql, html, mail header, ... in a html context (web page, email body), apply htmlentities/htmlspecialchars to a value right before outputting it, to help prevent cross site scripting.
-
do you have php's error_reporting set to E_ALL and display_errors set to ON, preferably in the php.ini on your development system, so that php will help you by reporting and displaying all the errors it detects? are you using php8+, where exceptions are the default setting for database statement errors, or if using < php8, have you enabled exceptions for errors for the database extension you are using? when your code/data doesn't work, you need to find at what point they are doing what you expect and at what point they are not. the problem lies between those two points. if all you have done is run your code and notice that it doesn't insert the expected data, you haven't narrowed down the problem to a single line of code. you need to use debugging techniques, such as using var_dump() on data, to both determine which exaction path your code is taking and what data values it is using, to find out exactly where your code/data stops doing what you expect. well written code, with sufficient error handling and validation logic, should either work or it should tell you (display/log) why it doesn't work. every data validation error should get handled. your if (Token::check(Input::get('token'))) validation doesn't do anything if the token check is a false value, indicating either a programming mistake or someone/something hasn't visited/requested the form to generate a token. you need to add an else conditional branch to display (during development) or log (when on a live server) relevant information when this occurs. finally, you have some problems in the posted form/form processing - your user ->create() method is using a surname field, that doesn't exist in the form your form has a status field, that isn't being used if you want the user to be required to make a specific choice for the status field, the first <option ...> needs to be a prompt to make a choice, with an empty value attribute the email field is not being validated both the username and email fields must be defined as unique indexes in the database table. you must then have exception error handling for the insert query that tests for a duplicate index error (number), determines which or both of the submitted values where duplicates, and sets up user error(s) for the duplicate values. the foreach() loop displaying the validation errors, is concatenating each error onto the existing $response. when there is more than one error, the $response will get echoed multiple times, with a growing number of errors in it. i recommend that you just implode() the array of errors using a '<br>' tag and output the result. the form is submitting to insert/user.php. that doesn't correspond to the filename of the posted code.
-
when using named prepared query place-holders, the name must match between what you use in the sql query and the binding. in your code, they don't. e.g. :LogID is not the same as :LOGIN_ID. ... i recommend that you use simple positional ? place-holders. there's less to type and keep track of. regardless of the place-holder type, you can simply supply an array of the input values to the ->execute([...]) call, saving more typing. you should not manage the id value yourself in code. this is not concurrent safe. instead, use an autoincrement primary index. the database engine will perform the necessary table locking to insure that concurrent queries will generate unique values. your database must enforce uniqueness, it is the last step in the process. the username column must be defined as a unique index. you would then attempt to insert a row of data, and test in the exception handling catch block for that query if an duplicate index error (number) occurred. if it did, setup a message for the user letting them know that the username is already in use. for all other error numbers, rethrow the exception and let php handle it. there's also nothing to fetch from an insert query. why are you doing that?