-
Posts
5,514 -
Joined
-
Days Won
185
Everything posted by mac_gyver
-
here's something that will save you a ton of duplicate effort. client-side validation is a nicety for legitimate visitors. data sent to your web sever can come from anywhere, not just your forms/links/cookies, can be set to anything, despite any client-side validation you may have, and cannot be trusted. you must trim, mainly so that you can detect if a value is all white-space characters, then validate the trimmed data, on the server, before using it. since you must do this on the server, you should either just use the browser's built-in form validation or use ajax to send the piece(s) of data to the server for pre-submission validation, then validate it again, on the server, when the form has been submitted.
-
most database errors are either due to programming mistakes or a database server that's not running. these type of errors are not recoverable by the user, and the user or hacker on a site doesn't need to know anything specific when these type of errors occur. however, you, as the programmer/developer, do want to know when these type of errors occur. therefore, when learning, developing, and debugging code/query(ies) you would like to display the raw database statement errors, so that you get immediate feedback about problems. when running your application on a live/public server, you would like to log the raw database statement errors, so that you have a record of them, and can find and fix what's causing them. the PDO extension has always used exceptions for connection errors. you should use exceptions for all the other database statements that can fail - query, exec, prepare, and execute. in php8+, the default setting now is to use exceptions for all the database statements that can fail (for both the PDO and mysqli extensions.) you should only catch and handle database exceptions in your code for user recoverable errors, such as when inserting/updating duplicate or out of range user submitted data. the exception catch logic would test the query error number, and setup a message for the user letting them know what was wrong with the data that they submitted, so that they can potentially correct what is wrong, and resubmit the data. for all other query error numbers, just rethrow the exception and let php handle it. for all other types of queries, simply do nothing in your code and let php catch and handle any database exception. when php handles an exception, php will use its error related settings to control what happens with the actual error information, via an uncaught exception error (uncaught exceptions will 'automatically' get displayed/logged the same as php errors.)
-
PHP Form Won't Send - Missing PHP for Submit Button
mac_gyver replied to Lanxalot's topic in PHP Coding Help
the double posted code is the same form, but with a different amount removed for posting by the op. the 13 lines starting with the id="package-step07" div has been additionally removed from the second posting. code doesn't just stop working, so you will need to investigate what is actually occurring. is the form processing code actually getting executed? are there any php errors getting displayed/logged? you will likely need to check with your web server administration as to what is happening with these emails on the mail server. a bunch of recommendations - email can be unreliable. you should store the submitted form data in an database table or a log file so that you have record of the form submissions. the form processing code should NOT copy variables to other variables for nothing. this is just a waste of typing. keep the form data as a set in a php array variable, then operate on elements in this array variable throughout the rest of the code. as a more advanced programming task, if you have more than 2-3 form fields, you should use a data-driven design and dynamically validate and process the form data. you need to trim all the input data before using it, mainly to detect if all white-space characters were entered. after you do item #2 on this list, you can accomplish this will one single line of code. you need to validate all the trimmed input data before using it, storing user/validation errors in an array using the field name as the main array index. 'required' fields must not be equal to an empty string and fields that must have a specific format, such as an email address, must be validated to insure they have that format. after the end of the validation logic, if there are no validation errors (the array holding the user/validation errors will be empty), use the form data. you need to apply htmlentities() to all the submitted form data, after validating it and before using it in an email or in form field values, to help prevent cross site scripting. you must test the return value from the mail() call. if it is a false value, setup a general failure message for the user and log all the relevant data from the request, such as - date/time, ip address, form data, ... the form fields should be 'sticky' and repopulate the field values upon any user/validation errors, so that the user doesn't need to keep reentering data over and over. note: if there are user/validation errors, you would redisplay the form, therefore it should not be inside the else conditional for a post method form having been submitted. if this stopped working, the most likely cause is that it is being used to send spam. by not validating the submitted email address (see item #5 on the above list) and putting the submitted value into the mail header, a spammer can send anything to anyone he wants through your mail server. -
nothing i wrote concerns a fixed amount for each fee type. the fee type is the name/meaning of the fee and by submitting the correspond fee_id and storing that, you are normalizing the data, which will result in the least amount of data storage and the fastest queries. the amount field should actually get populated with the current default amount for the selected fee type (i would use data- attributes and some javascript), for those cases where the standard fee will be used.
-
this is at least the 3rd time someone has stated in your threads to not store derived values. you just calculate them when needed. and if you store the raw data properly, it is a simple and fast query to do so. you should (and probably do) have a student table, which holds the unique/one-time student data. this defines the student_ids. any data related to a student should use the student_id. you should not have any other values from the student table, such as the student_name, in any other table. you should (and probably do) have a semester table, which holds the unique/one-time semester data. this defines the semester_ids. you should (and probably do) have a class table, which holds the unique/one-time class data. this defines the class_ids. you should have a register table, which i suspect is what the invoices table is trying to be, that holds a row for each class, for each semester, for each student. this table defines the class_semester_student_ids that should be used when storing related data, such as invoices, assignments, exams, ... to keep track of the invoice data, per my reply in your previous most recent thread - "you should have a 'fee' table that holds the different type of fees/discounts. you would then have a select/option menu to select the fee type, which submits the fee_id, and the fee amount." you would insert a row for each fee/discount for each class_semester_student_id into an invoice_item(s) table (currently named items_table.) to get the current amount for any or all fee type(s) for any or all class(es), semester(s), or student(s), you would simply SUM() the +/- amounts for the records matching the WHERE term that you build.
-
Fixing Issues with PHP, AJAX, and MySQL Data Insertion
mac_gyver replied to Olumide's topic in PHP Coding Help
in the network tab, if you click on the URL, which is apparently save_invoice.php, it will show you a list of tabs for the request and response data. -
don't unconditionally loop over $_POST data. hackers/bots can submit 100's or 1000's of fields (php had to add a setting to limit the number of fields), with their own field names (which will allow sql injection in the query), not yours. you should instead have an array the defines the expected fields, then use this definition to control what your code does. this is referred to as a data-driven design. see this example - // define the expected form fields $fields = ['easting', 'northing', 'purpose', 'country', 'admin1', 'admin2', 'admin3', 'settlement', 'orig_wellno', 'date_completed', 'coord_sys', 'elev', 'status']; $col = []; // array of columns $data = []; // array of prepared query input values // add the well no $col[] = '`well_no`'; $data[] = $_SESSION['well_no']; // use whatever the actual session variable is // loop over the defining array foreach($fields as $field) { // note: empty considers 0 or '0' to be an empty value. this will prohibit a numerical zero value being used. // you should instead test if the value is or is not an empty string. if($_POST[$field] !== '') { $col[] = "`$field`"; $data[] = $_POST[$field]; } } // build the sql query $sql = "INSERT INTO well_parent (".implode(',',$col).") VALUES (".implode(',',array_fill(0,count($col),'?')).")"; // examine the result echo $sql; echo '<pre>'; print_r($data); echo '</pre>';
- 2 replies
-
- 1
-
-
- pdo
- $_post variables
-
(and 1 more)
Tagged with:
-
Fixing Issues with PHP, AJAX, and MySQL Data Insertion
mac_gyver replied to Olumide's topic in PHP Coding Help
the grand total is a derived value. you would calculate it whenever you need it, but do not submit it or store it in the database table. the jquery .ajax success function is called when the ajax request is successful. all this means is that the request and response occurred. when using an ajax request, it is up to your server-side code to build and output appropriate data that the javascript tests for and uses. since you are console logging a fixed 'Invoice data saved successfully.' success message, that is all you know. as @Barand has posted, you can check the browser's developer tools network tab to see what is actually being output by the server-side code. as to the actual problem, which of the commented out lines of code are actually in place? does your insert query list the total_fee_payable column and have a corresponding prepared query place-holder, that's being supplied the correct value when the query gets executed? some other things the code should/should not be doing - you should be selecting from existing students, that are registered for the selected semester, with a select/option menu, possibly with type-a-head, auto-suggest filtering, which i'm guessing you may be doing, since you have some disabled form fields. this should result in a student_semester_id, that you would use when storing related data. you should have a 'fee' table that holds the different type of fees/discounts. you would then have a select/option menu to select the fee type, which submits the fee_id, and the fee amount. you would insert a new row for each different fee/discount for each student_semester_id. the invoice number should be generated by your system, which it may be based on the disabled form field. programing already is a tedious typing activity. if you find yourself repeating code that only differs in its name, it is a sign that you should be getting the computer to operate on the repetitive set of values, instead of you doing a lot of typing. some things you can do that will simplify the code - in the javascript, if you assign a unique class name to the 'fee' fields, you can assign the 'input' event to all the fields with that class name at once, and you can operate on all the values by getting them as a collection and looping over them. you can get all the form field values at once using either the jquery .serialize() method or a javascript FormData object, without writing out lines of code for each field. in the php code, detect if a post method form was submitted, then reference the form data. this only takes one line of code, regardless of how many fields there are. only unchecked checkbox/radio fields won't be set. these are the only cases where you should use isset() statements. don't copy variables to other variables for nothing. this is just a waste of your time typing. keep the form data as a set, in a php array variable, then operate on elements in this array variable throughout the rest of the code. you should trim all input data, mainly so that you can detect if it is all white-space characters, before validating it. after you do item #5 on this list, you can trim all the input data at once, using one single line of code. you should validate all inputs separately, storing user/validation errors in an array, using the field name as the main array index. after the end of the validation logic, if there are no errors (the array holding the user/validation errors will be empty), use the form data. if the insert query could result in duplicate records, your exception catch logic should test for a duplicate index error number, and setup a message for the user (add it to the array holding the user/validation errors) letting them know what was wrong with the data that they submitted. for all other error numbers, just re-throw the exception and let php handle it. if you simply supply an array of the input values to the ->execute([...]) call, you can eliminate all the bindParam() statements. after the end of using the the form data, if there are no errors, you would setup a success response and output it. if there are errors, you would setup an error response, consisting of the all the error messages, and output it. for an advanced programming task, if you have more than 2-3 fields, you should use a data-driven design and dynamically validate and process the data. -
the basic jquery dataTable coding is only usable up to a few hundred rows of data, because of the time it takes to send that much data/markup to the client and how much time it takes to manipulate that much data in the client. once you have a lot of real-world data, you need to switch to use server-side processing, where the dataTable is just the User Interface (UI) and the actual work of column sorting, pagination, and searching is done on the server. only the data needed to 'draw' the current page is output to the client. see this link - https://datatables.net/examples/server_side/index.html in any case, if you want to do something like search and find all the orders that use an item, you will need to list all the items in the orders, repeating the common order data in the columns without using rowspans.
-
so, you actually have a jquery dataTable problem? the dataTable coding assumes that each row has the same significance. any column sorting and pagination is based on the literal rows of data. i suspect that as soon as you put a rowspan with more then one row, that it produces javascript errors. you can check in the browser's developer tools console tab. the question becomes, what are you trying to accomplish? if you want to list all the orders, with column sorting, pagination, and searching, you would only output the unique/one-time information about each order. if someone finds an order that they want to see the details of, they would click on a link and, for example, open a dialog popup with the item details in it. you might (untested) be able to use the jquery dataTable show extra/detailed information api - see this link - https://datatables.net/examples/api/row_details.html If you want to instead be able to do column sorting, pagination, and searching for both order information and item information, forget about the rowspan and just repeat the common information in each row.
-
the links you produce need to start with a copy of any existing $_GET data (so that the original $_GET data is unchanged), set the relevant element(s) in the copy of the data, such as the id element, build the query-string part of the URLs using php's http_build_query(), then produce the link. this will propagate any existing filter, pagination, search, ... terms in the links.
-
unless you can have multiple images per weapon, now or in the future, you don't need a separate table for the images. if it is possible that a weapon doesn't have an image, you would either skip producing the markup for the image or display a general 'no image available' image instead. this php error message indicates that the query failed due to an error (or perhaps your full code is overwriting or using the variable for something else), and that you don't have any error handling for database statements that can fail. see my first post in this thread, point #5 about using exceptions for database statement errors. a) you should be using php8+ and b) you should set the error mode to exceptions for the database extension you are using if you are not using php8+. edit: i see that, at least in the documentation, a null is returned when there is no (more) data to fetch (it used to be a false value for this condition.) if so, this indicates that the query didn't match any data. if this is a case of no image for a weapon, you need conditional logic to test for an image or not and take an appropriate action in the code. the snippet of code and variable naming also implies you are executing queries inside of loops. this is extremely inefficient and is resulting in a wall of unnecessary code/query(ies). when you have related data in multiple tables, you need to use an appropriate type of JOIN query to get all the data that you want in a single query, then simply loop over the result from that single query to produce the output that you want.
-
did you look at the resulting markup in your browser's 'view source' of the page to see what might be wrong with it?
-
presumably, you have a weapon table, that holds the definition of each weapon, with damage value for each weapon? the total damage is a derived value. you would query/calculate it when needed. you would use a JOIN query, between the playeritem table and the weapon table, to SUM() the damage value for each weapon that the user has. some points about the posted code - you should trim all input data, mainly so that you can detect if it was all white-space characters, then validate it before using it. if an input is required to be non-empty or must have a specific format, don't use it if it isn't valid. don't copy variables to other variables for nothing. you should use a post method form when performing an action on the servers, such as when inserting, updating, or deleting data. don't put external, dynamic values directly into sql query statements, where an sql special character can break the sql query syntax. use a prepared query instead. if it seems like using prepared queries with the mysqli extension is overly complicated, it is. this would be a good time to switch to the much simpler and more modern PDO extension. don't use or die() for error handling. you should instead use exceptions for database statement error handling (this is the default setting now in php8+) and only catch and handle database exceptions for user recoverable errors, such as when inserting/updating duplicate or out of range user submitted data. for all other query errors and other types of queries, simply do nothing in your code and let php catch and handle any database exception. don't create specific variable names for nothing. e.g. $reequip, $equip. the only variable names that must be unique are the result from any section of code that will be used elsewhere in the code. for these two variables, just use $sql or similar, since you will completely deal with one query before going on to do something else in the code. don't echo static markup. just drop out of php mode and put the markup inline.
-
trying to create new connections after each login using PDO
mac_gyver replied to nlomb_hydrogeo's topic in PostgreSQL
the user registration/login system on your web site is for the purpose of determining what a user can see and do on the web pages. this has nothing to do with database connections. it is your application code that is performing the database operations and the database connection credentials are making a connection to allow your application code to do its work. it is up to your application code to determine what database operations can be performed for any user to your site. this is not how web applications are implemented. post or describe an example of something you think requires this, and a forum member will provide information on how to correctly implement it. -
your login code should put the user's id (auto-increment primary index) into a uniquely named session variable, such as $_SESSION['user_id']. you would then test if that session variable is set on any page that requires a logged in user. you would query on each page request, using $_SESSION['user_id'], to get any other user data, such as the username, email, access type, ... don't do that. once you have the user's data, just test/use it on a single page to control what content gets displayed on the page and what action the user can perform on that page. since this query to get the access type will at most match one row of data, don't use a loop at all. just fetch/test the data. i reviewed your previous thread on this forum. you were using a single fetch() statement in it. what happended? this implies your db() function creates a new database connection every time it is called. don't do that. a database connection is one of the slowest operations you can perform on a page. your application should create one database connection, then use that single connection for every database operation on the page. don't do this. as of php8, the default setting for PDO error handling is to use exceptions for all the database statements that can fail - connection, query, exec, prepare, and execute. with exceptions, any discrete error check logic in your code won't ever get executed upon an error since execution transfers elsewhere. this is one of the great points of using exceptions. your main code will only 'see' error free execution. if execution continues past a statement that can fail, you know the statement was successful without needing conditional logic to test if it was or was not. this simplifies the code, allowing you to remove all the now unnecessary conditional logic. the only time you should catch and handle a database exception in your code is for recoverable user error, such as when inserting/updating duplicate or out of range user data. for all other error numbers and all other query types, just let php catch and handle any database exception. if you set the default fetch mode to assoc when you make the database connection, you don't need to specify it in each fetch statement, simplifying the code.
-
you logic makes no sense. $bob is an array. the comparison with == 1 'works' because a non-empty array is a true value that is loosely equal to 1. your goal should be to test the value in $bob['fk_usertypes_id'] also, is there more than one row of data matching the email address? if there is not, don't use the fetchAll() method and don't use a loop to loop over the data. just fetch the single row of data.
-
a space in an attribute value is a stop character, indicating the end of the value. to make this work, you need to enclose the attribute value in quotes (single or double.) you should actually always enclose attribute values in quotes, for consistency, even in those cases where they are not required. however, the value attributes should be the organization ids, not the organization names, so that when you store the submitted data, you are storing the organization id. this will result in the least amount of data storage, the fastest queries, and allow you to edit the organization name or even display the organization name in a different language, without affecting the stored data. next, for the 'required' attribute to work, the first option choice needs to have an empty value attribute and serve as a prompt, e.g. <option value=''>Select an Organization</option>. lastly, there's no good reason to catch and handle an exception from a SELECT query. any error from this type of query, is either due to a programming mistake or the database server is not running, is not recoverable by the user, and the user doesn't need to know anything about its occurrence. simply do nothing in this case and let php catch and handle any database exception from a SELECT query.
-
if you got an error, you need to post it. the $page_count variable doesn't exist, likely causing an undefined variable error, nor is it used anywhere in the posted code. you don't need to SELECT data in order to decide to insert or update it. just use an INSERT ... ON DUPLICATE KEY UPDATE ... query. you can use the MySql LAST_INSERT_ID(expr) function in the query to make the counts column value accessible via the expr (expression) argument without needing to execute another query. don't put external, unknown, dynamic values directly into an sql query statement. use a prepared query instead. if it seems like using a prepared query with the mysqli extension, this would be a good time to switch to the much simpler and more modern PDO extension.
-
the reason to use the name as the array index is this allows you to directly test for and access the entry in the array, without needing to search through the entire array. this is the same reason that you index data in a database. this greatly simplifies and speeds up the code/query. the reason your code doesn't work when the data starts at the zeroth index in the array is because array_search() returns the index if the value is found, but the zero index is a false value in a loose-comparison. array_search() returns an exact false value when the search fails to match a value. to test for a not-found condition, you must test if the returned values is exactly false, e.g. ===false. to test for a found condition, you must if the returned value is not exactly false, e.g. !==false.
-
Data not showing properly in correct header
mac_gyver replied to CSS-Regex's topic in Javascript Help
the code is doing exactly what it was written to do, build a <tr><td>num</td></tr> for each number. if you want to produce a single <tr></tr>, you would need to add the opening <tr> before the start of the looping and add the closing </tr> after the end of the looping. -
you can also use the BC math functions, which expects strings as input and operates on each character as a bcd digit, like a hand held calculator works.