Jump to content

mac_gyver

Staff Alumni
  • Posts

    5,518
  • Joined

  • Days Won

    187

Everything posted by mac_gyver

  1. the most common reason for a password_hash()/password_verify() to fail is because the database column is not long enough to hold the hashed value. another common reason are programming mistakes in the form/form processing code and a lack of server-side validation that results in the hash value not actually being from the password that was submitted in the registration code, or the value being used in the login code not being what you think it is. your post method form processing code should always trim the input data, mainly so that you can detect if all white-space characters were entered, then validate all inputs before using them.
  2. so, i found the problem, with the help of php's error reporting, though the problem is in javascript. you are echoing blocks of static html/javescript using php's heredoc syntax. when I made the test page i used, the javascript was simply in-line. you are using template literals with embedded expressions in the javascript, e.g. ${some_var}. however, in php's heredoc syntax, this is the syntax for a php variable. so, php is putting the last value for any of its variables with the some_var name into the echoed javascript. how i found this is that the embedded expressions in the openUpdateTotalsPopup() javascrpt, for ${width}, ... produced undefined php variable errors. the simplest fix would be to use php's nowdoc syntax. the correct solution would be to NOT echo blocks of static html/javascript, which I see i wrote about in one of your previous threads.
  3. i haven't looked that the code yet, but in Quotes/Edit_Quote_Quantity.php, log the $_GET variables so that you can see how many requests are made to it and what the inputs are - file_put_contents('log.txt',print_r($_GET,true),FILE_APPEND);
  4. a test page works for me (uses the correct quoteItemId matching the clicked button, both in the javascript and in the php code) in chrome, edge, and firefox, but i don't have all the code on your page. the only changes i made to the //loop code is to add a <table> tag before it and comment out the 5 lines with number_format() calls, since i didn't want to make up fake data to loop over for these. do you have some event listener for 'buttons' that could be affecting this? this is acting like some broken markup is causing all those buttons to call the last openEditQuantityPopup(...), instead of the correct one or all the buttons are being clicked and you are seeing the end result from the last such operation. i would console.log the quoteItemId value inside the openEditQuantityPopup() faction, so that you can see how many times it gets called, and with what value as an input. in the end, you will need to post all the code on that page that's necessary to reproduce the problem.
  5. probably this - when you browse to main.php (or is it index.php), do you include the www. on the URL or not and does the URL you use for login.php always include the www. or not? also, since you have shown the full login code, the redirect upon successful completion of the form processing code MUST be to the exact same URL of the login page. this is so that the browser won't attempt to resubmit the form data should that page get browsed back to or reloaded, where someone can use the browser's developer tools to look at what the form 'payload' is and see what the email and password are for the last person to submit the form.
  6. sending a session variable from one page to another involves - having a working, error free, session_start() statement on both pages; have a server properly setup with a folder to hold the session data files; have the session cookie parameters setup so that they match the url for both pages; assign a value to a session variable on one page, that you are sure isn't getting cleared after you have set it, and test for and use the session variable on the second page. except for very overt symptoms, there is not a 'one symptom' is always caused by 'one thing' relationship in programming. if you are expecting someone here to be able to directly tell you what the cause of this problem is, you are mistaken. there are too many possibilities. when something in programming doesn't work, you must find where your code and data are doing what you expect and where they are not. the problem lies between those two points. if all you have done is run your code and notice that the output doesn't exist, you haven't narrowed down the problem. the first step in narrowing down a programming problem is finding any errors that the language is reporting. to do this, you must setup the error related settings and verify that they are actually the values that you have set them to. in your last thread, you would have been getting a fatal run-time error to alert you to one of the problems in the code, but you didn't indicate you were getting any errors. this means that php's error related settings (error_reporting, display_errors, and log_errors) are not setup so that php will help you. once you have set the error settings as i stated, and comment out the redirect, this will narrow down the possibilities, by either producing a error pointing to a problem or if doesn't produce an error this points to where to look at next.
  7. do you have php's error_reporting set to E_ALL and display_errors set to ON, preferably in the php.ini on your system, and you have confirmed using a phpinfo(); statement in your code that these are the values php is using? you can temporarily put these settings into your code, on both pages, immediately after the first opening <?php tag. next, if php's output_buffering is on, and you have a redirect in your code, it will discard any non-fatal errors or debugging output you have added. temporarily comment out the header() redirect so that you can see if there are any php errors up to that point. do you have a session_start() statement in the login.php code? and as is sometimes given, here's a list of programming practices for the posted code - don't use variables ending in numbers. you should completely deal with the result from one block of code before performing another operation, and there's no need to use or to keep track of numbered variables. you should list out the columns you are SELECTing in a query. you need to use prepared queries, instead of putting dynamic values directly into sql query statements. if it seems like using the mysqli extension is overly complicated and inconsistent when dealing with prepared queries, it is. this would be a good time to switch to the much simpler and better designed PDO extension. you need to use php's password_hash() and password_verify() for password handling, i.e. don't store passwords as plain text. the value you store in a session variable upon successful login should be the user's id (autoincrement primary index), and it should be named user_id or similar. you should query on each page request to get any other user data, such as the username or permissions. this is so that any changes made to this other user data take effect on the very next page request after is has been changed, without requiring the user to log out and back in again. the header() redirect needs an exit/die statement to stop php code execution. you could, for example, have some code following the posted code, that's clearing the session variable.
  8. you should do this directly in the sql query statement. MySql has a large number of datetime functions. what is the format of the 'date' column in the database table? if you do this in the php code, you must either compare objects with objects or compare formatted strings with formatted strings, with the same exact format, in a left-right order from most significant field (year) to least significant field (day.) the current php code produces a fatal error at the date_diff() method call, because the 2nd argument must be an object, not the $data["date"] string. $date is a datetime object, you cannot directly compare it with the $data["date"] string. you either must use the datetime ->format() method to produce a formatted string from the $date object, or you must create a datetime object from the $data["date"] string. $diff in a dateinterval object. to get the number of days, you would need to use the dateinterval ->format() method with the '%a' format specifier to produce the whole number of days.
  9. if you post the code generating the array, someone could post an example, instead of just writing about how to do it.
  10. if all you want is a COUNT() per last name, you can do that in the query that's getting the data, with a GROUP BY last_name term. if you want the name data and a count for each last name, i would index/pivot the data using the last name as the main array index when you fetch the data, from wherever it is coming from.
  11. wildcard characters % and _ are only used with a LIKE comparison in a query. if your first query produces any result, it means that you managed to store the % characters in with the data in the database table. preg_match() is a php function. you cannot put it a query to match data in the database table. this query would be producing an sql error. are you using exceptions for errors for the sql queries (this is the default setting now in php8+)? MySql does have regular expressions. see this link - https://dev.mysql.com/doc/refman/8.4/en/regexp.html the regex pattern you came up with matches a string with exactly 3 decimal digits. your stated example is to match 2 digits. which is it and can it vary? what exactly is the overall top-level task you are trying to accomplish, because using regex pattern matching is slow and cannot use indexes, so is a poor choice when you have large amounts of data? lastly, do NOT put dynamic data values directly into sql queries, where any sql special character in a value can break the sql query syntax. use a prepared query instead. if it seems like using the mysqli extension is overly complicated and inconsistent, especially when dealing with prepared queries, it is. this would be a good time to switch to the much simpler and better designed PDO extension.
  12. you are trying to store the data like it is in a spreadsheet, not a database. doing this makes all the code and queries to perform any action on the data overly complicated. it appears that each html table section is for a different type/category of products? within each type/category of product, the testx field is the item id, the testx1 field is the quantity, and the testx2 field is the total? if so, when you store the data in the detail table, you should have a category_id column (that indicates which html table section that data is for), an item_id column, a quantity column, and a total column.
  13. you still have not provided any context (meaning) of this data. name-numbered, labels and variables, are meaningless to us. if the mix of rows shown in the example picture is valid, i.e. you can have have any number of rows from each html table section, you should (probably) store the data from each row in each html table as a separate row in the detail database table, with an item_id column to indicate the meaning of each row of data. i have a recommendation for the dynamically added markup. don't write out the markup in the javascript yourself, where you have to keep it updated to match any changes or corrections (you are going to need to eliminate the use of duplicate ids) you make to the markup being output on the page. instead, define/store the output being output on the page in a php variable, so that you can echo it on the page and echo it as the markup inside the javascript. if you use back-ticks (template literals) around what you echo in the javascript, you can use the exact same markup in both cases. see this link - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
  14. here's a separate list of points for the posted code - use 'require' for things your code must have. include_once, require_once, require are not functions. the () around the path/filename don't do anything and should be removed. every redirect needs and exit/die statement to stop php code execution. the current login check code still allows the rest of the code on the page to run. your form processing code and form need to be on the same page. this simplifies all the code, provides a better User eXperience (UX), and allows you to repopulate the form fields with any existing data so that the user doesn't need to keep reentering values over and over upon an error. this will also let you easily edit existing data when you get to that point. if db.php creates a database connection, why are you also creating a database connection in-line in the code? modern php (8+) uses exceptions for database statement errors by default. with exceptions, there's no need for discrete logic to test if a statement worked or failed and any existing discrete logic should be removed. you should be using prepared queries to prevent any sql special characters from being able to break the sql query syntax, which is how sql injection is accomplished. this will also greatly simplify the sql query syntax. if it seems that the mysqli extension is overly complicated, especially when dealing with prepared queries, it is. this would be a good time to switch to the much simpler and better designed PDO extension. do not query to get the current max() value for a column and use it. this is not concurrent safe. you need to the 'last insert id' function/method/property to get the autoincrement id from the first insert query. do not use any calculated total submitted from the browser. the submitted data can be altered and cannot be trusted. perform any such calculation on the server using data that is on the server. the redirect you perform upon successful completion of the post method form processing code needs to be the exact same URL of the current page to cause a get request for that page. this will prevent the browser from trying to resubmit the form data should that page get browsed back to or reloaded. you need to validate the resulting web pages at validator.w3.org ids in the markup must be unique. you should NOT include the id attributes in the addRow markup. if you are not using the id attributes, simply leave them out of all the code. the <label></label> tags are incomplete and not associated with the corresponding form field. the simplest way of correcting this is to put the closing </label> tag after the form field the label corresponds to.
  15. your dynamic addRow javascript only adds a row to the current html table, but the form processing code assumes that all the array form fields have the same number of elements. since your example, using name-number elements, provides no context upon which to help you, you need to decide if you should change the form to dynamically add a row to every html table at the same time or if your form processing code should handle the data from each html table separately, possibly even storing related data in separate database tables. if you care to provide some real world context to this data, we would be better able to help.
  16. in the mysql documentation, where the year() and curdate() functions can be found, there's a date_format() function that has a way of doing what you are asking - https://dev.mysql.com/doc/refman/8.4/en/date-and-time-functions.html#function_date-format didn't everyone learn from the y2k problem not to store years as 2 digits?
  17. secondary to the problem in this thread, if you are at the point of updating data, you should be using a unique id to reference specific row(s) of data.
  18. you should use a decimal data type. a float data type suffers from floating point conversion errors, because some values cannot be exactly stored. the = comparison doesn't work because the actual value as a float is something like 27.550001 (just an example) the like comparison works because the value is converted to a string and the like compares the values character by character.
  19. what is the data type of the cost column?
  20. i'm going to guess that the overall goal you are trying to accomplish is reading data from an api and insert new data into a database table or update existing data? if so, you can accomplish the insert new data/update existing data using a single query. see - https://dev.mysql.com/doc/refman/8.4/en/insert-on-duplicate.html
  21. danger of what? your example doesn't do what you think. the javascript is NOT calling the php function. the php code runs on the web server when the page is requested. the php code is echoing whatever the function produces (and the echo tester(); statement echoes a null value because the function is not returning anything.) if you look at the 'view source' in the browser of the page that this code is on, the output from the php code is already there. all the javascript is doing is taking what was assigned to the test variable and putting it into the id="tx1" element. the code might as well just directly echo whatever the function produces in the markup for the id="tx1" element. how often does this remote data change? you would need to cache/persistently store this remote data somewhere in order to avoid reading it again. web servers are stateless. they don't know or care what happens outside of the current http(s) request they are serving. when the php code on a page ends, all the resources used in the code are destroyed, so the remote data that you read is destroyed. perhaps if you provide a more helpful example of what you are trying to accomplish, rather than your proposed solution for accomplishing it?
  22. browsers, including javascript running in the browser, make http(s) requests to web servers. the browser/javascript is not directly calling anything in the php code. the server-side code, on the page that you make the http(s) request to, would build and execute any edit/update query for a database. to use javascript to make a http(s) request, after the page has been requested and sent to the browser, you would make the request using ajax. see - https://developer.mozilla.org/en-US/docs/Glossary/AJAX all data submitted in http(s) requests to a web site can come from anywhere, not just your web pages, can be set to anything, and cannot be trusted. you must use the data securely in whatever context you are using it in. if the edit/update operation requires a logged in user having permission to perform an update query, the server-side code must have logic to enforce these conditions. the actual query must securely use the data to protect against any sql special characters in a value being able to break the sql query syntax. the simplest way of providing this protection, for all data types, is to use a prepared query. what does reading information from a source that takes a long time have to do with editing/updating data in a database?
  23. you didn't answer what is wrong with the last posted code/output? i understand your code perfectly. the list of programming practices will help to - secure your web site, provide a good User eXperience (UX), simplifies the code, and corrects some mistakes. i looked back at the search form, here's a similar list for it (repeats some things already posted) - to get a form to submit to the same page it is on, simply leave out the entire action attribute. as already written, this should be get method form and it should be 'sticky' and reselect any existing option choices. you need to validate the resulting web pages at validator.w3.org you should list out the columns you are SELECTing and only list the ones you are using in the code. you should (almost) always fetch data using an associate index name so that if your database table gets rearranged the code will still work and your code will be self-documenting (anyone reading it can tell what it is doing without needing to know what your table definitions are). any query that can match more than one row of data needs an ORDER BY ... term so that the data is in an expected order. some of your queries have an ORDER BY, some don't. using a character data type for numerical data won't sort correctly once you have values with more than a single character length. you should use a numerical data type for numerical data. the default ORDER BY ... direction is ASC. you don't need to specify it in a query. if a query doesn't match any data, you should output a message stating so, instead of outputting nothing. you need to apply htmlentities() to dynamic values being output in a html context, right before/as they are being output in order to prevent any html entities in a value from being able to break the html syntax. if you use php's short-open-print-tag <?= it will save typing. also, you can leave out the closing ; right before a closing tag ?> saving typing. there's a ; on the end of all the while ():; statements. this should either be a syntax error or is short-circuiting the loop and should be removed. for the 'required' attribute to work for a select/option menu, the first option choice must have an empty value and serve as a prompt to make a choice. you only need to use the 'required' attribute, you don't need the ="required" value. for a <label> to work, you must either have a for='...' attribute and a corresponding id='...' attribute in the field or more simply just put the closing </label> tag after the form field it corresponds to. if you have a <label>, you cannot have an empty display item for the first <option></option> choice. don't use a series of name-numbered variables. you are/should be completely dealing with the result of one query before going on to the next. just reuse simple variable names.
  24. and what exactly is the problem with the last posted code? here are some points for the current code - you should use a single database extension. now that you have used the much simpler and better designed PDO extension, all your code should be updated to use the extension. you should NOT use the mysqli_real_escape_string() function, which probably doesn't have the character-set set, to match your database tables, when the connection was made, then put these pieces of data directly into the sql query statement, as this can allow sql special charters in a value to break the sql query syntax. you should use a prepared query. converting a query that has php variables being put into it into a prepared query is straight forward. if you need, someone can post a list of instructions how to do this. you should use a get method form when determining what will be displayed on a page. this is so that if someone finds a result they want to return to or share with someone, they can bookmark the URL or share the URL and be able to return to the same result. the search form should be on the same page as the result and the form should be 'sticky' and repopulate the fields, selected options, checkboxes, and radiobuttons with any existing values so that if the search doesn't find what the user expects, they can simply make changes to the search values and try again. all the search form processing code should be inside the conditional statement testing if the form has been submitted. the current code will produce a bunch of php errors and likely produce no search result and output if the page is requested without any form data. you need to trim, mainly so that you can detect if all white-space characters were entered, then validate all input data before using it. the search inputs you have shown are all 'required'. if they are not all valid, you should output error messages stating what is wrong with them and NOT run any of the query/output code. if you want to make any of these search inputs 'optional' you will need to dynamically build the WHERE part of the query and only include the terms that have search values. the use of LEFT JOIN doesn't make sense (to me). it indicates that you want to get marks data that may not have any student or school associated with it. you should just use a JOIN if you only want marks data that has school/student data. if a query doesn't match any data, you should output a message stating so, rather than outputting nothing. you need to apply htmlentities() to dynamic values being output in a html context, right before/as they are being output in order to prevent any html entities in a value from being able to break the html syntax.
  25. this is the thead section - <thead> <tr class="text-center"> <th class="th-sm text-center">Subject </th> <th class="th-sm text-center">Class Score <br>(30%) </th> <th class="th-sm text-center">Exam Score <br>(70%) </th> <th class="th-sm text-center">Total <br>(100%) </th> <th class="th-sm text-center">Grade </th> <th class="th-sm text-center">Position </th> <th class="th-sm text-center">Remarks </th> </tr> </thead> it is the same for every student. your output is incorrect because the markup you are producing is broken. the code inside the loop is incorrect. the reason I posted an outline of what the code should do is to help you to be able to produce the correct output that will work. i recommend that you validate the resulting web page at validator.w3.org
×
×
  • 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.