Jump to content

mac_gyver

Staff Alumni
  • Posts

    5,459
  • Joined

  • Days Won

    177

Community Answers

  1. mac_gyver's post in MySQL UPDATE changes all rows instead of WHERE was marked as the answer   
    when i tried your code, $headerData being used when the query is executed is the full 'Battery-0975GJ' value. this is a string, not an integer. you are casting it as an integer in the bind_param("si" usage, resulting in a zero for a value. in sql queries, when one parameter in a comparison is a number, the other parameter is converted to a number as well. you are getting WHERE 0 = 0 which is matching every row.
     
     
  2. mac_gyver's post in I need help with this PHP issues. was marked as the answer   
    if you were doing this for real, where the price can change over time, the pricing would be stored in a related table, associated back to the token rows through the token's id, with a token_id, price, and effective start and effective end datetime columns.
    the point of the id column in this table is to assign a token id (auto-increment integer primary index), that would be stored in any related data table. this is the value that the form would submit for the selected token and would be stored in the usertoken table, not the token name.
    the balance is a derived value. you would not maintain the balance as a single value in a column, but would instead calculate it when needed. to do so, you need an account(ing) table, with a separate row inserted for each deposit/withdrawal that affects the account balance. also, the full name should be stored, using two columns, e.g. first_name, and last_name, so that you can uniquely distinguish between and search for people by name, e.g. is someone Ross Martian or Martian Ross?
    the account(ing) and usertoken table would use the id value from the users table, to related any stored data back to the correct user.
    this table should contain all the who, what, when, where, and why information about the purchase. the who would be the user_id of the buyer. the what would be the token_id, quantity, and purchase price (if you have a separate table for the pricing, you don't need this value). the when would be the datetime of the purchase. the where would only apply if there's a location associated with the purchase. the why would be a status/type value or memo field describing the reason for the purchase.
    this table doesn't need the account number, as that is defined in the users table and is known based on the user id. also, the totalbuy is a derived value that isn't stored. it is calculated when needed using the quantity and the purchase price (or the separately stored price at the datetime of the purchase.)
    the discount amount should be calculated and inserted as a separate row, in a related discount/interest accounting table, related back to the usertoken through the id in the usertoken table.
    you must do this as a single 'atomic' operation, in one query. the way to do this is use the query technique shown in this thread -  https://forums.phpfreaks.com/topic/315532-avoid-appointment-conflict where you have an INSERT ... SELECT query that will only insert a new row in the usertoken table if the where clause calculates if the user's current balance - by summing the user's accounting rows, discount/interest rows, minus the user's existing token purchase amounts, is greater then or equal to the total amount of the submitted purchase.
    and just to clarify, the only two values submitted from the form should be the selected token id and the quantity. everything else should use values that only exist on the server.
     
  3. mac_gyver's post in I want to update an employee profile as an admin but it not update and shows a warning in the placeholder for the unique id was marked as the answer   
    you are using a post method form, followed by an unnecessary redirect, to select which record to edit and then a get method form for updating the data. this is backwards. you should use get inputs to determine what will be displayed on a page and a post method form when performing an action on the server, such as updating the data. also, you can and should do all of this on one page to avoid repetition of code.
    the code for any page should be laid out in this general order -
    initialization post method form processing get method business logic - get/produce data needed to display the page html document when you display the existing records, the edit button should be a get method link with the id as part of the link. when you click one of those links, the resulting code that gets executed would query to get the  existing row of data to populate the form field values, but only if the update form has never been submitted. if the update form has been submitted, you would not execute this query. the way to accomplish this 'interlocking' of the data being edited is to use an internal 'working' array variable to hold this data, then use elements in this array variable through out the rest of the code. inside the post method form processing logic, you would store a trimmed copy of the $_POST form data in this variable. at the point of querying for the initial data, if this variable is empty, you would execute the query.
    here are some issues with and things that will simplify the posted code -
    your login system should only store the user id in the session variable upon successful login, then query on each page request to get any other user information, such as the user's name, permissions. your code should check if the current logged in user is an admin before allowing access to the edit logic. when conditional 'fail' code is much shorter than the 'success' code, if you invert the condition being tested and put the fail code first, it results in clearer, cleaner code. also, since the fail code is a redirect in this case, which must have an exit/die statement to stop php code execution, you can eliminate the else {} part of the conditional test since the redirect/exit/die will stop the execution for a non-logged in user. don't copy variables to other variables for nothing. this is just a waste of typing and introduces errors. don't use multiple names for the same piece of data. whatever the actual meaning of the data is, use that name throughout the code. one such example is the staff_id value being called 'data' and at another point it is a name value. since you will be switching to use a post method form for the update operation, after you detect if a post method form has been submitted, all the form fields (except for unchecked checkbox/radio fields) will be set. there will be no need for a massive list of isset() statements. you should put the database connection code in a separate .php file, then require it when needed. you should not unconditionally echo database errors onto the web page, which will only help hackers when they internationally trigger errors. instead, use exceptions for database statement errors an in most cases let php catch and handle the exception. the exception to this rule is when inserting/updating user submitted data that can result in duplicate or out of range values, which is something that you are doing. in this case, your code should catch the exception, test if the error number is for something that your code is designed to handle, and setup a message letting the user 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. the logout operation should use a post method form. any function definitions should either be in the initialization section of code or be in their own .php files that get required in the initialization section of code. your application should not use the root user without any password. instead, create a specific database user with a password with only the  permissions that it needs for you application. the updateRecord function should only have two call-time parameters. an array of the input data and the database connection. the updateRecord should not contain any application specific html markup. this should be handled in the calling code. the function should only return a true or false value to the calling code. don't put external, unknown, dynamic values directly into sql query statements. you must protect against sql special characters in data values from being able to break the sql syntax, which is how sql injection is accomplished. the fool-proof way of doing this is to use prepared queries. since the mysqli extension's prepared query interface is overly complicated and inconsistent, this would be a good time to switch to the more modern and simple PDO database extension. the updateRecord function should not close the database connection. it is not the responsibility of this function to do this, only to update the recorded. the update form should populate the form field values and preselect the option that matches the initial existing data being edited, then populate/preselect using the submitted form data, as described above. any dynamic value that you output on a web page should have htmlentities() applied to it to help prevent cross site scripting. the value attribute for the select/option 1st prompt option should be an empty string. since you are putting the <label></label> tags around the form field they belong with, you don't need the for='...' and matching id='...' attributes. the post method form processing code should -
    detect if a post method form was submitted. keep the form data as a set in an array variable. trim all the input data as at once. after you do item #2 on this list, you can do this with one php statement. validate all the inputs, storing validation errors in an array using the field name as the array index. after the end of all the validation logic, if there are no errors, use the form data. after using the form data, 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 the session variable at the appropriate location in the html document. if there are errors at step #5 or #6 on this list, the code would continue on to display the html document, where you would test for and display any errors, and redisplay the form, repopulating the field values/selected option choices with the values that are in the 'working' array variable holding the submitted form data.
  4. mac_gyver's post in loop multidimensional array was marked as the answer   
    foreach(array_keys($matches[1]) as $key) { echo "SKU number {$matches[1][$key]} costs {$matches[2][$key]}<br>"; }  
  5. mac_gyver's post in PHP Loop: API with max queries was marked as the answer   
    $sku = array( '1234', '5678', '4444', '2222', '9393', '1111', '8689' ); foreach(array_chunk($sku,5) as $chunk) { $qs = '&SKU=' . implode('&SKU=',$chunk); // examine the result echo $qs . '<br>'; }  
  6. mac_gyver's post in about using variables in a query was marked as the answer   
    the main point of using a prepared query, e.g. with place-holders in the sql statement where the data values are to be acted upon, then supply the actual data values when the query is executed, is to prevent any sql special characters in a data value from being able to break the sql query syntax, which is how sql injection is accomplished, by separating the parsing of the sql query syntax from the evaluation of the data values. a secondary point is they provide a performance gain (~5%) in the rare cases when you execute the same query within one instance of your script with different data values, since the sql query statement is only sent to the database server once, where it is parsed and its execution is planned only once.
  7. mac_gyver's post in Php and javascript with mysql copy button was marked as the answer   
    in general, functions should accept input data as call-time parameter(s), so that they can be reused with different input values.
    start by dynamically building the id attribute, incorporating the $row['id'] value (note: you can put php variables directly into an overall double-quoted string without all the extra quotes and concatenation dots) -
    id='c_{$row['id']}' dynamically build the function call with the same value as its call-time parameter -
    <button onclick=\"myFunction('c_{$row['id']}')\">Copy</button> modify the function definition to use the call-time parameter as the id of the element to reference -
    function myFunction(id) { // Get the text field var copyText = document.getElementById(id); .. the rest of the function code is the same  
  8. mac_gyver's post in Mysql question was marked as the answer   
    php variables are not replaced with their value unless the string they are inside of uses initial/final double-quotes. also, when you have just a variable, e.g. the $dbuser and $dbpass, don't put quotes around it/them at all.
    several of the things you have posted should have been producing php errors. 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?
    the PDO extension is much simpler, more consistent, and more modern than the mysqli extension. if you are just starting out, forget about the mysqli extension.
    when you make the PDO connection, you should name the variable holding the connection as to what it is, such as $pdo. you should also set the character set to match your database tables, set the error mode to use exceptions, set emulated prepared queries to false, and set the default fetch mode to assoc.
    don't bother catching any database exception unless it is for something that the user to your site can recover from, such as when inserting/updating duplicate or out of range data. in all other cases, simply let php catch and handle any database exception, i.e. don't put any try/catch logic in your code.
    you should always list out the columns you are SELECTing in a query and build the sql query statement in a php variable.
    this is obsolete markup. use css instead. you should validate your resulting web pages at validator.w3.org
    don't copy variables to other variables for nothing. this is just a waste of typing. just use the original variables.
    in most cases, there's no need to free result sets, free prepared query handles, or close database connections, since php will destroy these when your script ends.
     
  9. mac_gyver's post in DIfferent class if first row was marked as the answer   
    // before the start of the loop, set a variable to the unique/one-time output you want. $first = 'class="active"'; while($row = mysqli_fetch_array($result)) { // echo that variable at the point where you want the output ?> <li><a id="<?php echo $row["urlName"] ?>Tab" <?=$first?> href="#<?php echo $row["urlName"] ?>Content"><?php echo $row["title"] ?></a></li> <?php // then set that variable to an empty string after the point where you echo it. every pass through the loop after that point will echo an empty string, i.e. nothing will be output. $first = ''; }  
  10. mac_gyver's post in Update Price based on Quantity Selected was marked as the answer   
    <script> const format = (num) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(num); </script> replace $('#totalPrice').text(totalPrice); with $('#totalPrice').text(format(totalPrice));
  11. mac_gyver's post in Not connecting to MySql database using $CONN in attempting to set up ElementorPro CRUD was marked as the answer   
    you should be learning, developing, and debugging your code/queries on a localhost development system. trying to use public/online hosting is a waste of time, constantly uploading, and making sure there were no upload errors, to see the result of each change. until your code is secure, this opens the possibility of your web hosting getting abused by hackers. also, most cheap shared web hosts disable things like php's error related settings and database error settings that you need in order to get php and your database statements to help you. they also set disk and web server caching so that you won't immediately see the result of changes you make to your code.
    the database hostname on shared hosting is generally not going to be localhost. your web host should have an FAQ section that gives examples of connection credentials. the control panel where you created your database user/password should also list the hostname/ip address to use and any prefix for the username.
    if you can setup php's error related settings, you need to set error_reporting to E_ALL and set display_errors to ON. these should be in the php.ini on your system so that they can be changed at a single point.
    next, you always need error handling for statements that can fail. for database statements that can fail - connection, query, prepare, and execute, the simplest way of adding error handling, without adding logic at each statements, 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 above paragraph) to control what happens with the actual error information (database statement errors will 'automatically' get displayed/logged the same as php errors.) to set the error mode to exceptions 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); lastly, if you are just starting with php/MySql, learn and use the simpler and more modern PDO database extension.
  12. mac_gyver's post in Some Real Beginner's Questions was marked as the answer   
    the code for any php page should be laid out in this general order -
    initialization post method form processing get method business logic - get/produce data needed to display the page html document the code for any particular section can all be in the main file or divided between the main file and any number of separate files that get 'required' when needed. the html document should only contain simple php code, acting like a template engine, that operates on the input data supplied to the html document from the other sections of code OR more simply just use a 3rd party template engine.
     
  13. mac_gyver's post in Php mysql edit data was marked as the answer   
    the key to updating an existing row or inserting a new row is the existence or absence of an id (autoincrement primary index) in the form data.
    if your database table doesn't already have an id/autoincrment column, add it. when you query to get the existing data to edit, add this column to the SELECT ... list (you should actually list out the columns you are selecting, rather than use *). output the id in a hidden form field. in the form processing code, if the id input is a true value, execute the code for an UPDATE query. if it is not a true value, execute the code for an INSERT query.
    to handle both having existing data to edit or no data, you should have an intermediate array variable, such as $post, that will initially hold any existing data that you fetch from the SELECT query, then inside the post method form processing code be assigned a trimmed copy of the $_POST form data. in the form value attributes, use php's null coalescing operator (??) to output the corresponding $post value or an empty value -
    Energie: <input type='text' name='Energie' value='<?=$post['Energie'] ?? ''?>'><br>  
  14. mac_gyver's post in Need Help tp simplify a function. was marked as the answer   
    assuming the function code already exists and you don't want to change it, you can use php's splat ... operator to call the function with an array of values that will get expanded into the individual input parameters.
    $gift_fields = [77, 80, 65, 66, 67, 83, 74, 87, 88, 90, 92]; $params = []; foreach($gift_fields as $field) { $params[] = $form_data['field'][$field]; } echo SpecificGifts(...$params); if you rewrite the function code to accept and operate on elements of a single array input parameter, you would change the last line to - echo SpecificGifts($params);
  15. mac_gyver's post in Need Help with PHP Function - newbie here was marked as the answer   
    $form_data doesn't exist inside the function (there would be php errors.) 
    you could actually just define the function to accept an array of data as the input and call the function with $form_data['field'][77] as the input parameter. this will allow the processing to be applied to any array of data, not hard-coded for $form_data['field']...
  16. mac_gyver's post in Match issue with /u switch was marked as the answer   
    substr() deals with single byte characters. try mb_substr()
  17. mac_gyver's post in Error 405 Not Allowed nginx was marked as the answer   
    i suspect the error is due to exceeding some limit at your free/cheap web hosting -
    you might ask their support group.
    already stated -
     
  18. mac_gyver's post in "SQL LIKE Keyword" search not functioning as it should was marked as the answer   
    the ? place-holder that's put into the sql query statement is only the ? character, no single-quotes, no wild-card characters. any wild-card characters go around the value you are supplying in the execute() call.
    you should also be using a method = 'get' form when performing a search and to get the form to submit to the same page it is on, simply leave the entire action='...' attribute out of the form tag.
    also, Don't Repeat Yourself (DRY.) use one single search form. to select which type of search, use either a select/option menu or radio buttons.
    the serach form should be 'sticky' and repopulate the form fields with any existing search inputs and use css instead of in-line styling.
  19. mac_gyver's post in GET form being posted to "index.php" every time / not doing what expected was marked as the answer   
    did you not read the reply in the existing thread for this task?
    anyways, the form field values for a get method form will replace any get parameters you try to put on the end of the url in the action='...' attribute. to supply 'additional' get parameters, you would need to use hidden form fields.
  20. mac_gyver's post in search for unknown number in a string? was marked as the answer   
    $string = 'Joe has 5 large apples'; // find any digit(s) in the string if(preg_match('!\d+!', $string, $matches)) { print_r($matches); // result in $matches[0] } else { echo 'no number found'; } // find digit(s) with the specific before/after text if(preg_match('!Joe has (\d+) large apples!', $string, $matches)) { print_r($matches); // result in $matches[1] } else { echo 'no number found'; }  
  21. mac_gyver's post in Upgrade from php 7 to 8 broke class code was marked as the answer   
    i just tried the code, and there is one php version difference. a method named the same as the class is no longer automatically called when an instance of the class is created. you must specifically name the method __construct. change function PicSQL($DBName = ""){ to function __construct($DBName = ""){
  22. mac_gyver's post in Login Form Username / Password Values was marked as the answer   
    @Barand, the OP is using PDO.  bindValue(), PDO::PARAM_STR, and errorInfo() are all PDO elements.
    the error you are getting, assuming that php's error_reporting is set to E_ALL, means that the query didn't match a row. you need to test when you fetch the row if anything was fetched. if a row was fetched, it means that the WHERE clause was true and there's no need to test in the current php code if the form username matched the fetched username. however, if no row was fetched, this indicates that the WHERE clause was false. that's the condition where you would setup the login failure message.
    as to why the query isn't matching a row, and isn't producing an error, are you sure the username/password that you used was correct? when you executed the query directly in phpmyadmin, did it contain the sha1() password hash or did it directly have the password in it?
    when you make the database connection are you -
    setting the character set to match your database tables? setting the error mode to exceptions setting emulated prepared queries to false setting the default fetch mode to assoc as to the link you posted, don't take a backward step and use the mysqli extension. the PDO extension is the best choice, though you can simplify how you are using it, and whatever is causing the current code to not match a row will still be a problem with a different database extension.
    btw - you should be using php's password_hash() and password_verify(). the simple sha... hashing functions where never intended for security purposes. you should also only store the user id (autoincrement primary index) in the session variable to identify who the logged in user is. you should query on each page request to get any other user information, such as the username or user role/permissions. this insures that any changes made to these values will take affect on the very next page request.
     
  23. mac_gyver's post in Call to undefined function Login_sucess() was marked as the answer   
    you have actually been give the answer -
    don't put function definitions inside of other function definitions.
  24. mac_gyver's post in Calendar paging was marked as the answer   
    the operation is to simply either add one day or subtract one day from the current date -
    <html> <head> <title></title> </head> <body> <form method="post" name="f1"> <?php error_reporting(E_ALL); ini_set('display_errors', '1'); // Default dates $today = date('Y-m-d H:i:s',strtotime('today')); // Check the form was submitted if ($_SERVER['REQUEST_METHOD'] == 'POST') { $today = $_POST['today']; if($_POST['Submit'] == 'Tomorrow'){ $today = date('Y-m-d H:i:s', strtotime($today . '+1 days')); } if($_POST['Submit'] == 'Yesterday'){ $today = date('Y-m-d H:i:s', strtotime($today . '-1 days')); } } ?> <table border="1" align="center" width="100%"> <input type="hidden" name="today" value=<?php echo $today;?>> <tr> <td align="center" width="20%"><input type="Submit" name="Submit" value="Yesterday"></td> <td align="center" width="60%"> <?php echo $today;?></td> <td align="center" width="20%"><input type="Submit" name="Submit" value="Tomorrow"></td> </tr> <?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { //<!--- Form view ---> echo"<tr><td>query</td></tr>"; } else{ //<!--- Default view ---> "<tr><td>default</td></tr>"; } ?> </table> </form> </body> </html>  
  25. mac_gyver's post in Problems saving to sql after updating to PHP 7.3 was marked as the answer   
    It's possible that some of the data values that are not present for a one-way trip don't have an acceptable default value and/or are not allowed to be a null value in the database table definition, and the database server mode is now set to strict mode, which will cause an error for those columns, rather than truncating data to the nearest min/max value.
    this code doesn't have any (useful) error handling for the database statements that can fail and the one place it does have some, won't work, because the connection variable is missing from the msyqli_error(...) call. the easiest way of adding error handling for all the database statements, without adding logic at each statement, is to use exceptions for database statement errors and in most cases 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 get displayed/logged the same as php errors.) to use exceptions for errors for the mysqli extension, add the following line of code before the point where you make the one/single/first connection -
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); i hope that this code is just part of an assignment and is not on a live/public server, because it has no protection against sql special characters in the data values from breaking the sql query syntax, which is how sql injection is accomplished. you should be using prepared queries when supplying external, unknown, dynamic values to a query when it gets executed.
     
×
×
  • 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.