Jump to content

mac_gyver

Staff Alumni
  • Posts

    5,451
  • Joined

  • Days Won

    175

Everything posted by mac_gyver

  1. 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. 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. 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. 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.)
  5. 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.
  6. you are likely getting that same error when the the login works, but it is probably being hidden by a redirect. since you only use mysqli_stmt_free_result() if you are using mysqli_stmt_store_result(), which you aren't in the posted code, doesn't that mean that you shouldn't be using mysqli_stmt_free_result() at all? you need to switch to the much simpler PDO extension and use exceptions to handled db statement errors. it only takes 4 lines of code to replace the 11 lines you have from the sql query statement through to the fetch statement. $query = "SELECT id,recruits_number,sponsor_username,account_activation_status,id_video_verification_status,id_verification_video_file_url,username,password,primary_domain,primary_website_email,registering_country,registering_ip,registering_browser,registering_os,registering_isp,age_range FROM users WHERE $querying_column = ?"; $stmt = $pdo->prepare($query); $stmt->execute([$login_username_or_email_or_domain]); if(!$row = $stmt->fetch()) { // the email/username was not found // set up the failed login message } else { // the email/username was found, check the activation status and then verify the password hash to finish logging in // the fetched data is in the associative array $row }
  7. to do this, you will need to dynamically build the sql query statement, with a place-holder for each value (you can use a few array function calls to do this), then you will need to dynamically bind all the parameters. unfortunately, the php mysqli extension was designed poorly concerning prepared queries and dynamically calling the bind_param() statement requires a lot of extra, slow, messy code. if you can, switch to use the php PDO extension. it is much easier, straightforward, and consistent to use, over the php mysqli extension. to do this using the php PDO extension, after you build the sql query with the correct place-holders in it, you don't need to call any bind statements, and can just supply the exploded array as the input parameter to the execute() call.
  8. seems like this has been asked and answered before - https://forums.phpfreaks.com/topic/302345-how-to-loop-the-following-question-and-answer/
  9. calculate how long it will take for your table to have 5 million rows in it. with today's server hardware, 5 million rows in a properly indexed table is about the point where you need to start worrying about doing things like using partitioning or archiving older data.
  10. some separate issues - 1) a person's age is not a fixed value, unless they are dead. for people that are still alive, their age changes each year (or every 4 years if born on Feb. 29). you should instead be storing a date of birth and then calculating the age when needed. 2) you should be using php's password_hash() (and password_verify()) functions for your password hash.
  11. the fatal error is occurring after the point where the sql query statement is being executed (unless the profile related query is after the code you have posted), so it is not directly the cause of the data not being inserted, but it is a separate issue that MUST be fixed. if the data isn't being inserted into the reports table (is that the correct table for the profile information?) then the db_qry() function isn't detecting if there is an error and returning a false value so that the or die(...) logic has something to operate on. you would need to post the code for the db_qry() function for us to be able to directly help. as to the fatal error, if you read the php.net documentation for that function, you will find what it means and what to do to fix it. however, the code already has the 'fix' in it. you use the $_SESSION variable directly in assignments and references, combined with a session_start(); statement near the top of the code on any page that sets or references a $_SESSION variable. lastly, your code has some even more serious problems than what you are trying to currently fix. the reason for the first and third errors are because your php version was updated to at least php 5.5. if your php version gets updated again, to php 7, ALL the database code using the php mysql_ statements will stop working because the php mysql_ extension has been removed from php and your code will need to be rewritten. your code is also most likely open to sql injection, since it is putting data values directly into the sql query statement. switching to the php PDO extension and using prepared queries would be the best why of solving both of these problems.
  12. your pagination should retrieve the total number of rows you want to display on the page and it should use a variable (or defined constant) to specify the number of rows so that you don't have a hard-coded value in three different places in the code (and if you apply a little algebra to your equation, you only need to use the value in two different places.) next, as you are looping over the data to display it, you would either have a loop counter and a conditional test to check the value in the counter or you can use array_chunk() to break up the result set into chunks of the size you want. if you only want to display an advert once, you would test the absolute value of the counter. if you want to display an advert every n number of blog posts, you would use the Modulus operator to test the value of the counter. you would also test if the number of rows in a result set is less then the point where you want to display the advert, for example the last page of results, then display it once on the end of the output. lastly, the php mysql_ extension is obsolete and has been removed from php. you need to convert your code to use the php PDO extension, and use prepared queries to supply data values to your sql query statement.
  13. 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? do you have any error handling for the mysqli statements, so that you will know if and why they are failing? if you enable exceptions for the mysqli extension (there are examples in the php.net documentation showing how to do this), combined with the above two php settings, will cause any mysqli errors to throw an exception that php will catch and then display the actual error information. the above two items will get your code to tell you when and why it is failing. next, there are some problems and security issues with the code - 1) you cannot successfully use the ip address to identify a visitor. several people can share the same ip address and the ip address can change during one visit to a site (a cable/dsl modem gets reset for example.) you need to generate a cart id, store it in a session variable, and use it in the cart data. the easiest way of generating a cart id is to have an 'orders' table and insert a row into the table, with a status value that indicates a 'pending' order, i.e. a cart, and then get the last insert id and use this as the cart id. 2) you should not put data values directly into sql query statements. you should use prepared queries, with place-holders in the sql query statement, then supply the data values when you execute the query. the mysqli and PDO extensions both support prepared queries, but the PDO extension is much easier to use. if you can, you should switch all your code to use the PDO extension. 3) function names should indicate what the function does. a function named cart() could display the cart, add an item to the cart, update item(s) in the cart, or delete item(s) from the cart. the name should give a hint to anyone reading the code what the function does. 4) variable names and database columns names should also be descriptive. 5) any inputs a function needs should be passed as call time parameters. 6) you should use a post method form when you cause an action on the server, such as creating, updating, or deleting data. your add to cart should use $_POST, not $_GET. 7) you should validate data before using it. what happens if the 'add_cart' value is set but it's empty? it's not a number? it's not a valid product id? your cart needs a quantity column, so that someone can select more than one of something. 9) you need to define what your code is going to do for each possible combination of inputs and existing data. what should your code do if an item is already in the cart? should it output a message, replace the existing quantity with a one, or add one to the existing quantity? 10) your database table holding the cart contents should have the cart id and product/item id defined as a composite unique index so that you can only insert any item once in a cart. doing this will also allow you to use an INSERT ... ON DUPLICATE KEY UPDATE ... query to manage inserting a new item or updating the quantity of an existing item using a single sql query.
  14. a data driven method that doesn't involve program logic for each choice - // define the choices in a data structure $choices = array(); $choices['airflow'] = 'Beds with Airflow Fibre Mattresses'; $choices['supreme'] = 'Supreme Collection'; // add more entries here... $base_url = '/folding-beds/browse-by/'; $selector = isset($_GET['selector']) && isset($choices[$_GET['selector']]) ? $_GET['selector'] : 'airflow'; // get the selector or default to 'airflow' $href = $base_url . $selector; $text = $choices[$selector];
  15. $row['entry_name'] == $name; ^^^ this is a comparison, not an assignment, so one would expect nothing to be altered.
  16. this browser behavior cannot be changed. it occurs anytime the 'last' action for a url was a post method form submission. the way to prevent this is to do a header() redirect, i.e. a get request, to the exact same url after you have finished processing the post method form. see this link - https://en.wikipedia.org/wiki/Post/Redirect/Get
  17. also, at about line 10 in the friend requests code, you have this - if ($numrows < 1) { $numrows is an array, which may be empty if the query didn't match any rows, and that comparison makes no sense. use variable names that indicate the meaning of the data. this is the new friend request query result/data/rows and the variable name should be some variation of that information - $friend_request_rows would be one possible choice. then, an empty array is treated as a Boolean false, so you can directly test it in an if() conditional or you could use count() to find how many rows are in the array. next, your friend_one and friend_two columns should be the user id, not the user name. by storing the user name, you cannot edit any user name without going through and updating all the records holding the user name. storing the user id will also result in the least amount of data storage requirements and produce the fastest queries. finally, don't run queries inside of loops. your query to get the user table information (avatar) should instead be gotten by change the new friend request query to be a JOIN query with the user table. this will also 'fix' the problem in the current code with the $i variable that only 'works' if there is a single new friend request.
  18. your php code isn't outputting anything. you are producing the $data array, but you are not json encoding it and echoing it to the browser. the friend requests code is also echoing a string value and then exiting. this may be just for testing, but because the output isn't in the format that the ajax code expects, the javascript isn't going to do anything. you need to get to the point of being able to write, test, and debug your code. for the time being, forget about using ajax. just write a html form that submits the expected fields and values to your php code and get your php code to work. once it produces the expected output for all cases of inputs, then you are at the point where you can add ajax.
  19. start by setting error_reporting to E_ALL. by setting it to a 1, the only errors that are being reported are fatal runtime errors.
  20. if you have any type of account (bank, credit, loan, itunes, cell phone data plan, in game purchases, ...) that keeps track of an amount (quantity or money) or have ever done any in person or on-line shopping, you have seen this being used. it's not overkill, it's a necessity that's used everywhere in real situations. it gives you a record/audit trail of each transaction, so that you know all the who, what, when, where, and why information about each transaction. this lets you detect and correct errors, produce reports,... this method also has the advantage of correctly working with multiple concurrent users, since the changes made by each user will be recorded separately (at least the OP removed a race condition, by eliminating a separate SELECT query to get the 'current' starting amount.) without doing this, by just maintaining the amount in a field, there's no record of any duplicate data submissions, incorrectly entered values (transposed digits, hitting the wrong key), programming errors, fraud/cheating, ... the first sign of a problem is when someone tries to use an amount, that the system says exists, but it doesn't. if the OP is really doing an inventory system, that's more than just a classroom assignment or part of a beginner's attempt at making a game, the current method will eventually get out of sync with the actual products and you won't know which of the possible reasons why because there's no record being kept of what values have affected the total.
  21. in addition to not being able to execute multiple queries in one sql statement (unless you use a php statement/method call that supports it), your form has two fields named quantity and three fields named id. only the last field for any name will 'win'. you need to get your form code under control so that you will know which field is going to actually supply the values that your form processing code will use. next, you shouldn't add/subtract values to maintain a quantity. your current method has no way of detecting/preventing multiple form submissions from incorrectly altering the data. you can end up with the wrong quantity values and you won't even know if this has occurred. the correct way of maintaining a quantity (or any other 'account' total) is to insert a new record for each transaction that adjusts the value, inset a positive value to add to the quantity and negative value to subtract from the quantity. you would then simply SUM() the quantity for any id value (use GROUP BY id) to get the current quantity.
  22. this is a very common application. there are countless examples posted on the web showing the logic needed to do this. the only portion of an authentication script that would be Postgres specific would be the DNS (Data Source Name) used when making the connection to the database server and any database specific sql and php statements and if you use php's PDO extension, the php statements would be generic, simple, and straightforward.
  23. the code at the top of your post has - setcookie('hs_user_sess', $session, time() + (86400*30));, but there is no $session variable present in that code, so it would set the cookie to an empty value. also, break; only works for loops and switch statements. it has no affect on if() statements, so in the cases where you have used it in the code above, all the logic is still being executed. if your code testing if the cookie is set is being executed on the same page request where you are setting the cookie, the $_COOKIE variable won't be set until the browser makes a request to the web server after you have set the cookie.
  24. you probably have a type conversion problem or a null value that's matching all values. a) how do you know the second query is (apparently) matching 5 rows? you have only shown the code getting the result from the queries. perhaps there's a logic error or a mis-display of the results? b) what exactly does using var_dump($motionid); show and what ARE the motions_id values in the incorrect result set? c) how did the rows of data get inserted into the votes table and what is the column definition for the motions_id column?
  25. the code on your page should be laid out in this general order - initialization, start of database dependent code, determine user state and permissions, post method form processing, get method business logic, end of database dependent code, get method presentation logic, and html docuement/template. 1) initialization - create/define things your code needs - session_start(), require files holding configuration data/function definitions, setup an autoloader for class definitions... 2) start of database dependent code - create a database connection. 3) determine user state and permissions - check if the current user is logged in and retrieve any permissions the user has. the rest of the code on the page would make use of the logged in state and permissions to determine what code can be ran and what content will be produced. 4) post method form processing - the post method form processing code, which causes an action or change in state or change in data values on the server, should come near the start of your file so that you aren't tempted to output anything to the browser before the action/state/or data operation has been performed by the processing code. if your page has multiple sections of form processing code, you would have them all groped together in this section of code. after successfully (no errors) processing any post data, do a header() redirect to the exact same url that the form submitted to. this will cause a get request for your page. this will cause the browser to forget that a form was just submitted to that url and it won't try to resubmit the form data if you refresh the page or browse back to the same url. this also enforces separation of concerns. post method form processing is a separate concern from displaying data due to a get request for your page. if you want to display a one-time 'success' message after the header() redirect, pass it in a session variable, then clear he session variable after the the message gets displayed. if there are errors while processing any post data, you would not redirect, stay on the page, let the rest of the code on the page display the errors, (re)display the form, and repopulate the form fields with (some of) the previously submitted values. 5) get method business logic - code that produces/gets data needed for the dynamic content on the page. this code contains any database specific code that knows how to retrieve data from your database tables. the result of this code should be php variables that the code later on the page uses as its input. this code should contain NO html/css/javascript markup. 6) end of database dependent code - you can (or let php do this when the script ends/exits) destroy any query result resources (to free up memory) and the database connection at this point since you won't need them any longer. 7) get method presentation logic - code that knows how to take the data (database data, errors, form data...) from ALL the above code and produce the dynamic output for the page. if the output doesn't require any 'heavy' processing/formatting, just use the data directly in the html page/template code. the result from this code should be php variables that the html page/template uses. this code should contain NO database specific statements. if your page has multiple sections of get method presentation logic, you would have them all groped together in this section of code. html document/template - this section starts with the <!DOCTYPE ... tag and ends with the </html> tag. it is the actual html document that the dynamic output is put into to make the complete page. if you use php (rather than an actual template system) only simple php conditional logic/loops, function calls (that are responsible for producing output), and echo statements should be present in this section of code. any data you output on the page needs to be passed through htmlentities() in order to prevent any html content in it from being operated on by the browser. if you organize the code on your page like this, it will separate all the different concerns, making it easier to see what your code is doing, easier to test, and easier to get help with because you can isolate and post just the relevant part. next, if you put the form processing code and the form on the same page, it will reduce the amount of code you have to produce, since it will eliminate the repetition of the common items. this will also let you re-populate the form field values in the case where there were validation errors with the submitted form data. some specific comments for the code you have posted - 1) the global keyword only has meaning when used inside of a function (which you are not doing) and even then it should be avoided as it breaks the encapsulation and scope. remove any lines of code containing the global keyword. 2) if you use a php array variable to hold validation error messages, it will also serve as an error flag. if the array is empty(), there are no errors. if the array is not empty(), there are errors. after you have validated all the input data, you would use that data if there are not errors. at the point of (re)displaying the form, if there are errors, you would display them, either as a group or display them individually near the form field they go with. 3) you should NOT be using addslashes() at all. 4) whatever your validateInput() function code is, is probably not actually validating anything. if you want help with the validateInput() code, you need to post it. 5) this is a bit tongue in cheek, but a person's age is not a fixed value, unless they are dead, and you should not be storing a person's age. you should be getting and storing the date of birth and then calculating the age when needed. edit: since you are using a file to hold the data, substitute 'file operations' for any mention of 'database' in the above information.
×
×
  • 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.