Jump to content

mac_gyver

Staff Alumni
  • Posts

    5,454
  • Joined

  • Days Won

    175

Community Answers

  1. 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
  2. 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.
  3. 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.
     
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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 -
     
     
  9. 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.
  10. 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.
  11. 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.
  12. 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.
  13. 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.
  14. 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.
  15. 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();
  16. 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.
  17. 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.
  18. 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.
  19. mac_gyver's post in How can an index be set and undefined at the same time? was marked as the answer   
    the error is because you are concatenating the string 'count: ' with the isset() expression, which will always be true. you need to put () around the trinary statement so that it is evaluated as an expression that then gets concatenated with that string.
  20. mac_gyver's post in Updating Database changes all entries was marked as the answer   
    your code and queries are only as secure as you make them. if you use a prepared query incorrectly, it will won't be secure.
     
    by using a true prepared query (the PDO extension has emulated prepared queries turned on by default for all database types, despite what the documentation states, and you need to turn them off when you make the database connection) to supply data values to the sql query statement, your sql query will be safe against sql special characters in the data from breaking the sql syntax or breaking out of, i.e. escaping from, the sql syntax in the case of intentionally injected sql.
     
    after you choose the php database extension you are going to use, the posted code needs to do or not do a number of things -
     
    1) you are mixing procedural and OOP style for the msyqli statements. you should be constant in your programming. using the PDO extension will fix this since it only has OOP statements.
     
    2) using prepared queries will eliminate all the ...real_escape_string() calls. you are using one in the case of a value being output to the browser. the ...real_escape_string() statements are only used on string data being supplied to a non-prepared sql query statement, not on data being output to the browser.
     
    3) you need to use exceptions to handle database statement errors. your code has error handling on only one of the query statements now. the PDO extension already uses exceptions for connection errors. you need to set the error mode to exceptions, for all the rest of the statements, when you make the connection.
     
    4) all the post method form processing code should be grouped together and come near the top of your code. you should actually test if a post method form was submitted, then if you have multiple possible forms, detect a field name or field value that identifies if the Delete or Update form was submitted.
     
    5) you should validate all the submitted data before using it, then only use it if it is valid. use an array to hold validation errors. you can then test if the array is empty or not to determine if there have been any validation errors. to display the errors, just output the contents of the array.
     
    6) your delete checkbox logic only works for a single/last checkbox. in fact, all the form fields don't work when there is more than one set of data in the form. you need to use array names for all the form fields, with the $row['id'] value as the array index (this is needed to distinguish which row each form field value corresponds to) and you need to remove the hidden field with name='checkbox' (having this causes only the last checkbox in the form to work.) you would also need to add a loop in the Update form processing code to loop over all the submitted sets of data.
     
    7) with prepared queries, when you are looping over data and executing the query inside the loop, you will prepare the query once before the start of the loop. the code inside the loop only gets the correct set of data and calls the ->execute() method.
     
    when you remove the hidden form field with name = 'checkbox' (which was done to prevent php errors when no checkboxes are checked, but because it is being output repeatedly, only allows the last checkbox to work), the logic in the delete form processing code will need to be changed. if there are no checked checkboxes, $_POST['checkbox'] won't be set. you need to add an if(isset($_POST['checkbox'])) test.
     
    9) the code to retrieve the data needed to display the page should be removed from the actual html document/template. this will make it easier to write and test your code, and if you need to change the code to use a different database extension, such as the PDO extension, consolidates the database specific code in one place and makes the html document/template general purpose. just fetch the data from the query into a php variable and use that variable in the html document/template.
     
    10) the html document you are creating is reusing DOM id='...' attribute values. id's must be unique. if the client-side code isn't actually referencing the id's, don't even put them into the markup.
     
    11) you are outputting an empty <tr></tr> after each actual <tr>....</tr> of output. makes no sense and is repeating an id attribute value which is also not valid. only output markup that you need.
     
    12) you are outputting the $row['id'] value in a form field. this is not an editable data value. the $row['id'] specifies which row the data belongs to. you can display the $row['id'] value if you wan't, but it should not be in a visible form field. see item #6 in this list for how the $row['id'] value should be used to associate the submitted values with the $row['id'] value they belong to.
     
    13) when your SELECT query doesn't match any data, your code is correctly skipping over the code to produce the output from that data, but your code is also not doing anything to notify the user that there was no data to display. you should set up and display a message that the reason for the blank section on the page is that there is no data to display.
     
    14) all data values being output to the browser should be passed through htmlentities(), with an appropriate 2nd parameter value, to prevent any html entities in the data from breaking the html on the page and to help prevent cross site scripting.
     
    15) you are repeating the <tbody>...</tbody> tags for each set of data being output. while this is valid markup, unless you are going to style each table body section separately, there's no point in doing this and it is just adding clutter to the result and would prevent a large table body section from being able to be scrolled on the page.
  21. mac_gyver's post in sess_start() makes session variables vanish. was marked as the answer   
    did verifymail.php ever have a sess_start(); call in it?
     
    all your files must be doing the same thing for the session to match up. it's likely that this was initially working because you already had an existing session, using session_start(), that matched up between the files. when you added sess_start() to just the index.php page, that created a new session with a second name, alongside the existing session, and so your verifymail.php had session data. once you finally closed your browser and started over, index,php was using the sess_start() settings, verifymail.php was using the session_start() settings, and there was no matching session data for verifymail.php to use.
     
    most of the code you have shown at the top of index.php is common logic that ALL your pages should use. why don't you have them in a file and require it into each page (Don't Repeat Yourself - DRY) or better yet, if you are at the point of wanting to set up custom session settings, why aren't you using a single file, index.php, to implement your entire site? having a single index.php file site would eliminate the need to even pass data in session variables and would eliminate all the repetitive code and html you are trying to write, test, and maintain.
  22. mac_gyver's post in Process the value of a searched result was marked as the answer   
    do you have php's error_reporting set to E_ALL and display_errors set to ON in the php.ini (putting these settings into your code won't help show syntax errors in the same file where the settings are being set) on your development system so that php would help you by reporting and displaying all the errors it detects?
     
    you would be getting a php syntax error because you are mixing php and html markup inside of php code tags. you would also be getting a blank php page, which you didn't tell us you are getting as a symptom when you run your code. to output in-line html markup, you need to have a closing php tag to switch out of php 'mode'. with 300+ posts, you should be past having these basic problems.
  23. mac_gyver's post in What did I do wrong? was marked as the answer   
    an auto-increment column needs to be an integer data type.
  24. 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.
  25. mac_gyver's post in extract image data (BLOB) from imagejpeg() was marked as the answer   
    you would need to use php's output buffering statements.
×
×
  • 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.