Jump to content

mac_gyver

Staff Alumni
  • Posts

    5,510
  • Joined

  • Days Won

    185

Everything posted by mac_gyver

  1. if you do this - a majority of this code will go away. assuming i decoded what you are trying to produce as output. the following should be all the code that you need for the data table section - // pre-fetch the data, indexing/pivoting it using the station, then fuel as indexes $data = []; while ($row = sqlsrv_fetch_array($result)) { $data[$row['station']][$row['fuel']] = $row; } // produce the output ?> <table class = "main"> <tr class="main"><td></td> <?php // output the heading foreach($fuel as $fu) { echo "<td class = 'main'>$fu</td>"; } ?> <td class = "main">Atnaujinta</td></tr> <?php // output the data foreach($station as $st) { echo "<tr><td class='main'><a href='levelStation.php?station=$st'><b>$st</b></a></td>"; foreach($fuel as $fu) { if(empty($data[$st][$fu]['vol'])) { echo '<td>-</td>'; } else { $row = $data[$st][$fu]; $class = ''; if ($row['fmm']<=100) $class = 'class="low"'; if ($row['fmm']>100 AND $row['fmm']<250) $class = 'class="alert"'; if ($row['vmm']>=5) $class = 'class="water"'; $qs = []; $qs['station'] = $st; $qs['fuel'] = $fu; $qs['type'] = 'all'; $qs = http_build_query($qs); echo "<td $class><a href='levelFuel.php?$qs'>{$row['vol']}</a></td>"; } } echo "<td>".date_format(date_create($row['date']),"Y-m-d H:i:s")."</td></tr>\n"; } // output the totals ?> <tr><td>Iš viso:</td> <?php foreach($fuel as $fu) { $sum = 0; foreach($station as $st) { $sum += $data[$st][$fu]['vol']??0; } echo "<td class = 'main'>$sum</td>"; } ?> <td></td></tr> </table>
  2. the code is unconditionally looping over some number of $fuel choices and expects there to be corresponding data in $cellt. IF (a big if) the data in $cellt has gaps in the 1st index, then the code should be testing if $cellt[$k] isset() before referencing it. what does adding the the following, after the point where $cellt is being built, show - echo '<pre>'; print_r($cellt); echo '</pre>'; this code is apparently (hard to tell without all the actual code, sample data, and desired output) outputting data for each station (starts a new section when the station value changes) and each fuel type. the code is repetitive, because it must complete the previous section when a new section is detected, and it must also complete the last section at the end. you can greatly simplify all of this by pre-fetching the data into an array and indexing/pivoting it by first the station, then the fuel. to produce the output from the pre-fetched data then just takes a couple of loops, without repetition in the code or extra variables to detect when the station changes. you should also use associative index names for the fetched data, so you are not having to keep track of numbers. lastly, in the code building the links, the only thing that is different is the class='...' markup. this is the only thing that should be conditional. the rest of the markup is identical and should only exist once in the code - Don't Repeat Yourself (DRY.) build the class='...' markup in a php variable, then use that variable when building the single link. you should also build the query string key/values in an array, then use http_build_query() to produce the query sting for the link.
  3. you are getting a http 500 error because the code contains a php syntax error. you don't know this because you haven't put the php error related settings into the php.ini on your system, so that ALL php errors will get reported and displayed. when you put these settings into your code, they don't do anything for php syntax errors in that file since your php code never runs in this case to change those settings. the approximate point where the syntax error is occurring at can be seen since the color highlighting stops changing, both in your programming editor and in the forum post. if you always build sql query statements in a php variable, it helps prevent syntax errors like this by separating the sql query syntax as much as possible from the php code. you can also help prevent syntax errors like this by using a prepared query (which will also prevent sql special characters in a value from being able to break the sql query syntax) when supplying external, unknown, dynamic values to the query when they get executed, since you are only putting a simple ? prepared query place-holder into the sql syntax for each value.
  4. just trying different things, and throwing them away when they don't work is not learning. an analogy to the method you are trying to use, would be picking up a piece of a jigsaw puzzle, trying it in every possible location, without looking at what part of the picture it likely matches so that you are trying it in places it has a chance of fitting. this method takes 100 times longer, and sometimes never, to accomplish putting together the puzzle. writing code involves actually learning the meaning of the words and syntax you are using, so that you are writing (and reading) the programming language you are using. without this learning, you cannot debug code when it doesn't work, because you don't know what each statement contributes, and you also cannot write new code, building on what you have learned before, because no learning has occurred to serve as the basis for new learning. you must somehow make the transition from just copy/pasting words you have found to actually learning (internalizing) the meaning of the words, so that you can write meaningful code that does what you want. another reason to learn what the words actually mean and do, is because a large percentage of the code you will find posted on the internet is lacking in security, validation, and error handling. they may 'work' under perfect conditions, but they aren't secure, and when anything unexpected occurs, they won't tell you why they didn't work. here's an example from your original code that appears to work, but isn't actually doing what you think, that reading what the lines of code are doing would point out - $id=$_SESSION['id']; $fname=$_POST['fname']; $email=$_POST['email']; $select= "select * from users where id='$id'"; $sql = mysqli_query($conn,$select); $row = mysqli_fetch_assoc($sql); $res= $row['id']; if($res === $id) all the code on this web page 'requires' a logged in user for the form processing code to be executed or the form to be displayed. to accomplish this, your code must validate the session variable first, before using it, e.g. does it even exist. the code must also test if the query matched a row of data before using the fetched data. the above code, when the session variable doesn't exist ends up testing if null (the query will fail to match a row of data, resulting in $res being null) === null (the nonexistent session variable), which is true comparison, and allows anyone who isn't logged in to cause the UPDATE query to be executed. next, for any post method form processing code, you should not attempt to detect if the submit button is set. there are cases where it won't be. you should instead detect if a post method form was submitted. one of the cases where the submit button won't be set is if the size of the form data exceeds the post_max_size setting on the server. this can occur for any post method form, but is more likely to occur when uploading files, since the size of the uploaded file is out of your control. when this condition occurs, both the $_POST and $_FILES arrays will be empty. after detecting if a post method form was submitted, the code must detect if this condition exists, and setup an error message for the user, since there's no form data for the rest of the code to use. once your code has found that there is form data, you must test the ['error'] element in the $_FILES... array, which is why there's an error element to test. testing the ['name'] element is not enough. for some of the possible upload errors, there will be a valid ['name'] element, but the file upload has failed with whatever error is indicated in the ['error'] element.
  5. the error message confirms that the problem is as stated in the first paragraph of my reply. if you are getting an error about an - wouldn't the solution be to make it into a quoted associative index name, e.g. by adding quotes around it?
  6. the most likely thing that stopped the code from working are all the $_POST[unquoted associative index name here] in the main code (but not inside of overall double-quoted strings.) in the past, one of php's unfortunate choices assumed that if a defined constant by the given index name doesn't exist, the value was treated as a string. this no longer works and is a fatal run-time error. setting php's error_reporting to E_ALL and display_errors to ON, preferably in the php.ini on your system, will cause php to help you by reporting and displaying all the errors it detects. this code is insecure. by outputting the raw form data on the web page, in the emails, and saving it to a file/importing it into excel, any code in the values will allow cross site scripting. at a minimum, you need to apply htmlentities() to all the values when they are being output, to prevent any html, css, javascript, ... in them from being operated on. the code also has no validation of the input data before using it, could stand to be rewritten in an organized and simplified format, needs error handling and file-locking for the file operations, and needs the markup updated.
  7. or use BC (BCD - Binary Coded Decimal) math - https://www.php.net/manual/en/ref.bc.php
  8. perhaps if the OP posts the incorrect result and points out what is wrong with it, it would provide a clue as to the problem.
  9. the following is an example showing the code and queries needed to accomplish this task - <?php // initialization // these settings should be in the php.ini on your system - error_reporting(E_ALL); ini_set('display_errors', '1'); // Start the session session_start(); // fake a logged in user $_SESSION['user_id'] = 1; // insure the current visitor is logged in if(!isset($_SESSION['user_id'])) { // handle a non-logged in user here... header('location:index.php'); die; // stop code execution } // use exceptions for database statement errors and only handle the exception for user recoverable errors // based on the sql syntax error posted, you ARE using exceptions for database statement errors. do yourself a favor and remove all the existing database error handling logic since it is no longer being used and is just cluttering up your code. require 'pdo_connection.php'; $post = []; // array to hold a trimmed working copy of the form data $errors = []; // array to hold user/validation errors // post method form processing if($_SERVER['REQUEST_METHOD'] === 'POST') { // input(s) - gname, this should be the selected user's id - e.g. gid or similar // trim all the input data at once $post = array_map('trim',$_POST); // if any input is an array, use a recursive trim call-back function here instead of php's trim // validate the input data // the selected user's id if($post['gid'] === '') { $errors['gid'] = 'You must select a user'; } else if($post['gid'] == $_SESSION['user_id']) { $errors['gid'] = 'You cannot select yourself'; } else { // find if the selected user exists $sql = "SELECT COUNT(*) FROM users WHERE id=?"; $stmt=$pdo->prepare($sql); $stmt->execute([ $post['gid'] ]); if(!$stmt->fetchColumn()) { // if you see this error, it is either due to a programming mistake or someone submitting data values that are not from your code $errors['gid'] = 'The selected user does not exist'; } } // if no errors, use the data if(empty($errors)) { // since it is doubtful the OP will change what they are doing, the following updates the value in the token column // start transaction $pdo->beginTransaction(); // subtract 1 token from the current user, if they have enough tokens $sql = "UPDATE users SET token=token-1 WHERE token > 0 AND id=?"; $stmt=$pdo->prepare($sql); $stmt->execute([ $_SESSION['user_id'] ]); if($stmt->rowCount()) { // the UPDATE query affected the row, token was > 0 // add 1 token to the recipient user $sql = "UPDATE users SET token=token+1 WHERE id=?"; $stmt=$pdo->prepare($sql); $stmt->execute([ $post['gid'] ]); } else { // the UPDATE query didn't affect the row, token is not > 0 $errors['token'] = "You don't have enough tokens"; } // if you are here, no database errors/exceptions occurred, commit the transaction $pdo->commit(); } // if no errors, success if(empty($errors)) { $_SESSION['success_message'] = "You have successfully gifted a token"; die(header("Refresh:0")); } } // get method business logic - get/produce data needed to display the page $sql = "SELECT id, username FROM users ORDER BY username"; $stmt = $pdo->query($sql); $all_user_data = $stmt->fetchAll(); // html document starts here... ?> <?php // test for, display, and clear any success message if(!empty($_SESSION['success_message'])) { echo "<p>{$_SESSION['success_message']}</p>"; unset($_SESSION['success_message']); } ?> <?php // test for and display any errors if(!empty($errors)) { echo '<p>'.implode('<br>',$errors).'</p>'; } ?> <?php // display the form, repopulating form fields using any data in $post ?> <form method='post'> <select name='gid'> <option value=''>Select a user</option> <option value='234'>An invalid user</option> <?php foreach($all_user_data as $row) { $sel = isset($post['gid']) && $post['gid'] == $row['id'] ? 'selected' : ''; echo "<option value='{$row['id']}' $sel>{$row['username']}</option>"; } ?> </select><br> <input type='submit'> </form> this code renamed the session variable, because many things have 'id's, what exactly is the id stored in the session? uses the much simpler and more modern PDO database extension.
  10. the logged in person is known from the $_SESSION['id'] variable, which your code should validate before using, i.e. this page requires a logged in user for it to do anything, and your code should test to make sure that the current visitor is logged in. the form should submit just the id of the selected recipient. any data that you store should use the user ids, not the name/username. this will result in the least about of storage and the fastest queries. why are you making 3 different database connections? if these databases are on the same server, make one connection, then just specify the database name in the query. you should be using exceptions for database statement errors and only catch and handle the exception for user recoverable errors, such as when inserting/updating duplicate or out or range user submitted data. in all other cases simply let php catch and handle the exception, where php will use its error related settings to control what happens with the actual error information (database statement errors will 'automatically' get displayed/logged the same as php errors.) you can then eliminate the existing error handling logic, since it will no linger get executed upon an error, simplifying the code. note: in the latest php versions, a mysqli connection error always throws and exception, so that the existing error handling logic you have won't ever be executed upon an error. use a prepared query when supplying external, unknown, dynamic values to a query when it gets executed. this simplifies the sql query syntax, provides protection for all data types, not just strings, and if you switch to the much simpler and more modern PDO database extension, simplifies the php code. don't copy variables to other variables for nothing, just use the original variables. this is just a waste of time typing. you should NOT maintain a single number in a column to keep track of the number of tokens. this does not provide an audit trail that would let you detect if a programming mistake, accidental key press/button click, or nefarious activity cause the value to change. you should instead insert a row of data for each transaction that affects a value. to get the current amount, just sum() the quantity from all the rows of data belonging to the current user. don't bother closing database connections in your code since php will automatically destroy all resources when your script ends. your post method form processing code should - detect if a post method from was submitted. keep the form data as a set in an array variable, then reference elements in this array variable throughout the rest of the code. trim all the input data at once. after you do item #2 on this list, you can accomplish this with one single line of code. validate all inputs, storing user/validation errors in an array using the field name as the array index. after the end of the validation logic, if there are no errors (the array will be empty), use the form data. if after using the form data (which could result in more errors), if there are no errors, redirect to the exact same url of the current page to cause a get request for the page. if you want to display a one-time success message, store it in a session variable, then test, display, and clear that session variable at the appropriate location in the html document. if there are errors at step #5 or #6, the code will continue on to display the html document, where you would test and display any user/validation errors, and re-display the form, repopulating form fields with the submitted form data. any dynamic value that you output in a html context should have htmlentities() applied to help prevent cross site scripting.
  11. the WHERE clause in the UPDATE query does not identify a single row. the UPDATE query is repeatedly updating all the rows matching the class, term, and year value with the new data, so it first updates all three rows with the first row of data, the second row of data, then the third, leaving all three rows with the third/last set of data in them. when a row of data should be updated, what columns can contain new values and what columns identify the row of data? note: you won't include the columns that are in the WHERE clause in the SET ... list, because by definition, they won't have different values in them, because they are what identifies the row data. also, don't use columns that end in numerical sequences. this indicates that you are trying to threat the database as a spreadsheet, which will result in overly complicated code and queries to accomplish any task. your database design should have one row for each data item. you would have a (one) subject column and a (one) test score column. you would insert a separate row for each test/test score. such data would also have a datetime column that indicates when the test/test score occurred.
  12. the existence or absence of a session is under the control of the client/script making the requests to your site. you cannot use session (or cookie) data to detect or control the login attempts, since the client/script can simply not propagate the session id (or cookie) between requests and they will get a new session. you must store the data needed to detect or control the login attempts in a database table. you have two pieces of identifying information from the requests, the ip address (where the request came from and where you will send the response back to, along with any session id cookie or remember me cookie token) and the username/email for the login attempt. you would store the datetime, ip, and username/email for each failed login attempt, as a separate row, in a database table. it is this data that you would test to detect and control the login attempts. also, you don't 'lock' the accounts, you rate limit the login attempts. if a user is already logged in, they should still be able to access the site, i.e. they are won't be attempting to login, since they already are logged in.
  13. this is a sign that your php code isn't being executed, but is instead being output to the browser, where the browser is only 'rendering' the quoted string. what does the 'view source' in your browser show?
  14. there's nothing wrong with the POSTED code (just tested.) errors like this are usually caused by copy/pasting code that's been published on the web, with smart/curly quotes, which then produce php errors since those type of characters have no meaning in php, but which get converted back to straight quotes when code gets posted on a programming help forum, and therefor work when tried. delete and re-type the line of code.
  15. what output do you get, e.g. item #4 on my list? do you have php's error_reporting set to E_ALL and display_errors set to ON, in the php.ini on your system, so that php will help you by reporting and displaying ALL the errors it detects? stop and start your web server to get any changes made to the php.ini to take effect and check using a phpinfo(); statement in a .php script that the settings actually got changed to those values.
  16. Php 101 - php is a server-side scripting language. do you have a web server with php installed? the php file must be placed in the web server's document root folder, which may have different paths/names depending on what operating system is in use and how you obtained and installed the web server/php. to run a php script, you must make a http(s) request to the web server. what URL did you use in your browser to request the file? it should be something like - http://localhost/1.php (for a localhost development system.) if is starts with file:///..., that's not a URL, that's a filesystem path, which means that you opened the .php file directly in the browser, which won't invoke the php language engine that's installed on the web server. if you made a http(s) request to a URL and got a blank page, what does the 'view source' of the page in your browser show? you can also check in your browser's developer tools, network tab to see what the response is.
  17. at one per second, it will take 25 minutes to send all the emails. php scripts are not intended to run continuously. you would need to call set_time_limit(...) inside the loop to keep the script from fatally timing out and halting, but not using set_time_limit(0) so as to not prevent the script from stopping due to a programming mistake. this is normally done by queuing, in a database table, all the mail addresses to be sent to. having a cron job/scheduled task that runs at some reasonable interval, such as once a minute. the code that the cron job triggers checks if the queue has any unsent messages in it, loops, with a sleep() call inside the loop, to send fewer emails than the time to the next execution of the cron job, to prevent overlap, and marks each email in the queue as having been sent. e.g. with the datetime when it was sent. doing this, you would send ~50 email per minute, in 30 executions of the cron job.
  18. you would have been getting php errors at the reference to the connection variable. php's error_reporting should always be set to E_ALL. when learning, developing, and debugging code/query(ies), display_errors should be set to ON. when on a live/public server, display_errors should be set to OFF, and log_errors should be set to ON.
  19. what output are you getting on the web page? if it's a blank page, what does the 'view source' in your browser show? can you echo a string using php code? is your code doing any redirects that could discard any output from the web page if php's output_buffering is ON? 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? stop and start your web server to get any changes made to the php.ini to take effect and check that the settings actually got changed to those values by using a phpinfo(); statement in a .php script file. do you have error handling for all the database statements that can fail - connection, query, prepare, execute, and a few others? the simplest way of adding error handling, without adding conditional logic at each statement, is to use exceptions for errors and in most cases simply let php catch and handle the exception, where php will use its error related settings (see the previous paragraph above) to control what happens with the actual error information (database statement errors will 'automatically' get displayed/logged the same as php errors.) to enable exceptions for errors for the mysqli extension, add the following line of code before the point where you make the database connection - mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
  20. almost none of that is what i wrote, and you must echo the id in the field array index for it to be output (check the view source of the output in your browser.) see the following example (uses made up checkbox data instead of sql query data) - // for debugging, examine the input data echo '<pre>'; print_r($_POST); echo '</pre>'; // post method form processing if($_SERVER['REQUEST_METHOD']==='POST') { // test if any checkbox is checked if(isset($_POST['weekday'])) { // get and loop over the checked checkbox ids foreach(array_keys($_POST['weekday']) as $id) { // access the timing field value echo "Weekday id: $id, Timing: {$_POST['timing'][$id]}<br>"; } } } // make up some checkbox data $days = []; $days[] = ['id'=>1,'name'=>'Monday']; $days[] = ['id'=>2,'name'=>'Tuesday']; $days[] = ['id'=>3,'name'=>'Wednesday']; $days[] = ['id'=>4,'name'=>'Thursday']; $days[] = ['id'=>5,'name'=>'Friday']; ?> <form method='post'> <button type='submit'>Submit</button><br> <?php foreach($days as $row) { $chk = isset($_POST['weekday'][$row['id']]) ? 'checked' : ''; ?> <input name="weekday[<?=$row['id']?>]" type="checkbox" <?=$chk?> class='weekday'> <?=$row['name']?> <br>Timing<br> <input type="text" name="timing[<?=$row['id']?>]" value="<?=$_POST['timing'][$row['id']]??''?>" class='timepicker'><br> <?php } ?> </form>
  21. only checked checkboxes will be set. if no checkboxes are checked, $_POST['weekday'] won't be set and any reference to it will produce a php error. you must test if $_POST['weekday'] isset() before referencing it. next, to associate each timing[] field to the corresponding weekday[] field, you should use the id as the array index for both fields, and forget about using a value attribute for the checkboxes. after you have determined that $_POST['weekday'] isset(), you can get the ids/keys (see php's array_keys()), then loop over the ids and access the corresponding timing[] field values.
  22. 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 would help you by telling you why the setcookie() call is failing?
  23. just because code produces the expected result under perfect conditions, doesn't mean that the code is finished and ready to be used. this code will fall apart when it has to deal with real-world inputs. this code needs to be completely rewritten to make it secure, provide a good user experience, to eliminate all the unnecessary variables, and to add useful validation logic and error handling, so that the code will either work or it will tell you why it doesn't.
  24. this code always produced the list of posted undefined errors, but they were hidden due to php's error related settings not setup so that ALL php detected errors would be reported and displayed. basically, this code was developed on a system where php wasn't setup to help the developer write good code. the solution is to find and fix what's causing each error. for the first add-task error in this line - if ($_POST['add-task']) {. the generally correct way of detecting which of several post method forms has been submitted is to use a hidden form field, with a unique value in it that you can test and use to control what form processing code to execute. the post method form processing for the add-task, is not secure (none of the database code is), has no validation logic, is filled with copying of variables to other variables for nothing, is filled without verbose variable names, shouldn't unconditionally output raw database statement errors onto a web page, doesn't have any exit/die statement to stop php code execution, and should redirect to the exact same url of the current page upon successful completion.
  25. the following appendices list the major changes to php - https://www.php.net/manual/en/appendices.php you will need to go through and make sure that your code isn't using any backward incompatible or removed features. the error you posted above has nothing to do with php version. it's due to output being sent prior to the session_start statement. correcting it would involve finding what the output is and eliminating it and/or organizing your code so that the session_start occurs before any output. if you want anyone here to help with your code, you will need to post it.
×
×
  • 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.