-
Posts
5,527 -
Joined
-
Days Won
188
Everything posted by mac_gyver
-
that's because the current code is looping over the collection of class = s elements, and setting them all to the data that is returned - $(".s").each(function(k,v) { $(".s").html(data); //Populates the Standard drop-down having class .s with the data from the Standard function } ); you need to 'find' the correct class = s element and set it to the data that is returned. take a look at the jquery .parent() method to find a common parent container that all the related form fields are in, then use the jquery .find() method to find the element with class = s.
-
the most immediate problem is that the onChange code for the Student select/option menu needs to get the correct sid value. by using $(".i") you are getting a collection of all the class = i elements, not the current one. using $(this) should work (all suggestions are untested unless indicated otherwise.) next, requiring the user to select each student from a select/option menu is a poor User Interface (UI) and provides a bad User eXperience (UX). you should simply list out each Student, the Standard select/option menu with any existing choice pre-selected, and the Attendance select/option menu with the Present choice pre-selected (the most common case.) the user should only need to make the fewest number of changes to the choices and submit the form, so, only make any Standard changes and select which students are Absent.
-
here's a tested example showing the suggested method - <?php // fake a request start and end date - 1st May 2025 to 8th May 2025 $start_date = "2025-05-01"; $end_date = "2025-05-08"; // exclude check-out date from length of stay/pricing $end = new DateTime($end_date); $end = $end->modify( '-1 day' ); $end_date = $end->format("Y-m-d"); // define default weekday and weekend prices $default_price = []; $default_price['wd'] = (object)['name'=>'Standard Weekday','price'=>'60']; $default_price['we'] = (object)['name'=>'Standard Weekend','price'=>'80']; // define seasonal prices $seasonPrices = []; $seasonPrices[] = (object)["SeasonName"=>"Spring half-term", "SeasonStart"=>'2025-02-21', "SeasonEnd"=>'2025-03-03', "SeasonPrice"=>'100']; $seasonPrices[] = (object)["SeasonName"=>"Easter", "SeasonStart"=>'2025-04-11', "SeasonEnd"=>'2025-04-27', "SeasonPrice"=>'100']; $seasonPrices[] = (object)["SeasonName"=>"May Day", "SeasonStart"=>'2025-05-02', "SeasonEnd"=>'2025-05-05', "SeasonPrice"=>'110']; $seasonPrices[] = (object)["SeasonName"=>"Summer half-term", "SeasonStart"=>'2025-05-23', "SeasonEnd"=>'2025-06-01', "SeasonPrice"=>'110']; $seasonPrices[] = (object)["SeasonName"=>"Summer", "SeasonStart"=>'2025-07-18', "SeasonEnd"=>'2025-09-01', "SeasonPrice"=>'120']; $seasonPrices[] = (object)["SeasonName"=>"Autumn half-term", "SeasonStart"=>'2025-10-24', "SeasonEnd"=>'2025-11-02', "SeasonPrice"=>'110']; $seasonPrices[] = (object)["SeasonName"=>"Christmas", "SeasonStart"=>'2025-12-19', "SeasonEnd"=>'2026-01-04', "SeasonPrice"=>'120']; // start by creating an array of request dates filled with the default weekday price $request = array_fill_keys(Cal::bookedArray($start_date, $end_date), $default_price['wd']->price); // get the weekend prices between the request start and end dates $weekend_prices = get_we_prices($start_date,$end_date,$default_price); // put the weekend prices into the array $request = array_replace($request,$weekend_prices); // get the seasonal prices between the request start and end dates $season_prices = get_prices($start_date,$end_date,$seasonPrices); // put the seasonal prices into the array $request = array_replace($request,$season_prices); // examine the result echo '<pre>'; print_r($request); echo '</pre>'; echo "Total: " . array_sum($request); // get the weekend prices between the request start and end dates function get_we_prices($start_date,$end_date,$default_price) { $dates = []; // find 1st Sat of the start date $date = date('Y-m-d',strtotime("first sat of $start_date")); // generate all the Saturdays between the start and end dates $start = new DateTime($date); $end = new DateTime($end_date); $end = $end->modify( '+1 day' ); // include the end point $interval = new DateInterval('P7D'); // 7 days $daterange = new DatePeriod($start, $interval ,$end); foreach($daterange as $date){ $dates[$date->format("Y-m-d")] = $default_price['we']->price; } // same as above but for Sundays // find 1st Sun of the start date $date = date('Y-m-d',strtotime("first sun of $start_date")); // generate all the Sundays between the start and end dates $start = new DateTime($date); $end = new DateTime($end_date); $end = $end->modify( '+1 day' ); // include the end point $interval = new DateInterval('P7D'); // 7 days $daterange = new DatePeriod($start, $interval ,$end); foreach($daterange as $date){ $dates[$date->format("Y-m-d")] = $default_price['we']->price; } return $dates; } // get the seasonal prices between the request start and end dates function get_prices($start,$end,$seasonPrices) { $result = []; foreach($seasonPrices as $row) { // keep entries that match the requested start/end // SeasonEnd >= start AND end >= SeasonStart if($row->SeasonEnd >= $start && $end >= $row->SeasonStart) { // expand this entry and only keep the values between the start and end (for the case of spanning the start or end date) $entry = Cal::bookedArray($row->SeasonStart, $row->SeasonEnd); foreach($entry as $date) { // if date between start and end, keep it if($start <= $date && $date <= $end) { $result[$date] = $row->SeasonPrice; } } } } return $result; } class cal { // produce a date range from start to end public static function bookedArray($start,$end) { $start = new DateTime($start); $end = new DateTime($end); $end = $end->modify( '+1 day' ); // include the end point $interval = new DateInterval('P1D'); // 1 day $daterange = new DatePeriod($start, $interval ,$end); $dates = array(); foreach($daterange as $date){ $dates[] = $date->format("Y-m-d"); } return $dates; } }
-
you are constantly changing data types, names, and adding features. this makes writing code extremely wasteful. you need to define everything possible, before you write any code. you also need to define what inputs you have for any operation, what processing you are going to do based on those inputs, and what result or output you are going to produce. as to a simple, straightforward solution, i recommend that you read the suggestions in the previous thread, about building an array with the dates as the array index and the values being whatever you are trying to produce. in that thread, the array was for the special events for the calendar being displayed. in this thread, the array is for the requested date range and the price for each day in that range. the inputs to this code are the start and end dates of the request, the standard week day and week end prices, and the seasonal pricing. you would start by creating an array using the request range of dates as the array index. you would fill in the array with the week day and week end prices. you would then replace any price that matches the seasonal pricing data. when you are done, you will have an array with all the days of the request as the index, and the price for each day. you can then just sum the prices to get the total. here's a procedural function that gets the seasonal prices, given the request start and end date - // get seasonal prices between start and end date function get_prices($start,$end,$seasonPrices) { $result = []; foreach($seasonPrices as $row) { // keep entries that match the requested start/end // SeasonEnd >= start AND end >= SeasonStart if($row->SeasonEnd >= $start && $end >= $row->SeasonStart) { // expand this entry and only keep the values between the start and end (for the case of spanning the start or end date) $entry = Cal::bookedArray($row->SeasonStart, $row->SeasonEnd); foreach($entry as $date) { // if date between start and end, keep it if($start <= $date && $date <= $end) { $result[$date] = $row->SeasonPrice; } } } } return $result; } you can use array_replace() with the array you are building and the array returned by the above function to replace the standard prices in that array with the seasonal prices.
-
for the posted information, the requested date range of 2025-05-06 to 2025-05-22 doesn't match any of the $seasonPrices data. It starts one day after the end of the May Day range and ends one day before the start of the Summer half-term range. it should use the base/default price for every day. since you are using a standard date format, you can directly perform date comparisons by order, as mentioned in the previous thread. you can directly compare a date to the $seasonPrices SeasonStart and SeasonEnd values to find if it is between a date range. i would write a function/class-method that accepts a date input, loops over the $seasonPrices data, returns the first price that is between the SeasonStart and SeasonEnd values, or returns zero (or some other easily detected value) if it reaches the end without finding a match. as a procedural function, something like - function get_price($date,$seasonPrices) { foreach($seasonPrices as $row) { // date between start and end if($row->SeasonStart <= $date && $date <= $row->SeasonEnd) { return $row->SeasonPrice; } } // no match return 0; }
-
what exactly is the single $booked data for vs the array of $bookings? i have the following recommendations - use a standard yyyy-mm-dd date format. if/when you store the data in a database, this will be necessary to allow queries to compare dates by order. it will also make your current code easier to understand. the bookings data should be stored in a database table. you should have a start_date and an end_date input to the code on this page, so that the code will work for any date range, from multiple years down to a single month. you are looping over the $res array for every date being displayed, currently for the whole year. i recommend that you instead produce an array using the date as the array index, and the stored value indicating what is occurring on that date, limited to be between the start_date and end_date mentioned above. as you are producing the output, you can simply test, no loop required, if there is an entry in this array, using isset(), then get the stored value if there is one, and use it to control what you output for the date. with a little conditional logic, you don't need separate logic to deal with the first (partial) week, then repeat that logic for the remainder of each month. if you use php's short-open-print tag and leave out the ; right before a closing tag, you can use simple syntax like - <?=$some_var?> to output values in the markup. use php's DateInterval and DatePeriod to expand the booking date ranges. here's example code for item #7 - $start = new DateTime($start); $end = new DateTime($end); $end = $end->modify('+1 day'); // include the end point $interval = new DateInterval('P1D'); // 1 day $daterange = new DatePeriod($start, $interval ,$end); $dates = array(); foreach($daterange as $date){ $dates[] = $date->format("Y-m-d"); }
-
send email with phpmailer not using smtp issue
mac_gyver replied to ianhaney10's topic in PHP Coding Help
this is a 'contact us' form. for the client to be able to receive and read the emails, they must be sent to an email address that the client has access to. is this To: address at their web hosting (mail_box_name@their_doman_name) or somewhere else, such as a gmail address ([email protected])? i didn't find any information about using unauthenticated smtp at hostgator, but if this is possible, it would require an email account to be created within cpanel for the domain name that's hosted at hostgator, then this email address would be used as the From: address. the To: address can then be anywhere, even the same as the From: address. everything I saw about hostgator email used smtp authentication, which needs an email account to be created within cpanel for the domain name hosted at hostgator, with the password known. if they have an email address at their domain name, but the password is not known, it needs to be reset to a known value within cpanel. for php to be able to send to (the From: and To: addresses would be the same and be the email account at hostgator) or through (the From: address would be the email account at hostgator and the To: can be anywhere) the mail server at hostgator, you would use the hostgator server settings. see the cPanel Emails, Outgoing Email Settings at this link - https://www.hostgator.com/help/article/email-connection-settings#cpanelemails you can, using the phpmailer/swiftmailer class, send an email to or through an external mail server, such as gmail, but this requires the username/password of the account on that external mail server. -
send email with phpmailer not using smtp issue
mac_gyver replied to ianhaney10's topic in PHP Coding Help
the php mail() function and the phpmailer/swiftmailer classes allow php to act like an email client, to send an email to a mail server. when you don't use smtp authentication against a mail box on that mail server, that mail server must be configured to "trust" the (ip address of the) web server where the php code is running. typically, a local mail server at web hosting is configured this way. if you are not getting any errors back, it is likely that the locally configured mail server is setup to silently accept emails, regardless of it it intends to send them, without returning an error. where are you running this php code at? a localhost development system or web hosting, and if on web hosting is the domain name in the From: address hosted at the sending web server or is it hosted at some other location? -
telling us that something doesn't work is pointless. we are not sitting next to you and didn't see what symptom or error you got that leads you to believe something didn't work. you must tell or show us what result you got and what the expected result should be. 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, so that php will help you by reporting and displaying all the errors it detects? have you checked in the browser's developer tools, console tab for errors? you should use 'require' for things your code must have. require/include are not functions. the () around the path/filename do nothing and should be removed. $_GET['email'] is an input to your code. it may not exist. you need to use isset() to prevent errors when it doesn't exist and you must trim, then validate it before using it, when it does exist. the two session variables are also inputs to your code. they may not exist. you need to use isset() to prevent errors when they don't exist.
-
Invalid password when using password_verify
mac_gyver replied to rwahdan1978's topic in PHP Coding Help
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. -
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.
-
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.
-
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.
-
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.
-
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.
-
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.
- 1 reply
-
- 1
-
-
if you post the code generating the array, someone could post an example, instead of just writing about how to do it.
-
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.
-
failed to search using preg_match in a query php in html form
mac_gyver replied to admien's topic in PHP Coding Help
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.- 1 reply
-
- 1
-
-
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.
-
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
-
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.
-
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.
-
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?
- 1 reply
-
- 1
-