Jump to content

mac_gyver

Staff Alumni
  • Content Count

    4,236
  • Joined

  • Last visited

  • Days Won

    106

Everything posted by mac_gyver

  1. mac_gyver

    Submit large form created with select statement

    you only need one form field per item. use a meaningful name for the field, such as qty, and use the item id as the field's array index value - name='qty[item id goes here]'. in the form processing code, use a foreach() loop. this will give you the item id and the submitted quantity for the id. to remove empty items use array_filter() with no call back function (empty strings and zeros are false and will be removed.) lastly, you need to insert a separate row in your table for each item and you need to use a prepared query, with place-holders in the sql query statement for each value, then supply the values when you execute the query. you would prepare the query once, before starting to loop over the data, then only get each set of values and execute the query inside of the loop.
  2. mac_gyver

    display data in two columns bootstrap

    before the start of your html document, query for and retrieve the data you want in the order that you want it, storing the two rows of data in an appropriately named php array variable. loop over the data at the point in your html document where you want to display the content and output the dynamic parts using php code.
  3. mac_gyver

    Help with checking 'balance' after 'wallet'

    you have been given working logic (here and phpbuilder, which i just verified that both work) to test the amount, wallet, and wallet2/balance/earnings (you keep changing what it is called) and to calculate new wallet and wallet2/balance/earnings amounts, yet the code you continue to 'try' is using neither method. are you even reading the replies you are getting? next, in the code i reviewed and added comments to here, there's no logic to get the starting wallet2/balance/earnings value. wouldn't that be a necessary step to get the code to work? btw - your existing code has an UPDATE query at the correct point within the transaction/rollback logic. you would want to use the new wallet and wallet2/balance/earnings amounts in that existing single query, per the comment i added at that point, rather than to start adding more queries before the start of where the transaction/rollback logic starts.
  4. mac_gyver

    Strange query behavior

    your code is probably executing the connection code again, which is recreating the table. it's generally not a good idea to have table deletion/creation queries being unconditionally executed.
  5. mac_gyver

    Help with checking 'balance' after 'wallet'

    no. the u_paid_videos table holds the information about the items(videos) in the order, but it contains redundant data. it has nothing to do with the accounts table i mentioned. everything i stated has to do with database normalization (you can research what that means) and is about properly organizing the data, so that you are only storing the data you need and are not repeating values in multiple places. you are keeping track of two different type of things, 1) information about items/videos that are being purchased (as already stated needs an orders and an order_items table), and 2) user's money/credits. the orders table should have at a minimum, columns for - an id (auto-increment, produces an order_id), user_id (who placed the order), date_time (when the order was placed), and a status column (indicates what state the order is in.) i'm not sure what the session key is, but if it needs to be stored per order it would go in the orders table. the order_items table should have at a minimum, columns for - an id (auto-increment), order_id (what order the item is part of), item_id (the id of the item/video), quantity (this code is just a cart script and in general should support any quantity of an item), purchase_price (the price at the time of purchase), and a status column (indicates the status for each item in the order.) the account table should have at a minimum, columns for - an id (auto-increment), user_id (who the account belongs to), amount (the + or -- amount), transaction_type (wallet, balance), and date_time (when the transaction was made.)
  6. mac_gyver

    PHP Login Logs in but only correct on a refresh

    if you fix what's causing the first error message, the second one will go away. why do you have two session_start() statements?
  7. mac_gyver

    Help with checking 'balance' after 'wallet'

    this code contains no useful comments, making it difficult to determine what it is trying to do, which makes it impossible to make changes to it. the original author, and you as you are making changes to it, should put useful comments in the code that describe what it is doing and why. this is what i think it is trying to do - <?php if(true) // whatever the actual conditional logic is { // get cost video // get the default video price, to use if there is no per video play price $db->where('name', 'video_play_price'); $db_cost = $db->getOne('config'); $video_cost = (float)$db_cost->value; // the number of submitted videos - used to determine if all records were inserted $count_video = count($id_array); $user_id = $user->id; // copy the user id for some reason // values shouldn't have thousands separators stored with them. formatting a number should only be done when it is displayed $wallet = (float)str_replace(',', '', $user->wallet); // add up the video prices $amout = 0; foreach ($id_array as $id) { // assuming this pt_secure function is actual secure, any $id in the following code should use $video_id instead $video_id = (int)PT_Secure($id); // get video data $video = $db->where('id', $id)->getOne(T_VIDEOS); // add the video play price if any, or the default price $amout += $video->video_play_price?$video->video_play_price:$video_cost; } // determine if the user has enough credits // it is here that you would include the balance amount if ($wallet >= $amout) { // you would calculate new wallet and balance amounts $wallet = (string)($wallet - $amout); // insert/update all the following queries as a group $db->startTransaction(); $inserted_records = 0; foreach ($id_array as $id) { // again, all the rest of the code should use $video_id, not $id $video_id = (int)PT_Secure($id); // get video data $video = $db->where('id', $id)->getOne(T_VIDEOS); // use the video play price if any, or the default price $video_cost_new = $video->video_play_price?$video->video_play_price:$video_cost; // add data to paid table $insert_buy = $db->insert('u_paid_videos', [ 'id_user' => $user_id, 'id_video' => $video_id, 'session_key' => $_SESSION['session_key'], 'video_play_price' => (string)$video_cost, // the cost at the time of purchase // this is the default video cost not the $video_cost_new 'video_title' => $video->title, // storing the title is redundant since you can retrieve it from the source video information 'user_id_uploaded' => $video->user_id, // the user who uploaded the video. this is also redundant // this should include the datetime of the purchase - actually there should be a purchase/order table and a purchase/order_items table ]); // count successful inserted records if ($insert_buy) { $inserted_records++; } //update the 'balance' of the user who uploaded the video // get the user's record $userwallet = $db->where('id', $video->user_id)->getOne(T_USERS); // credit the user 50% of the video cost $uploader_amount = $video_cost_new *0.50; // add to the balance $videouserwallet = $userwallet->balance+$uploader_amount; // update the record $db->where('id', $video->user_id); $update_balance = $db->update(T_USERS, [ 'balance' => number_format($videouserwallet, 1, '.', ''), // this is formatting with one decimal point only ]); } // update the current user's wallet (and balance) amounts $db->where('id', $user_id); $update_wallet = $db->update(T_USERS, [ 'wallet' => $wallet, // you would include the new 'balance' too ]); // if all the video records were inserted and the current user's wallet was updated, commit the changes if (($inserted_records == $count_video) && $update_wallet) { $db->commit(); echo json_encode([ 'status' => 200 ]); exit(); } else { $db->rollback(); echo json_encode([ 'status' => 400, 'error' => 'Buy process error' ]); exit(); } } else { echo json_encode([ 'status' => 400, 'error_num' => 1, 'error' => 'Not enough money' ]); exit(); } } else { echo json_encode([ 'status' => 400, 'error' => 'Bad Request, Invalid or missing parameter' ]); exit(); } if i have incorrectly deduced what any of these things are doing, make corrections to the comments before proceeding. if this code had useful comments, so that the meaning of the line of code producing the $video_cost_new value would be in recent memory, there probably wouldn't be a mistake in the pricing value used in the insert query. the following line should use $video_cost_new - 'video_play_price' => (string)$video_cost, // the cost at the time of purchase // this is the default video cost not the $video_cost_new next, the data design has one serious flaw and one that should be corrected - 1) the wallet and balance amounts should NOT be just columns in the user's row that get updated to change the value. by having just a value, you don't have any 'audit trail' should a programming mistake, duplicate form submission, or nefarious access alter a value incorrectly. you should instead have a separate 'account' table that gets a new row inserted for each transaction that affects the amount. this table would have all the who, what, when, where, and why information about each transaction ('wallet' or 'balance' would just be transaction types.) to get the total at any point in time for a user, you would just SUM() the +/- amounts for any particular user id. to get the either or both of the current 'wallet' or 'balance' amounts, you would group by the transaction type for any particular user id. 2) you should actually have two tables to hold the video purchase information. the first table should hold the unique/one-time information about the purchase. this will assign a purchase order id. the second table would hold the unique/one-time information about the items that were purchased, related back to the first table through the order_id. lastly, i put comments in the code where it would need to be modified to do what you are asking. two are near the if ($wallet >= $amout) { conditional test (LOL amount is misspelled in the code.) the last one is in the update query (which should instead be one or two insert queries for the account table) for the current user's wallet (and balance) amounts.
  8. mac_gyver

    PHP Create Not Inserting Into Db And Check If Exists

    here's code (partially tested only) that uses the suggestions above and from the previous thread - <?php //mySQL database config require "config.php"; // Define all variables and initialize them as 'empty' $errors = []; // an array to hold error messages and serves as an error flag $post = []; // an array to hold the trimmed input data // Process data when the form is submitted. if($_SERVER["REQUEST_METHOD"] == "POST") { // assuming the $_POST field names in the original code are accurate, the inputs to this code are - // name, username, password, and password2 $post = array_map('trim',$_POST); // get a trimmed copy of the $_POST data (if any of the form fields are arrays, you need a recursive trim call-back function in this line instead of php's trim() function) //Name check if(empty($post["name"])) { $errors['name'] = "Please enter a name."; } // Validate 'Username' if(empty($post["username"])) { $errors['username'] = "Please enter a Username."; } // Validate Password if(empty($post["password"])) { $errors['password'] = "Please enter a password."; } else { if(strlen($post["password"]) < 6) { $errors['password'] = "Password must have at least 6 characters."; } } // Validate Confirm Password. if(empty($post["password2"])) { $errors['password2'] = "Please confirm your password"; } // check password and confirm password if(empty($errors['password']) && empty($errors['password2']) && $post['password'] != $post['password2']) { $errors['password_confirm'] = "Password and confirmed password do not match."; } // if no validation errors, use the submitted data if(empty($errors)) { $sql = "INSERT INTO users (name, username, password) VALUES (:name, :username, :password)"; $stmt = $pdoConn->prepare($sql); // use a 'local' try/catch to handle errors from this query try { $stmt->execute([ ":name"=>$post['name'], ":username"=>$post['username'], ":password"=>password_hash($post['password'], PASSWORD_DEFAULT) ]); } catch (PDOException $e) { $er=$e->errorInfo(); // get the error information if($er[1] == 1062){ // duplicate key error number $errors['username'] = "The username is already in use."; } else { throw $e; // re-throw the pdoexception if the error is not handled by this logic } } // if no errors, the insert was successful if(empty($errors)) { header("Location: ../index.php"); exit; } } }
  9. mac_gyver

    Php Update Page No Errors Prob Something Small

    the posted form processing code contains a php syntax error, as indicated by the color highlighting stopping. there's no way it is running. only one one of the form field names matches between the php code and the form, so even if the form processing code runs, it is not operating on the correct field names. at a minimum, you need to set php's error_reporting to E_ALL and set it in the php.ini on your system. you can put the setting into your code but since you code never runs when there is a php syntax error, you won't see the error unless the setting is set in the php.ini.
  10. mac_gyver

    PHP Create Not Inserting Into Db And Check If Exists

    to do what you are asking, just make the username column a unique index, forget about the SELECT query, just run the INSERT query, and test if there was a duplicate key error. if there is, it means that the username already exists. this alone will eliminate a 1/4th of the code. in addition to the suggestions already given in a previous thread, this code is filled with unnecessary and repetitive logic, mistyped and non-existent variable names (which is why some of the code isn't running.) you even have a backward logic test that would only run the INSERT query if all the variables are empty. you need to use the simplest and most general purpose code that accomplishes a task. what you are doing now is creating a wall of code which is hiding the mistakes. you have a 'cannot see the forest for the trees' problem. some more suggestions - 1) forget about making discrete variables for every form field and every error. use arrays instead. one for the trimmed input data and one for the errors. 2) trim all the input values at one time. if i/someone has time they will post an example that takes only one line of code. 3) when you validate the inputs, store any error messages in an array. this array is also an error flag. if the array is empty, there are no validation errors. if the array is not empty, there are errors. after all the validation tests, if the array is empty, you can use the submitted data. in your html document, if the array is not empty, display the errors by displaying the contents of the error array. 4) stop creating variables for nothing. in this thread and your other current thread, you have variables that don't exist and typo mistakes in variable names. by using an array to hold a trimmed copy of the input data, then using just this array in the rest of the code, hopefully it will cut down on these type of mistakes.
  11. mac_gyver

    What PHP should i use? PDO

    using the php PDO extension, using prepared queries when supplying external/unknown data to the sql query statement, using implicate binding by supplying an array of the input data to the execute() method call, and using exceptions to handle database statement errors will result in the least amount of code and the simplest sql query syntax. the issue with the ...escape_string() functions is, if the character set that php is using for them isn't the same as the character set of your database table(s), sql special characters in the data can still break the sql query syntax, which is how sql injection is accomplished. by using a true prepared query (PDO has a mode that emulates prepared queries, which should be turned off in most cases), you are guaranteed that nothing in the data will ever been treated as sql syntax. by using a prepared query, you are also simplifying the code since any ...escape_string() functions you may have can be removed. as to the code you have posted above - 1) any trimming of input data would occur before you validate the data and you would never get to the point of preparing/executing the query if the input data is not valid. 2) you should set the default fetch mode to assoc when you make the database connection so that you don't have to specify it in every fetch statement. 3) the rowCount() method is not universally available for SELECT queries for all database types and should be avoided. 4) if you just fetch the data into an appropriately named php variable, using the fetch() method for a single row, or the fetchAll() method for multiple rows, you can test the variable to determine if any row(s) were matched and if you need to get a count of the number of multiple rows, you can use php's count() function. 5) copying the fetched data into discrete variables is a waste of typing time and memory. the original variable you fetched the data into is perfectly fine to use in the rest of the code. 6) using a ? place-holder is shorter/simpler/less typing. 7) you should list out the columns you are selecting. this helps to document what you are doing and causes only the data you want to be retrieved. using these suggestions, your two examples simply become - $sql = "SELECT id, name, language, date FROM users WHERE id = ?"; $stmt = $pdoConnect->prepare($sql); $stmt->execute([$param_id]); $user_row = $stmt->fetch(); // if $user_row is a boolean true, the query matched a row. if it is a boolean false, the query did not match a row. // access the id, name, language, and date elements in $user_row. $sql = "SELECT id, name, language, date FROM users"; $stmt = $pdoConnect->query($sql); $user_rows = $stmt->fetchAll(); // if $user_rows is a boolean true, the query matched at least one row. if it is a boolean false, the query did not match any row(s). // you can use a foreach(){} loop to loop over $user_rows to reference each row of data
  12. mac_gyver

    [Bao Kim]Saving data from all text boxes in one click

    use an array for the form field name, with the id as the array index - <input type='text' name='utilTextbox[1]'> <input type='text' name='utilTextbox[2]'> ... when the form is submitted, you can loop over the array of data to get the id and the value - foreach($_POST['utilTextbox'] as $id=>$value) { echo "id: $id, value: $value<br>"; }
  13. mac_gyver

    Conversion of text data from $variables issue

    any database, api or web site url/host information and any username/password/key values should be implemented in your code using variables or defined constants that are contained in a separate .php file and required by your main code, so that you don't need to be editing them out of the main code in order to post it for getting help.
  14. mac_gyver

    Conversion of text data from $variables issue

    the first method should work. the second method won't work because php variables contained within a single-quoted string are not parsed/replaced with the variable's contents. for the first method, there could be a number of reasons that it doesn't appear to work - 1) the variables don't exist at the point where you are referencing them. 2) the variables don't actually contain what you think or did but have been cleared by some of your code. 3) the method or place you are using to view the result or otherwise determine that this doesn't work, is at fault. 4) there could be a variable scope problem. edit: 5) you could be seeing the result from double page requests (different browsers/client programs do this for various reasons), where the first request does work, but the second doesn't actually find/retrieve the data. it would take seeing all the relevant code, from the point where you are querying for and retrieving the data through to where you are viewing the incorrect result. do you have php's error_reporting set to E_ALL and display_errors set to ON so that php would help you by reporting and displaying all the errors it detects.
  15. mac_gyver

    How to short hand this

    $values and $periods are already arrays. do the same for $ItemsAnnual and make it an array and populate its values using a loop.
  16. mac_gyver

    upgrade to PHP 5.5, Site Doesn't work

    it would help to know what the old php version was. just an update to 5.5 (which should have or soon will be an update to 7+) doesn't break the mysql_ functions. it's more likely that the code is dependent on register_globals in order to function. if so, it will take rewriting all the code to use the actual php super global variables where the external $_GET, $_POST, $_FILES, $_COOKIE, and some $_SERVER variables are at. you would also want to update the code to use one of the current database extensions, and since query security also went away in php 5.4, in order to keep from having to add a bunch of code, it is better to switch to use prepared queries, with the php PDO extension, and to use exceptions to handle database statement errors. doing this will result in the simplest php code and simplest sql query syntax, which will reduce the amount of things you have to update, i.e. you can just eliminate a bunch of stuff, rather than to spend time on updating it.
  17. mac_gyver

    5K - Race

    when looping to produce that html table, you would actually loop from 1 to 14 and test if the corresponding $_POST['runner'] element is set, since there won't initially be any $_POST data.
  18. mac_gyver

    5K - Race

    some suggestions - 1) don't create a bunch of variables without a good reason. the original $_POST variable(s) the data is in are perfectly fine to use in the rest of the code. 2) use arrays for sets of data. the form field name should be an array, i.e. name='runner[x]' with the array index (x) value being 1-14. this will let you loop over the submitted data using a simple foreach(){} loop so that you can dynamically process the data. this will eliminate the temptation to write out 14 lines of code that are doing nothing useful, but to waste your time typing (unless this is part of a keyboard/typing class?) 3) leading zero's on numbers in php cause them to be treated as octal. either treat all the values as integers and zero fill them when displaying them, or treat all the values as strings. 4) the three separate arrays of registration values should be instead one array (use the same base array name for all three), with an index value that indicates the division (the index can either just be a number or a string, but needs to be in the order that you want to produce the output in.) 5) to produce the final output, loop over the array of submitted $_POST['runner'] data. this will give you the runner number for positions 1-14. at the point that you have the current runner number for a position, loop over the registration main array and use in_array() to find if the current runner number is in each successive registration sub-array. if the current runner number is not in the current registration sub-array, output a &nbsp; in the current html table cell. if the current runner number is in the current registration sub-array, output the runner number in the current html table cell and increment a counter for the current registration sub-array index (use an array for the counter, with the index being the same index value you used in the registration main array.) to produce the last count row in the html table, just loop over the registration main array one more time and access the corresponding entry in the counter array. 6) you would want to make the form fields 'sticky' and set the value to any corresponding submitted $_POST['runner'] value, since you aren't actually storing the results in a database to make them persistent. 7) you would dynamically produce the form fields, rather than to have them statically written out.
  19. mac_gyver

    What is wrong with this line?

    1.b) additionally, one = is an assignment operator. two == is a comparison operator.
  20. mac_gyver

    What is wrong with this line?

    in order to put an array variable inside a string, it needs to be enclosed by {} however, there are a few things wrong with what that line of code is trying to do - 1) the mysqli_query() statement doesn't return data, it returns a result object, so, a variable holding the submitted password will never be equal to the value returned in that line. you would need to fetch the data first. 2) you should NOT store plain-text passwords. you need to use php's password_hash() and password_verify(). you would need to fetch the stored password hash and use password_verify() to test if the submitted password matches the hash. 3) you should NOT put external/unknown data directly into an sql query statement (and for those cases where it is safe to do so, string data must be enclosed by single-quotes.) you instead need to use a prepared query, with a ? place-holder in the sql query statement for each data value, then supply the data when the query gets executed. unfortunately, the php mysqli extension is overly complicated and inconsistent when dealing with prepared queries and you need to switch to the much simpler php PDO extension. doing this will actually simplify the sql query statement since the place-holder being put into the sql query statement eliminates the php variable, any {} around the variable, any single-quotes around the variable, and any concatenation dots.
  21. mac_gyver

    PHP Calendar with data from MYSQL

    someone already posted the steps you would perform -
  22. mac_gyver

    PHP Calendar with data from MYSQL

    before the start of the display code, you would query for and retrieve any event data matching the year and month being displayed. when you retrieve the data, you would store it as a sub-array of rows (there can be multiple events on any date) in a main array variable with the date (YYYY-MM-DD) value as the the main array's index. in your calendar display code, you would build the date (YYYY-MM-DD) value for the current day being displayed and test if the main array of retrieved data has an index for that date (you can just use isset().) if so, you would loop over the sub-array of data to reference each row of event information for that date.
  23. mac_gyver

    how to select two tables in update query

    as to displaying/logging the database statement errors. use exceptions to handle all database statement errors (connection, query, prepare, and execute) and in most cases let php catch the exception where it will use its error_reporting, display_errors, and log errors_settings to control what happens with the actual error information. the exception to this rule is if your application needs to detect and handle duplicate values for an insert/update query. your code would catch the exception in this case, detect if the error was for a duplicate index, set up and output an error message to the user telling them what is wrong with the data they submitted, or if error is not for a duplicate index, re-throw the exception and let php handle it. when learning, developing, and debugging code/queries, you would display all errors, which now includes the database statement errors, and when on a live/public server, you would log all errors, just by changing the php display_errors and log_errors settings. this will allow you to remove the existing error handling logic in your code, thereby simplifying it. to enable exceptions for the php mysqli extension, add the following line of code before the point where you are making the database connection - mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); lastly, since you need to change to use prepared queries when supplying external/unknown values to the sql query statement, you need to switch to the much simpler php PDO extension for all the database statements. the amount of code you have to write to accomplish a prepared query using the mysqli extension is an error prone waste of time (and the code needed to write a mysqli general purpose prepared query function/method is complicated and slow.)
  24. mac_gyver

    how to select two tables in update query

    you are going about this in the hardest way possible. even the naming of your tables and columns is not helping. your address table appears to be a rental unit table. it should be named that - rental_units. the id column in this table defines the unit id, the other column in that table is apparently the unit name. it should be named so - name. i'm assuming it is a varchar column because rental unit names can include alphabetic characters, A, B, C...? the amount table is some sort of unit dues payment table. it should be named to indicate the meaning of the data in the table - due_payments or similar name. the id column in this table defines the payment id, not the unit id. this table should have a separate unit_id column to relate the payment record back to the unit it corresponds to. the form to insert a new payment record should have a way of selecting from the existing units, such as a select/option menu. this will reduce typo mistakes and only allow valid units to be chosen. this select/option menu would display the unit name, but the value that is submitted would be the unit_id. the INSERT form processing code would insert a record into the payment table with the submitted unit_id, amount, and other fields you have defined. if you are editing an existing payment record, such as when correcting a typo in a value, you would reference the specific record using its payment id, not the unit_id. to display the corresponding unit name as part of this process, the SELECT query that retrieves the existing payment record would JOIN with the units table to get the unit name. the UPDATE form processing code would update the record indicated by the payment id value.
  25. if you are asking this question because your 1st code doesn't do what you expect, it's most likely because you are using one = in a comparison statement (which is a first week mistake) instead of two ==. despite what the documentation states, you can call bind result at any time after the mysqli statement object exists, but before you call the fetch statement (tested some time ago.) so, rather than to ask about which of the two versions of code is correct (neither will work correctly due to the above problem in both and the calling order of the bind result/fetch statement in the second one), come right out and state what sort of problem or error you are having that leads you to ask the question in the first place. at the risk of wasting time typing a reply that will be ignored again, you should NOT mix error handling logic with application functional logic. you should not combine both of these tests in this line of code - if(mysqli_stmt_execute($stmt)) && mysqli_stmt_fetch($stmt)). they mean separate things and since you already have error handling for the execute() call by using exceptions to handle the database statement errors, there's no point in having conditional error handling logic in your code.
×

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.