-
Posts
5,452 -
Joined
-
Days Won
175
Everything posted by mac_gyver
-
also, name the database connection variable as to the type of connection/extension you are using, e.g. $pdo, so that you can see or search through your code to find which database specific code has or has not been updated.
-
did you read the replies in your previous thread? they went into great detail what changes you will need to make to the database specific code and to your code in general. you should be updating and testing your code on a localhost development system, xampp or similar. constantly uploading files to a remote server to see the result of each change is huge waste of time. to get php to help you, by reporting and display all the errors it detects, you need to set php's error_reporting to E_ALL (it should always be this value) and set display_errors to ON. these settings should be in the php.ini on your development system. when you put these settings into your code, they won't do anything for a fatal parse/syntax errors because your code never runs in this case to cause the settings to take effect. when you move your tested code to the live server, you would have display_errors set to OFF, and log_errors set to ON, so that all php detected errors will get logged.
-
assuming you are using the PDO extension, it has a fetch mode that will index/pivot the data for you - // build and execute the query here... // index/pivot the fetched data using the first column in the SELECT list $data = $stmt->fetchAll(PDO::FETCH_GROUP); // at the point of producing the output if(!$data) { echo "<p>There is no data to display</p>"; } else { foreach($data as $index=>$items) { // output the section heading echo "<li class='current'><a href='#'>$index</a></li>\n"; // loop over the data in the section foreach($items as $row) { // output each row of data echo "<li>{$row['Sub']}</li>\n"; } // if needed, close the section here... } }
-
you need to index/pivot the data when you fetch it, using the Lvl value as the main array index. you can then simply loop over the data using two nested foreach loops to produce the output, like was shown in your previous similar thread.
-
you can use the MySql LAST_INSERT_ID(expr) function in an insert/update query to make the expr value present in that query accessible following the execution of the query. expr can be anything, such as a column (which would be the id column for what you are asking. i typically use it in an insert ... on duplicate key update ... query to tell if the update part was executed by getting the id of the row that was updated), the result of a calculation (such as incrementing and updating a page count column and accessing the resulting count), or the result of a comparison (i've got an example in my project archive where it is being used to return the true/false expr1 value from an IF(expr1,expr2,expr3) statement in a query) . you can then access the resulting value using the last insert id method/property for the php database extension you are using.
-
perhaps you have seen my suggested page layout posted in the forum? 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 editing existing data, you would test for a requested edit id $_GET input in the get method business logic, if the form has never been submitted, to query for and fetch the existing data to be edited. you would fetch the data into a common array variable that also holds a trimmed working copy of the form data that gets set inside the post method form processing. this common array variable being empty or not is how you determine if the form has never been submitted (requires at least one valid $_POST field in the form.) by using a little conditional logic in the form code to control a hidden field value indicating which post action (create/update) to preform, a hidden field with any requested edit id, and switch/case logic in the post method form processing to control which form processing code to execute, you can (re)use the same code for creating new entries or updating existing data. also, once you have more then 2-3 form fields you need to dynamically validate and process the data and dynamically produce the form fields by creating a defining array with the expected fields, along with their field/data type, select/checkbox/radio choices, validation rules, processing rules, and any other unique values that define each field. you would then loop over this defining data to validate, process, and produce the form fields, instead of writing out code for every field.
-
converting an old query that has variables being put directly into it to to use prepared queries, with the much simpler and better designed PDO extension, is fairly straightforward - remove, and keep for later, any php variables that are inside the sql query statement. note: any wild-card characters in a LIKE comparison are supplied as part of the data value not as part of the sql query statement. remove any quotes or {} that were around the php variable and any concatenation dots/extra quotes that were used to get the php variable into the sql query statement. put a simple ? prepared query place-holder into the sql query statement for each value. call the PDO prepare() method for the sql query statement. this returns a PDOStatement object. call the PDOStatement execute([...]) method with an array of the variables you removed in step #1. for a query that returns a result set, fetch the data from the query. see the PDOStatement fetch() method when fetching a single row of data. the PDOStatement fetchAll() method when fetching all the rows of data at once. and occasionally the PDOStatement fetchColum() method when fetching a single column from a single row of data. forget about any num rows function/method/property. just fetch then test if/how many rows of data there are. for a query that doesn't return a result set, you can use the PDO lastInsertId() method and the PDOStatement rowCount() method with an insert/update/delete query to get the last insert id and the number of affected rows. you should be using exceptions for database statement errors (this is the default setting now in php8+). for an insert/update query that could result in duplicate data (the appropriate column(s) need to be defined as unique indexes in the database table), you will need to catch and handle database exceptions from the insert/update query, test if the error number is for a duplicate index error, and setup a message for the user letting them know what was wrong with the data that they submitted. for all other query errors, simply rethrow the exception, and for all other type of queries, simply do nothing in your code, and let php catch and handle any database exception, where php will use its error related settings to control what happens with the actual error information via an uncaught exception error (database errors will 'automatically' get displayed/logged the same as php errors.)
-
your own connection.php code may be running w/o error. the tutorial script has its own connection code in config.inc.php. this is where the message you are getting is coming from. downloading and running code you find on the web, without reading it to learn what it is doing, doesn't teach you anything. as to the connection code you found and posted here. mysqli_error($con) requires a valid connection, when using mysqli procedural statements. therefore, this code won't report the actual reason for the connection failure and will produce its own error at the mysqli_error($con) statement. as to both the connection code you found and what is included in this out of date tutorial, modern php (8+) uses exceptions for errors and any discrete error handling logic will never get executed upon an error and should be removed, simplifying the code. i recommend that you update to use php8+ and find a recent tutorial.
-
where is the form and form process code hosted at? is on on the web site you previously posted the URL for?
-
that's why you need to make an attempt at doing this yourself, so that you will actually learn the meaning of the words and syntax you are using.
-
@Abi2702, the only technically relevant parts are the two sql queries - $query = "SELECT invoice_id, service_provider, reg_name, acc_no, acc_name, invoice_no, invoice_date, invoice_amount, eft_no, pay_status FROM invoices"; and - $sql = "SELECT name FROM admins inner join invoices on admins.user_code = invoices.user_name"; wouldn't you add the admins name column to the list of columns you are SELECTing and JOIN the invoices query with the admins table ON the same join condition being used in the second query? i recommend that when you write JOIN queries that you use table alias names and that you prefix every column reference with the corresponding alias, even when it is not necessary to make the query work, in order to prevent mistakes and to make it clear to anyone reading the sql query what you are attempting to do. i also recommend that you rename the invoices user_name column to user_code, since it is not holding user_name values.
-
i'm going to guess the answer involves a JOIN query or the number 42?
-
what is your goal for doing this? to have a working form to email application or to learn programming? if it's to have a working, secure, application, you need to hire someone or use an existing service. if it is to learn how to do this, i recommend that you start with a blank page (don't copy/paste out-of-date things you find on the web), and get the code to fully work for a single form field, then worry about adding all the code necessary for the rest of the fields. some points for creating an application - put the form processing code and the form on the same page. the code for any page should be laid out in this general order - 1) initialization, 2) post method form processing, 3) get method business logic - get/produce data needed to display the web page, 4) html document validate any web page you create at validator.w3.org the form processing code should detect if a post method form was submitted before referencing any of the form data. keep the form data as a set in a php array variable, then operate on elements in this array variable throughout the rest of the code, i.e. don't create discrete variables for every form field. trim all the input data before validating it. once you do item #4 on this list, you can trim all the data using a single line of code. validate the now trimmed data, store user/validation errors in an array using the field name as the array index. don't roll your own email valuation. use php's filter_var() with the FILTER_VALIDATE_EMAIL flag. after the end of the validation logic, if there are no errors (the array holding the user/validation errors will be empty), use the submitted form data. any value you use in a html context (web page, email) needs to have htmlentities() applied to it, right before being used, to help prevent cross site scripting. these emails are not being sent from the email address that someone entered in the form. they are being sent from the mail server at your web hosting. the From: mail header must be an email address that corresponds to your web hosting. the Reply-to: mail header can be set to the entered email address. don't use the php @ error suppressor, ever. you must test the returned value from the mail() call and take an appropriate action depending on the value. if it is a false value, you need to setup a message for the user (add it to the array holding the user/validation errors) that the email was unsuccessful. for a true value, you would let the post method form processing code run to completion. at the end of the form processing code, if there are no errors, you need to perform a redirect to the exact same URL of the current page to cause a get request. this will prevent the browser from trying to resubmit the form data should the URL get browsed back to or reloaded. to display a one-time success message, either store a flag value or the message in a session variable, then test for, display the success message, and clear the session variable at the appropriate location in the html document. if there are user/validation errors at item #8 or #13 on this list, the code will continue on to redisplay the html document, where you would test for and display the user/validation errors, and redisplay the form, populating field values, select choices, checkbox/radio fields with any existing data, so that the user doesn't need to keep reentering/reselecting data over and over upon an error. as an advanced programming subject, if you have more than 2-3 fields, you need to dynamically - validate and process the form data, and dynamically build the form.
-
how do i make file upload system efficient!?
mac_gyver replied to ujjwalG's topic in PHP Coding Help
if the total size of the form data exceeds the post_max_size setting both the $_POST and $_FILES arrays will be empty. what will your existing code do when there is no $_POST and $_FILES data? the post_max_size setting should be set to a reasonable value that your application expects to deal with for form data. resist the urge to set it to an extremely large value, since no matter how large you make it, someone can submit data that's larger. the total size of the form data is out of your control. the post method form processing code must first detect if a post method from was submitted, then test for this condition before trying to reference any of the form data. if there is no form data, you should setup and display an error message for the user that the form data was too large and was not processed. you also need to test the ['error'] element of the uploaded files before referencing any of the file information. there are upload errors where the ['name'] element exists (what the current code is counting), but the file was not successfully uploaded. for upload errors that are under control of the user, you must setup and display a message letting the user know what they did and how to correct the problem. for upload errors that are out of the control of the user, you need to setup and display a general message letting them know that the uploaded file was not processed, and log the actual reason for the failure, so that you (the site owner/developer) will know what is occurring. don't query to get the current MAX() value from a database table and increment yourself. when there are concurrent instances of your script running they will all get the same starting value, increment it an use it, resulting in duplicate values. you should instead have and use an autoincrement primary index in the table. don't run SELECT queries inside of loops (the task_photos query.) use a single appropriate type of JOIN query. the form processing code and form should be on the same page. this simplifies the code, allows you to display any user/validation errors when you (re)display the form, and lets you repopulate appropriate form field values (type='field' fields cannot be set) with existing data so that the user doesn't need to keep reentering data over and over. the code for any single 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 redirect you perform upon successful completion of post method form processing should be to the exact same URL of the current page to cause a get request for that page. this will prevent the browser from trying to resubmit the form data should that page get browsed back to or reloaded. -
Php escape string with GET function issue with apostrophe
mac_gyver replied to PNewCode's topic in PHP Coding Help
you need to use a prepared query in order to prevent any sql special characters in a value from being able to break the sql query syntax, which is how sql injection is accomplished. if it seems like the mysqli extension is overly complicated and inconsistent, especially when dealing with prepared queries, it is. this would be a good time to switch to the much simpler and better designed PDO extension. converting an old query that puts the data values directly into the sql query statement into a prepared query using the PDO extension is straightforward - remove, and keep for later, any php variables that are inside the sql query statement. note: any wild-card characters in a LIKE comparison are supplied as part of the data value remove any quotes or {} around the value and any concatenation dots/extra quotes that were used to get the php variable into the sql query statement put a simple ? prepared query place-holder into the sql query statement for each value call the PDO prepare method for the sql query statement call the PDOStatement execute method with an array of the variables you removed in step #1. for a query that returns a result set, fetch the data from the query. see the fetch() method when fetching a single row of data. the fetchAll() method when fetching all the rows of data at once. and occasionally the fetchColum() method when fetching a single column from a single row of data. forget about any num rows function. just fetch then test if/how many rows of data there are. here is typical PDO connection code - $DB_HOST = ''; // database host name or ip address $DB_USER = ''; // database username $DB_PASS = ''; // database password $DB_NAME = ''; // database name $DB_ENCODING = 'utf8mb4'; // db character encoding. set to match your database table's character set. note: utf8 is an alias of utf8mb3/utf8mb4 $options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // set the error mode to exceptions. this is the default setting now in php8+ PDO::ATTR_EMULATE_PREPARES => false, // run real prepared queries PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC // set default fetch mode to assoc, so that you don't need to specify it in each fetch statement ]; $pdo = new pdo("mysql:host=$DB_HOST;dbname=$DB_NAME;charset=$DB_ENCODING",$DB_USER,$DB_PASS,$options); -
without knowing what symptom you are getting and what debugging steps you have already performed, it is not possible to help you. there's no point in echoing a static string in the php code (2 places). just put the string as the value in the markup. don't use PHP_SELF. to cause the form to submit to the same page it is on, leave out the entire action attribute.
-
how to hide data behind the = (page.php?id=xx) for the user
mac_gyver replied to wildware's topic in PHP Coding Help
your code should be as general-purpose as possible, so that you don't need to keep redoing it as requirements change. the URL should uniquely determine what information will be displayed on a page, so, yes you should put the user id as a get parameter in the URL. the code for any page must enforce access permission for that page. for what you are seemingly asking, you would compare the logged in session user id with the get parameter id and only query for and display the requested user's data, using the get parameter id, if they match. if at some point you have a site administrator or a list of permitted 'friended' users, you would query for and display the requested user's data, using the get parameter id, depending on the current user's access permission for the requested user's data. -
without some examples, the uncommented, wall of markup and your statement doesn't make sense. are you adding these sub questions dynamically? are the number of choices per sub question dynamic? do you mean that all the choices for a sub question will be either text or they will be files? if so, you would have a radio field to show just the text fields or the file fields for that sub question. i would hope you are dynamically producing this markup? you should not use a series of name-numbered things. use an array instead. the labels are invalid (ids must be unique.) you would either generate unique ids, or more simply put the closing </label> tag after the form field it corresponds to.
-
had you initially posted the error message (someone did ask), you could have gotten help earlier. that error (most likely) means that the query failed with an sql error and the code does not have error handling for database errors. to add error handling for database errors, add the following line of code before the point where the database connection is made, then report back with the database error (this is the default setting now in php8+, so you need to also update to using php8) - mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); once you solve the current problem, to do what you have asked, which requires knowing first if the email/password is correct, then what the authorized value is, will require actual programming changes to be made to the query and to the program logic. programing is not about finding something that does what you want and repeat it in your code. programming is a creative writing (and reading) activity. you must actually learn the meaning of the words and syntax you are using so that what you write makes sense when it is executed by the computer. lastly, because the current query is putting the values directly into the sql query statement, sql injection is possible. someone can submit an email address for an administrator, to match his row of data, and bypass the need for the password and become logged in as an administrator. since i doubt you want this to be possible, you will need to convert this query to be a prepared query.
-
what error? if you want to do something based on the authorized value, you would not include it in the WHERE term in the query. you would SELECT it, then test its value in the program logic. also - use 'require' for things your code must have. include/require are not functions. leave the () around the path/file out. don't attempt to detect if the submit button is set. there are cases where it wont be. instead, test if a post method form was submitted. you need to trim, mainly so that you can detect if all white-space characters were entered, then validate all inputs before using them. don't copy variables to other variables for nothing. don't put dynamic values directly into sql query statements. use a prepared query. if it seems like using the mysqli extension is overly complicated and inconsistent, it is. this would be a good time to switch to the much simpler and better designed PDO extension. you should be hashing the passwords. see php's password_hash() and password_verify(). you would not include the password in the WHERE term. you would SELECT the password, then after you have determined if a row of data was matched, use password_verify() in your program logic to test the password hash. the fetch instruction returns either an array, a null, or a false value, not a number. is this where you are getting an error? the only user value you should store in a session variable is the user id. you should query on each page request to get any other user data. the redirect you perform upon successful completion of the post method form processing code needs to be to the exact same URL of the current page to cause a get request. every redirect needs an exit/die statement to stop php code execution. 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.
-
check the browser's developer tools, console tab for errors.
- 1 reply
-
- 1
-
unset() not working within foreach loop
mac_gyver replied to nlomb_hydrogeo's topic in PHP Coding Help
the query is SELECTing the column_name, which is why you are echoing column_name to produce the output - $row['column_name'] will be 'well_no' or 'geom'. you would create an array with the two values you want to exclude, then because you cannot directly loop over the result set from a query a second time, fetch all the rows of data into a php variable (see the fetchAll() method), then as you are looping over this array of data, use a conditional test if( !in_array($row['column_name'],['well_no','geom']) ) { produce the output here... } to exclude those two column_name values. and as was written in one of your previous threads, there no good reason to catch and handle an exception from a SELECT query in your code. just let php catch and handle it. remove the try/catch logic from this query, simplifying the code. also, where this catch logic is at, you won't see the output from it unless you look in the 'view source' in the browser. -
Upgrading PHP to current
mac_gyver replied to AdmiralQ's topic in PHP Installation and Configuration
if/when you update your code, here is a list of practices, based on a review of the login code in your other thread, that will help make the code more secure, provide a better user experience, eliminate unnecessary code, and though having usable validation logic and error handling will get your code to tell you when and why it doesn't work - always use a full opening php tag - <?php don't use $_REQUEST. use the correct $_GET, $_POST, or $_COOKIE variable that you expect data to be in don't use extract() as this allows hackers to inject their data values into your code, which is what register_globals allowed, which is why they were removed from php use 'require' for things your code must have post method form processing code needs to detect if a post method form was submitted before referencing any of the form data you need to trim, mainly so that you can detect if a value was all white-space characters, then validate all input data before using it you should list out the columns you are SELECTing in a query as already written, you would use prepared queries you need to hash the stored passwords. see php's password_hash() and password_verify() as already written, you would use exceptions for database error handling, and remove any existing error handling logic you would fetch and test if there is fetched data, meaning that the username was matched, then verify the password hash the only user related data that you should store in a session variable upon successful authentication is the user id (autoincrement primary index). you would query on each page request to get any other user data, permissions, ... this will insure that any changes made to this other user data will take effect on the very next page request, without requiring the user to log out and back in again you should only create and store data in the session variable(s) if authentication was successful. by unconditionally creating it/them, you now have session variables that exist, even if they are empty/null the first redirect implies that the form and form processing code are on separate pages. they should be on the same page. the code for any page should be laid out in this general order - 1. initialization, 2. post method form processing, 3. get method business logic - get/produce data needed to display the page, 4. html document by redirecting around on your site and using values from the url to control what the form page reports, your site is open to phishing attacks, where someone could trick your users to enter their username/password on the phishing site, then redirect them to your site and make it look like they just entered an incorrect username/password the only redirect you should have in your code is upon successful completion of post method form processing and it should be to the exact same URL of the current page to cause a get request for that page. this will prevent the browser from trying to resubmit the form data should that page get browsed back to or reloaded if you want to allow the user to go to a different page, provide navigation links, or more simply, just integrate the login operation on any page that needs it every redirect needs an exit/die statement to stop php code execution. while you have the remainder of the code inside an else {...} conditional branch, if you had stopped the php code after the redirect, you could just put the remainder of the code w/o the else the inno_login_track_staff INSERT query is part of the successful authentication code. after the logic is changed to use password_verify() and only store data to session variable(s) upon successful authentication, there will be a specific place in the php logic to put this query inno_school_staff - this indicates you have separate 'user' tables for students and staff. you should have one user/authentication table. the user data that you query for on each page request would control what the current user can see or do on any page don't copy variables to other variables for nothing and don't use intermediate variables when you only reference a value once as an advanced programming practice, if you have more than 2-3 form fields, you should dynamically validate and process the form data, and dynamically produce the form, rather than writing out bespoke code for every field every time you do something different -
it sounds like the session data files are being read and locked. the permission issue isn't due to the permission settings, but that some other instance/process is reading the file at the same time. this would be either due to session garbage collection (you can temporarily configure it to not run as a test or perhaps it is configured to run on each session start?), some code that's reading/scanning the session data files (do you have some code that's trying to read and manage the session data, such as logging users out after a time?) , or multiple concurrent instances of your script accessing the same session data (this can occur when ajax requests are used.) as to why this worked before and has now changed, I don't have any suggestions. it would take knowing everything your code is capable of doing, session related, uploaded file related, ... are there currently a bunch of unusual requests being made to the site or just your requests for troubleshooting this problem?