Jump to content

mac_gyver

Staff Alumni
  • Posts

    4,639
  • Joined

  • Days Won

    132

Community Answers

  1. 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.
     
  2. mac_gyver's post in Give Image to HTML through PHP-doesn't work was marked as the answer   
    that opens the file through the file system, not the web server, so, any links in the html will also be read through the file system. you must use a url to the html file, such as http://localhost/phptest.html. this will cause the src="phptest.php?id=1" attribute to be read through http://localhost/phptest.php?id=1
  3. mac_gyver's post in Call to a member function query() on null was marked as the answer   
    https://www.php.net/manual/en/language.oop5.visibility.php
  4. mac_gyver's post in Inserting csv records into a mysql table was marked as the answer   
    check is a reserved work and should not be used as a column name. either use a different name for that column or you must enclose the column name in back-ticks to cause it to be treated as an identifier.
  5. mac_gyver's post in Session variables are not being read was marked as the answer   
    are you using full <?php opening tags, per the problem in one of your previous threads? https://forums.phpfreaks.com/topic/311034-includes-not-being-displayed-on-page  how about the other improvements made in that thread? you seem to have gone backwards.
     
  6. mac_gyver's post in php sql syntax error was marked as the answer   
    the WHERE clause in the sql statement is probably FALSE, because you are still checking if the number 104 is equal to some value.
     
    before you go any farther on your programming journey, don't use numbed or letter-numbed database columns or variables. you won't get very far, because people you are expecting to look at your code/queries won't waste their time trying to figure out what your code and queries are doing.
     
    your code should be self-documenting. anyone reading a section of your code should be able to figure out what it is doing. database columns and variables should be named as to the meaning of the data in them.
     
    your code is testing if the query execute without any errors. that doesn't mean that the query affected any row(s). if you want to specifically know if an row was updated, check the number of affected rows. if you are using the php mysqli extension, see the ->affected_rows property.
     
    you should also be hashing passwords (see php's password_hash() and password_verify() functions) and you should not put data directly into sql query statements. use prepared queries when supplying data to an sql query statement.
  7. mac_gyver's post in Call to a member function query() on null was marked as the answer   
    you are trying to convert procedural mysqli to OO mysqli, which will take a bunch of time. when you get around to using prepared queries, you will have to convert the code again, because the programming interface for non-prepared mysqli queries and prepared mysqli queries is completely different.
     
    save yourself the time and just convert the code once, to use PDO. the programming interface for non-prepared and prepared PDO queries is the same. i recommend that you review your thread where you asked if you should switch to PDO.
  8. mac_gyver's post in need help with login script was marked as the answer   
    if this is your "working on past hosting" code, it never worked correctly.
     
    the (miss named) viewProtectedArea() method returns an array of row(s). in order to reference the zero'th/only row, you would need to reference $user[0][...].
     
    since the query will at most match one row, you should use the ->fetch() method.
  9. mac_gyver's post in A really weird update problem was marked as the answer   
    the error message is probably coming from some other query in your code, perhaps after the one in question, if you don't for example have an exit; statement after a header() redirect.
     
    in any case, it would take seeing all your code, less any connection credentials, to be able to specifically help find the cause of the problem.
     
    btw - the old and obsolete php mysql extension has been removed from the latest php version and you should be updating your code to use either the php PDO extension (which is the best choice) or the php mysqli extension (turns out is not a good choice at all), and you should not be putting data values directly into the sql query statement, but using a prepared query, with place-holders in the sql statement for the data values, then supply the data when you execute the query.
     
    updating the code will also let you use exceptions to handle the database statement errors, so you can simply enable exceptions for the extension you end up using, let php catch the exception, where it will use its error_reporting, display_errors, and log_errors settings to control what happens with the actual error information, and you can then eliminate any error handling logic you have in your code, thereby reducing the amount of code you have to convert.
  10. mac_gyver's post in newbie getting unexpected $end was marked as the answer   
    the problem is because the closing heredoc _END; identifier doesn't start in the first column in a line.
     
    there's big red warning in the php.net string/heredoc documentation -
     
     
  11. mac_gyver's post in How can I select sections of a line to be saved as variables in a graphical way on a website? was marked as the answer   
    if you want to do a 'click' interface, you would use javascript, but the data you need to produce and submit needs to be similar/same to what is given in the example above (you could have a start and end instead and calculate the length when the data is received by the php code.)
     
    if you output each character of the sample string in its own span, with a common name + numerical id that indicates the position, when you click on a character, you can get numerical position from the id of the DOM element that was clicked. if there is no currently selected id, you would start a 'pick' sequence. the first pick would give the start value. a second pick would give the end value and you would calculate the length from the difference between the end and start values. you would populate the form fields with these values. you can either use a select/option menu to pick a name or click on list of displayed names to populate the name form field. once you have picked values for all three fields in a set, the logic would 'reset' and any picks would start the process for the next set of values. you can change the color of any picked character when it is clicked on and you can change all the characters between the start and end positions if you want.
  12. mac_gyver's post in Is there a cleaner way of doing this without all the if/elseif statements was marked as the answer   
    what you doing is mapping input values to a set of output values. rather than use conditional logic to do this, just store the data somewhere, addressed/indexed by the input value. a database would be the best choice, or for a smaller set of data, you can use an array.
     
    once you have the data stored, you can perform any calculation when you 'query' for the matching data, either in an sql query, if the data is stored in a database, or using php array functions, if the data is stored in an array.
     
    some additional advantages of storing the data in a database, you would be able to create an administrative interface that allows the data to be created/edited by someone who doesn't have any programming knowledge and you can display the various levels to the users simply by querying for the data and displaying it.
  13. mac_gyver's post in issue in inserting data from dropdown into mysql table was marked as the answer   
    actually, no, it's not. there are two problems with the form -
     
    1) the value attributes, that have already been pointed out.
     
    2) the name you have given the submit button is the same as the select field name and only the last field with the same names will be used, so, you are getting the submit button value, which there is none, rather than the select field value. use a different name for the submit button.
     
    however, you need to do some other things -
     
    1) the value you use for the options should be an id (auto-increment column) from tbl_paramhead, not the text/label string, because you should store an id in any table holding data related to a tbl_paramhead selection.
     
    2) in your form code, the sql query does not have any external data being supplied to it, and using a prepared query here is wasting time typing and executing code that isn't doing anything useful. change the ->prepare() and ->execute() calls to just $stmt = $pdo->query($sql); the rest of the code using the result from the query will remain the same.
     
    3) in your form processing code, you have missed a point of using a prepared query. you do not put data values directly into the sql query statement when using a prepared query. you put place-holders in the sql query statement for the values (without any single-quotes around the place-holders), then you supply the data values when you execute the query.
     
    also, in your form processing code -
     
    4) the if($_SERVER["REQUEST_METHOD"] == "POST") conditional test should come first and/or be the only test you need. if your form processing code will only handle a single form, there's no need for any additional logic.
     
    5) you need to validate all submitted form data before using it. if the text field is empty or no select option was picked, you should not run the INSERT query. if you use an array to hold he validation error messages, you can just test if the array is empty to dected if there are no validation errors.
     
    6) there's no good reason to write out line after line of code that is just copying variables to other variables. the original variables are perfectly fine to use in the rest of the code. what happens if your form has 10 fields? are going to write out 10 lines of code copying each of the $_POST variables to other variables? the answer to this question should be no.
     
    if you do have a need to copy an array to other variables, such as if you are making a trimmed copy of the data, you can do it using a single statement,
     
    7) if you put the form processing code and the form on the same page, you can display any validation errors when you display the form and you can populate the form fields with the submitted values when there is an error, so that the visitor doesn't need to keep filling in/selecting field values, they only need to correct the fields that have errors.
  14. mac_gyver's post in Speed an update loop up? (thousands of records) was marked as the answer   
    your overall processing is - insert new data, delete old data from groups having a size greater than the queue size (30)
     
    from fastest to slowest, the following is a list of ways to insert data -
     
    1) LOAD DATA INFILE query
     
    2) LOAD DATA LOCAL INFILE query
      3) a multi-value prepared INSERT query. you can dynamically prepare a single multi-value INSERT query with a block size to handle most of the data, then dynamically prepare a unique multi-value INSERT query to handle any final partial blocks of data.
     
    4) a multi-value non-prepared INSERT query
     
    5) a single value prepared INSERT query
     
    6) a single value non-prepared INSERT query
     
    if you can, write the new data to a file and use option #1 or #2. this will be about 20 times faster than using single INSERT query inside a loop.
     
    reusing a prepared query will save about 5%, over a non-prepared query. using a new prepared query each time will actually take longer. if you had a problem with using prepared queries, it was likely due to this. if you want help with your prepared query code, you would need to post it.
     
    a multi-value INSERT query can easily insert 5K -10K rows in a single query (the limit is the max allowed packet size between the client/php and the db server, default is 1M byte) and will be between 5-10 times faster than using a single INSERT query inside a loop.
     
    -------------------
     
    to do this, i would insert all the new data using the fastest method available, then as a second process, delete the old data item from each group that exceeds the queue size. for your current concatenated data, you can use a multi-value INSERT ... ON DUPLICATE KEY UPDATE ... query (rather than three queries) to concatenate new data items onto the end of the list, then after all the new data has been inserted/updated, you can use SUBSTRING_INDEX() in one single UPDATE query to remove any leading data item from the start of the lists.
  15. mac_gyver's post in stumped on a form was marked as the answer   
    only form fields that have name='...' attributes will be submitted, using the name attribute's value as the $_POST['...] variable's name.
  16. mac_gyver's post in Server 500 error migrating WordPress sites was marked as the answer   
    you need some white-space after any opening <?php tag. add a space, tab, or new-line.
     
    if a php tag is the first line in a file, i recommend always putting it as the only thing on the line, so that any errors can be pinned down to something before or after the tag.
  17. mac_gyver's post in How do I bind param in this query? was marked as the answer   
    in most cases, you don't need to explicitly bind parameters or values, just supply an array to the execute() method call.
     
    here are some points for your current code -
     
    1) the place-holder names must be unique. when you are dynamically building a prepared query statement, you should use ? place-holders.
     
    2) the place-holders do not get single-quotes around them in the sql query statement.
     
    3) when building similar terms, it is cleaner to build them in an array, then implode() the array with the separator keyword between the elements. this will work correct even if there is a single element.
     
    4) the sql query statement doesn't need ( ) around it and having them just clutters up the code.
     
    5) you should be using exceptions to handle statement errors. this will mean that your main code only has to deal with error free execution and you don't need to have conditional logic for each statement that can fail.
     
    6) if you use php's array functions, it will eliminate the need to explicitly loop in the code. see the following example - 
    $searchTerms = explode(' ', $search_string); // note: you should filter empty values out of the $searchTerms array and only execute the remainder of the code if there are any remaining values in $searchTerms // build the dynamic part of the sql query statement $terms = implode(' OR ', array_fill(0, count($searchTerms), "ci.item_name LIKE ?")); // produce the complete sql query statement $searchQuery = "SELECT ci.id, ci.item_name, ci.item_description FROM core_item ci WHERE $terms"; // prepare the query $searchStmt = $this->pdo->prepare($searchQuery); // function to add % wildcard characters to the value function _wildcard($val) { return "%$val%"; } // add the wildcard characters to the values $searchTerms = array_map('_wildcard',$searchTerms); // execute the query $searchStmt->execute($searchTerms); // fetch and return the result - this will be an empty array if the query didn't match any row(s) return $searchStmt->fetchAll();
  18. mac_gyver's post in look up table was marked as the answer   
    calculate how long it will take for your table to have 5 million rows in it. with today's server hardware, 5 million rows in a properly indexed table is about the point where you need to start worrying about doing things like using partitioning or archiving older data.
  19. mac_gyver's post in Cookie issue was marked as the answer   
    the code at the top of your post has - setcookie('hs_user_sess', $session, time() + (86400*30));, but there is no $session variable present in that code, so it would set the cookie to an empty value.
     
    also, break; only works for loops and switch statements. it has no affect on if() statements, so in the cases where you have used it in the code above, all the logic is still being executed.
     
    if your code testing if the cookie is set is being executed on the same page request where you are setting the cookie, the $_COOKIE variable won't be set until the browser makes a request to the web server after you have set the cookie.
  20. mac_gyver's post in newbee to PHP, help with setting up my php to send to a txt file was marked as the answer   
    the code on your page should be laid out in this general order - initialization, start of database dependent code, determine user state and permissions, post method form processing, get method business logic, end of database dependent code, get method presentation logic, and html docuement/template.
     
    1) initialization - create/define things your code needs - session_start(), require files holding configuration data/function definitions, setup an autoloader for class definitions...
     
    2) start of database dependent code - create a database connection.
     
    3) determine user state and permissions - check if the current user is logged in and retrieve any permissions the user has. the rest of the code on the page would make use of the logged in state and permissions to determine what code can be ran and what content will be produced.
     
    4) post method form processing - the post method form processing code, which causes an action or change in state or change in data values on the server, should come near the start of your file so that you aren't tempted to output anything to the browser before the action/state/or data operation has been performed by the processing code. if your page has multiple sections of form processing code, you would have them all groped together in this section of code.
     
    after successfully (no errors) processing any post data, do a header() redirect to the exact same url that the form submitted to. this will cause a get request for your page. this will cause the browser to forget that a form was just submitted to that url and it won't try to resubmit the form data if you refresh the page or browse back to the same url. this also enforces separation of concerns. post method form processing is a separate concern from displaying data due to a get request for your page. if you want to display a one-time 'success' message after the header() redirect, pass it in a session variable, then clear he session variable after the the message gets displayed.
     
    if there are errors while processing any post data, you would not redirect, stay on the page, let the rest of the code on the page display the errors, (re)display the form, and repopulate the form fields with (some of) the previously submitted values.
     
    5) get method business logic - code that produces/gets data needed for the dynamic content on the page. this code contains any database specific code that knows how to retrieve data from your database tables. the result of this code should be php variables that the code later on the page uses as its input. this code should contain NO html/css/javascript markup.
     
    6) end of database dependent code - you can (or let php do this when the script ends/exits) destroy any query result resources (to free up memory) and the database connection at this point since you won't need them any longer.
     
    7) get method presentation logic - code that knows how to take the data (database data, errors, form data...) from ALL the above code and produce the dynamic output for the page. if the output doesn't require any 'heavy' processing/formatting, just use the data directly in the html page/template code. the result from this code should be php variables that the html page/template uses. this code should contain NO database specific statements. if your page has multiple sections of get method presentation logic, you would have them all groped together in this section of code.
     
    html document/template - this section starts with the <!DOCTYPE ... tag and ends with the </html> tag. it is the actual html document that the dynamic output is put into to make the complete page. if you use php (rather than an actual template system) only simple php conditional logic/loops, function calls (that are responsible for producing output), and echo statements should be present in this section of code. any data you output on the page needs to be passed through htmlentities() in order to prevent any html content in it from being operated on by the browser.
     
    if you organize the code on your page like this, it will separate all the different concerns, making it easier to see what your code is doing, easier to test, and easier to get help with because you can isolate and post just the relevant part.
     
    next, if you put the form processing code and the form on the same page, it will reduce the amount of code you have to produce, since it will eliminate the repetition of the common items. this will also let you re-populate the form field values in the case where there were validation errors with the submitted form data.
     
     
    some specific comments for the code you have posted -
     
    1) the global keyword only has meaning when used inside of a function (which you are not doing) and even then it should be avoided as it breaks the encapsulation and scope. remove any lines of code containing the global keyword.
     
    2) if you use a php array variable to hold validation error messages, it will also serve as an error flag. if the array is empty(), there are no errors. if the array is not empty(), there are errors. after you have validated all the input data, you would use that data if there are not errors. at the point of (re)displaying the form, if there are errors, you would display them, either as a group or display them individually near the form field they go with.
     
    3) you should NOT be using addslashes() at all.
     
    4) whatever your validateInput() function code is, is probably not actually validating anything. if you want help with the validateInput() code, you need to post it.
     
    5) this is a bit tongue in cheek, but a person's age is not a fixed value, unless they are dead, and you should not be storing a person's age. you should be getting and storing the date of birth and then calculating the age when needed.
     
    edit: since you are using a file to hold the data, substitute 'file operations' for any mention of 'database' in the above information.
  21. mac_gyver's post in How can i insert data from biomatric device to mysql + PHP was marked as the answer   
    it would be helpful if you define what the work-flow (steps) is (are) before you try to write code. it will also help us if you tell us what the work-flow is supposed to be. something like - 1) connect to device, 2) retrieve user and attendance data, 3) display data in forms, 4) submit form, 5) store submitted data into database table.
     
    are you displaying the data as part of the learning/debugging process and you want to 'automatically' insert the data into the database tables OR are you trying to display the data in a form and you will manually submit the form to cause the data to be inserted into the database tables?
     
    next, you need to separate the different concerns in your code.
     
    any form processing code should be near the top of your file and come before you output any html to the page. the form processing code would come before the <!DOCTYPE tag. all the form processing code would be grouped together.
     
    to display the page, your code is retrieving user and attendance data from the time-clock. the code to retrieve this data and store it in php variables should be grouped together and come before you start outputting the html document. you would then simply loop over this data when you output the html document.
     
    if you are outputting the data in a form, perhaps to allow it to be verified and edited by a manager, you would need to output it using form fields, in a valid form. there are currently no <form...> tag(s) and no data-input form fields in your code. your attendance data output doesn't even have a <table> tag, no <tr></tr> <td></td> tags and no echo statements for the data.
  22. mac_gyver's post in Creating a prepared statement from an array was marked as the answer   
    if you had php's error reporting set to E_ALL and display_errors set to ON, you would be getting a warning that would alert you to what's going on.
     
    amazingly, i have used (past tense, i don't think anyone uses mysqli with prepared queries) this code, error free, with a value coming from the array being looped over. perhaps a php version change.
     
    to get the current code to work, you need one more & in the foreach() - foreach($fieldarray as &$field){
     
    are you sure you don't want to switch to PDO? this is a lot of extra code just to call one php built in method.
×
×
  • 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.