Jump to content

mac_gyver

Staff Alumni
  • Posts

    5,496
  • Joined

  • Days Won

    184

mac_gyver last won the day on March 13

mac_gyver had the most liked content!

3 Followers

About mac_gyver

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

158,030 profile views

mac_gyver's Achievements

Prolific Member

Prolific Member (5/5)

654

Reputation

151

Community Answers

  1. you didn't answer what is wrong with the last posted code/output? i understand your code perfectly. the list of programming practices will help to - secure your web site, provide a good User eXperience (UX), simplifies the code, and corrects some mistakes. i looked back at the search form, here's a similar list for it (repeats some things already posted) - to get a form to submit to the same page it is on, simply leave out the entire action attribute. as already written, this should be get method form and it should be 'sticky' and reselect any existing option choices. you need to validate the resulting web pages at validator.w3.org you should list out the columns you are SELECTing and only list the ones you are using in the code. you should (almost) always fetch data using an associate index name so that if your database table gets rearranged the code will still work and your code will be self-documenting (anyone reading it can tell what it is doing without needing to know what your table definitions are). any query that can match more than one row of data needs an ORDER BY ... term so that the data is in an expected order. some of your queries have an ORDER BY, some don't. using a character data type for numerical data won't sort correctly once you have values with more than a single character length. you should use a numerical data type for numerical data. the default ORDER BY ... direction is ASC. you don't need to specify it in a query. if a query doesn't match any data, you should output a message stating so, instead of outputting nothing. you need to apply htmlentities() to dynamic values being output in a html context, right before/as they are being output in order to prevent any html entities in a value from being able to break the html syntax. if you use php's short-open-print-tag <?= it will save typing. also, you can leave out the closing ; right before a closing tag ?> saving typing. there's a ; on the end of all the while ():; statements. this should either be a syntax error or is short-circuiting the loop and should be removed. for the 'required' attribute to work for a select/option menu, the first option choice must have an empty value and serve as a prompt to make a choice. you only need to use the 'required' attribute, you don't need the ="required" value. for a <label> to work, you must either have a for='...' attribute and a corresponding id='...' attribute in the field or more simply just put the closing </label> tag after the form field it corresponds to. if you have a <label>, you cannot have an empty display item for the first <option></option> choice. don't use a series of name-numbered variables. you are/should be completely dealing with the result of one query before going on to the next. just reuse simple variable names.
  2. and what exactly is the problem with the last posted code? here are some points for the current code - you should use a single database extension. now that you have used the much simpler and better designed PDO extension, all your code should be updated to use the extension. you should NOT use the mysqli_real_escape_string() function, which probably doesn't have the character-set set, to match your database tables, when the connection was made, then put these pieces of data directly into the sql query statement, as this can allow sql special charters in a value to break the sql query syntax. you should use a prepared query. converting a query that has php variables being put into it into a prepared query is straight forward. if you need, someone can post a list of instructions how to do this. you should use a get method form when determining what will be displayed on a page. this is so that if someone finds a result they want to return to or share with someone, they can bookmark the URL or share the URL and be able to return to the same result. the search form should be on the same page as the result and the form should be 'sticky' and repopulate the fields, selected options, checkboxes, and radiobuttons with any existing values so that if the search doesn't find what the user expects, they can simply make changes to the search values and try again. all the search form processing code should be inside the conditional statement testing if the form has been submitted. the current code will produce a bunch of php errors and likely produce no search result and output if the page is requested without any form data. you need to trim, mainly so that you can detect if all white-space characters were entered, then validate all input data before using it. the search inputs you have shown are all 'required'. if they are not all valid, you should output error messages stating what is wrong with them and NOT run any of the query/output code. if you want to make any of these search inputs 'optional' you will need to dynamically build the WHERE part of the query and only include the terms that have search values. the use of LEFT JOIN doesn't make sense (to me). it indicates that you want to get marks data that may not have any student or school associated with it. you should just use a JOIN if you only want marks data that has school/student data. if a query doesn't match any data, you should output a message stating so, rather than outputting nothing. you need to apply htmlentities() to dynamic values being output in a html context, right before/as they are being output in order to prevent any html entities in a value from being able to break the html syntax.
  3. this is the thead section - <thead> <tr class="text-center"> <th class="th-sm text-center">Subject </th> <th class="th-sm text-center">Class Score <br>(30%) </th> <th class="th-sm text-center">Exam Score <br>(70%) </th> <th class="th-sm text-center">Total <br>(100%) </th> <th class="th-sm text-center">Grade </th> <th class="th-sm text-center">Position </th> <th class="th-sm text-center">Remarks </th> </tr> </thead> it is the same for every student. your output is incorrect because the markup you are producing is broken. the code inside the loop is incorrect. the reason I posted an outline of what the code should do is to help you to be able to produce the correct output that will work. i recommend that you validate the resulting web page at validator.w3.org
  4. in looking at the markup you are creating, id's must be unique. if you are using the id attributes for styling, you need to use css classes instead. also, since the thead section is the same, you should build it once, in a php variable, before the start of any looping, then just echo that variable when needed.
  5. i recommend indexing/pivoting the data using the 'studentid' as a main array index when you fetch the data. this will give you an array of sub-arrays, with one sub-array for each student. this eliminates the need for conditional logic to test when the student changes and eliminates repetitive code and logic to close out each student section, but not for the very first one, before starting a new student section, and again after the end of the output. // index/pivot the data using the studentid as the main array index $data = []; while ($row = mysqli_fetch_assoc($run)) { $data[$row['studentid']][] = $row; } this also allows you to use print_r() or var_dump() on the data to make sure it is what you expect, before trying to produce the output. you can then use two nested foreach loops to produce the output. you also need to define the markup you are trying to produce, before writing any code, something like - // foreach data as student // reference the zero'th row of student data to get the one-time values for the heading // output heading information // start table // start the thead section // output the tr // end the thead section // start the tbody section // foreach student as row // output the tr // end foreach // end the tbody section // start the tfoot section // end the tfoot section // end the table // end foreach
  6. yes. which you can determine by testing. unchecked checkboxes are not set in the submitted form data. your code should only be concerned if the checkbox data isset() or is (not) !isset(). the logic would be - if (isset($p) && !isset($d) && !isset($c) && !isset($o)) { echo "error"; }
  7. the 'successful' case is: $d == "Yes" || $c == "Yes" || $o == "Yes" because you are using negative logic to produce an error, the complement of this is: $d != "Yes" && $c != "Yes" && $o != "Yes" // what i think you want if ($p == "Yes" && $d != "Yes" && $c != "Yes" && $o != "Yes") { echo "error"; }
  8. your written statement is ambiguous. please post some examples showing what result you want for different input combinations. specifically, what is the 'successful' case, which can then be complemented to produce the error case? what do you want when $p is not Yes? is that an error or does it mean that you don't care about the other three values?
  9. are you asking this because something you have shown us doesn't work or for a critique of the method? here's a list of points for the posted code - i recommend naming the connection variables more uniquely, such as $db_host, $db_name, $db_user, $db_pass. you are going to require this code into a main file. depending on where it gets required at, you could have other $user and $pass variables that will conflict with this code. there's no good reason to catch and handle a connection exception in your code and re-throwing the exception you just caught with only the message and code looses the file and line information, hindering debugging. the only database exceptions you should catch and handle in your code are for user recoverable errors, such as when inserting/updating duplicate user submitted data. for all other query errors, all other type of queries, and for the connection, you should do noting in your code and let php catch and handle the database exceptions, where php will use its error related settings to control what happens with the raw database error information, via an uncaught exception error (database errors will 'automatically' get displayed/logged the same as php errors.) don't use the global keyword to make your code 'work'. doing this breaks function scope, is not general purpose, and makes it harder if you ever need to use more than one database connection in a script. you should supply inputs to a function as call-time arguments. query builders, like this, usually have a 'raw' query function/method to handle cases beyond what the code itself can handle. i hope you are NOT planning on directly using the submitted form data to supply the column definitions to these functions, as this is not secure. your code must be where the defining array is defined at, so that YOU have control over what happens with the data and what columns and data gets used when dynamically building the queries. having the definition in your code also allows you to define labels, for use in building error messages and dynamically producing form fields and validation rules, for dynamically validating data on the server before using it. because you are dynamically building these queries, you should surround the table and column names with back-ticks so that you don't need to worry about what the actual identifiers are at the point of building the query. because you are using exceptions for errors, the conditional logic you have for the ->execute() call in the insertData() function will never see a false value and should be removed. one of the main points of exceptions is that your main code only 'sees' error free execution, since execution goes elsewhere upon an error. if execution continues past a statement that can throw an exception, you know there was no error without needing to test using conditional logic. as already mentioned, you need the ability to test for a duplicate index error (number) from a query in the exception catch logic to handle the case of inserting/updating duplicate user submitted data. for both an insert and an update query, they produce a PDOStatment rowCount() and a PDO lastInsertId() values (yes you can get a lastInsertId() value from an update query, which can be used to get an arbitrary value from the query, such as the id of the row that was updated or the initial or final value that was updated.) you should return an array with both of these values in it. you need to consistently validate the $table and $data/$conditions inputs before using them. the deleteData function() should return the rowCount() value, not the boolean value from the ->execute() call, which again due to using exceptions will always be a true value. when you get to the point of writing the update function() you need to distinguish between the columns/values used in the SET ... part of the query and the columns/values used in the WHERE ... part of the query. WHERE ... terms often involve more than just = (equal) comparisons and only ANDing multiple terms. there are LIKE, IN(), BETWEEN, greater/less, ... comparisons and combinations using AND/OR between terms. insert, update, delete, and select queries can get prepared once, then executed multiple times with different input values. to handle this you can define the variable holding the PDOStatement object as a static variable inside the function, then only prepare the query if the PDOStatement object doesn't already exist. you need a way of destroying the PDOStatement object when you are done using it. you have set the default fetch mode to assoc when you made the database connection, why are you also putting it in the fetch call?
  10. is phpmyadmin working? your initial symptom is that the raw php code is being output to the browser. did this change to the file being downloaded? about the only thing that comes to mind (ignoring that you apparently directly created a file on the server and it didn't work) is that when you uploaded (ftp) the files to the web hosting they got changed, possibly due to using a binary transfer mode instead of text transfer mode.
  11. The point of programming help forums is for you to post your code and the error or symptom you are getting and someone with the ability (and often without) will attempt to help you with the problem.
  12. you should use var_dump() on the values for debugging, since it indicates the length of the value. unfortunately, you didn't show us what you saw when you echoed the variables and if you made a change to the sql query statement and it didn't work, showing us what you changed would help someone solve the problem. converting a query that has variables being put directly into it into a prepared query is straight forward - 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 to get the last insert id and the number of affected rows. for the query in this thread, this would look like - // i recommend that you build the sql query statement in a php variable. this makes debugging easier since you can echo the sql $sql = "Select * FROM weekends WHERE Weekend_Number = ? AND Men_Women = ?"; $stmt = $pdo->prepare($sql); $stmt->execute([ $_SESSION['Weekend_Number'], $_SESSION['Men_Women'] ]); // if this query can match a set of data $result = $stmt->fetchAll(); // if this query can match at most one row of data $result = $stmt->fetch(); 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 ]; $pdo = new pdo("mysql:host=$DB_HOST;dbname=$DB_NAME;charset=$DB_ENCODING",$DB_USER,$DB_PASS,$options);
  13. i second the use of prepared statements. you MUST protect against sql special characters in a value being able to break the sql query syntax, which is how sql injection is accomplished. a prepared query is the simplest (provided you use the much simpler and better designed PDO extension), fool proof way of accomplishing this for all data types. also, if the 'th' (ordinal indicator) is actually part of the value, it should not be. this is a human convention and should only be displayed, not actually submitted or stored. you should only submit or store the integer value. the code copying session variables to other variables is both unnecessary (just use the original variable that data is in) and indicates that your form and form processing code is on different pages. by separating these, you are nearly doubling the amount of code and since it takes more code to accomplish a task, you are likely leaving out things that provide security or a good User eXperience (UX.) 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
  14. have you done or checked the 3 possible things that were already posted above? are you actually including SecureFunctions.php? also, do you have multiple sets of these files in different paths and there is more than one SecureFunctions.php and the wrong one got updated?
  15. if this is the only session variable you are getting an error for (i didn't get an error for this variable, but did for some other ones when i ran your code), here are some possibilities - your actual code has some non-printing characters in or smart/curly-quotes around the index name (that posting code on this forum filtered out). i would delete and retype the entire index name, including the initial and final double-quotes, in each reference to this array index name. is any of the other code that gets executed in the functions being called, referencing or setting that variable and could be unsetting it? are you sure that the latest code got saved/uploaded so that you are actually initializing that variable? most of these session variables exist solely to pass data from the form processing code back to the form. you should instead put the form processing code and the form on the same page. this will greatly simplify all the 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 at the completion of the post method form processing code, you should preform a redirect 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. you should not copy variables to other variables for nothing. just use the original variables that data is in. in the current code, a significant number of lines are there only to copy variables back and forth, yet you have instances of using the original variable that data is in. you should apply htmlentities() to any dynamic value being output in a html context, right before/as it is being output, to prevent any html entity in value from breaking the html syntax.
×
×
  • 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.