Jump to content

mac_gyver

Staff Alumni
  • Posts

    5,529
  • Joined

  • Days Won

    189

Community Answers

  1. mac_gyver's post in How to identify each drop down uniquely of different rows of dynamic form was marked as the answer   
    i don't know what this will look like incorporated into the yii syntax, but this is what i used with just jquery/javascript -
    // the element that was clicked on var e = $(this); $.post("index.php?r=attendancereport/standard&aid="+$("#academicyearid").val()+ "&ascid="+$("#ascid").val()+"&sid="+e.val(),function(data){ e.closest('tr').find('.s').html(data); });  
  2. mac_gyver's post in Invalid password when using password_verify was marked as the answer   
    the most common reason for a password_hash()/password_verify() to fail is because the database column is not long enough to hold the hashed value.
    another common reason are programming mistakes in the form/form processing code and a lack of server-side validation that results in the hash value not actually being from the password that was submitted in the registration code, or the value being used in the login code not being what you think it is. your post method form processing code should always trim the input data, mainly so that you can detect if all white-space characters were entered, then validate all inputs before using them.
  3. mac_gyver's post in Getting difference between 2 dates was marked as the answer   
    you should do this directly in the sql query statement. MySql has a large number of datetime functions. what is the format of the 'date' column in the database table?
    if you do this in the php code, you must either compare objects with objects or compare formatted strings with formatted strings, with the same exact format, in a left-right order from most significant field (year) to least significant field (day.)
    the current php code produces a fatal error at the date_diff() method call, because the 2nd argument must be an object, not the $data["date"] string.
    $date is a datetime object, you cannot directly compare it with the $data["date"] string. you either must use the datetime ->format() method to produce a formatted string from the $date object, or you must create a datetime object from the $data["date"] string.
    $diff in a dateinterval object. to get the number of days, you would need to use the dateinterval ->format() method with the '%a' format specifier to produce the whole number of days.
  4. mac_gyver's post in call php function without reloading page? was marked as the answer   
    danger of what?
    your example doesn't do what you think. the javascript is NOT calling the php function. the php code runs on the web server when the page is requested. the php code is echoing whatever the function produces (and the echo tester(); statement echoes a null value because the function is not returning anything.) if you look at the 'view source' in the browser of the page that this code is on, the output from the php code is already there. all the javascript is doing is taking what was assigned to the test variable and putting it into the id="tx1" element. the code might as well just directly echo whatever the function produces in the markup for the id="tx1" element.
    how often does this remote data change? you would need to cache/persistently store this remote data somewhere in order to avoid reading it again. web servers are stateless. they don't know or care what happens outside of the current http(s) request they are serving. when the php code  on a page ends, all the resources used in the code are destroyed, so the remote data that you read is destroyed.
    perhaps if you provide a more helpful example of what you are trying to accomplish, rather than your proposed solution for accomplishing it?
  5. mac_gyver's post in failed to search using preg_match in a query php in html form was marked as the answer   
    wildcard characters % and _ are only used with a LIKE comparison in a query. if your first query produces any result, it means that you managed to store the % characters in with the data in the database table.
    preg_match() is a php function. you cannot put it a query to match data in the database table. this query would be producing an sql error. are you using exceptions for errors for the sql queries (this is the default setting now in php8+)?
    MySql does have regular expressions. see this link - https://dev.mysql.com/doc/refman/8.4/en/regexp.html
    the regex pattern you came up with matches a string with exactly 3 decimal digits. your stated example is to match 2 digits. which is it and can it vary?
    what exactly is the overall top-level task you are trying to accomplish, because using regex pattern matching is slow and cannot use indexes, so is a poor choice when you have large amounts of data?
    lastly, do NOT put dynamic data values directly into sql queries, where any sql special character in a value can break the sql query syntax. use a prepared query instead. if it seems like using 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.
  6. mac_gyver's post in php mysql statement not working on decimal value was marked as the answer   
    you should use a decimal data type.
    a float data type suffers from floating point conversion errors, because some values cannot be exactly stored.
    the = comparison doesn't work because the actual value as a float is something like 27.550001 (just an example)
    the like comparison works because the value is converted to a string and the like compares the values character by character.
  7. mac_gyver's post in using array items as commands? was marked as the answer   
    i recommend giving the fields a class name. you can then eliminate the array and just use getElementsByClassName to get a collection of the elements to loop over. see if this gets you closer to what you want - 
    <html> <head> </head> <body> <script> function hasNumericValue() { const matches = document.getElementsByClassName("numeric"); for (let i = 0; i < matches.length; i++) { alert(Number.parseInt(matches[i].value)); } } </script> <form name="tester" method="post" action="" onsubmit="return hasNumericValue();" > <input name="it_c" type="text" class='numeric' value=""> <br> <input name="it_h" type="text" class='numeric' value=""> <br> <input name="ot_c" type="text" class='numeric' value=""> <br> <input name="ot_h" type="text" class='numeric' value=""> <br> <input type="submit" value="submit"> </form> </body> </html> you can then test if each value is or is not a number.
  8. mac_gyver's post in Getting array data in variable was marked as the answer   
    your example works as expected for me.
    what php version are you using?
    what does using -
    echo '<pre>'; print_r($spec_recipe); echo '</pre>'; show for the data?
  9. mac_gyver's post in previous and next buttons to increment/decrement date range by 1 week was marked as the answer   
    you are doing 'date-ination'. it's like pagination, but using dates. you should be using a get request to determine what will be displayed on the page. this is so that if someone finds a result they would like to return to or share, they can bookmark or share the URL and can return to the same result. the dates you pass in the URL should be a standard YYYY-MM-DD format. format the dates as 'l j M' only when you display them. you would default to the current monday if there is no get input. you would produce the previous/next links with the previous/next monday's date and include any existing get parameters so that if you add other search/filters, they will automatically get propagated in the URL between pages.
    example code -
    <?php date_default_timezone_set('America/Denver'); // default to the current monday if there is no get input if(!isset($_GET['fdw'])) { $dw = new DateTime('monday this week'); $fdw = $dw->format('Y-m-d'); } else { // you should validate that the get input is a properly formatted date - code left up to you $fdw = $_GET['fdw']; } // use $fdw in your code to produce the output $dw = new DateTime($fdw); echo $dw->format('l j M') . '<br>'; // get a copy of any existing get parameters $get = $_GET; // produce the previous link // calculate previous date $dw = new DateTime($fdw); $pw = $dw->modify('-1 week'); $pfdw = $pw->format('Y-m-d'); // set the fdw element $get['fdw'] = $pfdw; // build the query string part of the url $qs = http_build_query($get,'','&amp;'); echo "<a href='?$qs'><button>< Previous Week</button></a>"; // produce the next link // calculate next date $dw = new DateTime($fdw); $nw = $dw->modify('+1 week'); $nfdw = $nw->format('Y-m-d'); // set the fdw element $get['fdw'] = $nfdw; // build the query string part of the url $qs = http_build_query($get,'','&amp;'); echo "<a href='?$qs'><button>Next Week ></button></a>";
     
  10. mac_gyver's post in Normal User and Admin User was marked as the answer   
    learning involves forming a theory about how something works, performing an experiment to prove or disprove the theory, observing the result of the experiment and concluding if the theory was correct or not. you will learn much better and quicker if you make an attempt at designing, writing, and testing code to see if it does what you expect.
    if(loggedin()) { // code for all logged in users if($user_level == 1) { // code for a logged in user with level == 1 } else { // code for a logged in user with level != 1 } } else { // code for a non-logged in user } i recommend two things - 1) use defined constants, such as define('ADMIN_USER',1);, instead of literal numbers, so that anyone reading the code can tell what the numerical values mean, 2) when conditional 'failure' code is shorter then the 'success' code, invert/complement the condition being tested and put the shorter code first. this will make your code easier to read and understand.
  11. mac_gyver's post in Coming from MySQL 5 was marked as the answer   
    PDO examples -
     a non-prepared query. assuming the literal 4 (which is not a string, it's a number) is hard-coded in the query -
    $query = "SELECT * FROM ember_features WHERE id = 4"; $stmt = $pdo->query($query); $row = $stmt->fetch(); a prepared query. assuming the value being shown in this query is a dynamic value -
    $query = "SELECT * FROM ember_features WHERE id = ?"; // a simple ? place-holder where the dynamic value is used at in the query $stmt = $pdo->prepare($query); // prepare the query $stmt->execute([ 4 ]); // execute the query, suppling dynamic value(s) as an array to the execute() call $row = $stmt->fetch(); where did you find this connection code? here's everything that's wrong with it -
    it's not setting the character set to match your database tables, so character conversion can occur, breaking multiple-byte characters it's not using exceptions for errors, which is the default setting now, which simplifies all the error handling it's not using true prepared queries. by using emulated prepared queries (the default) and not setting the character set, your queries are open to sql special characters in a value being able to break the sql query syntax, which is how sql injection is accomplished it's not setting the default fetch mode to assoc, so you will need to specify the fetch mode in each fetch statement there's no point in catching and handling a connection error in your application since a user to your site can do nothing about it and doesn't need to know it is the reason a page isn't working. catching and outputting the raw error information also helps hackers when they intentionally trigger connection errors (by flooding your site with requests that consume all the database connections.) if you have ever looked at a connection error, it lists the database server host/ip address, the database username, if the connection is using a password, and web server path information. do you really want to give someone this much information about your site? you should only catch and handle user recoverable database errors in your application, such as when inserting/updating duplicate user submitted data. for all other query errors and all other type of queries, simply do nothing in your code and let php catch hand handle database errors.
  12. mac_gyver's post in New dB not functioning was marked as the answer   
    in the phpinfo output, there's a value near the top named - Loaded Configuration File. is this the same php.ini that you checked?
    next, search for the error_reporting and display_errors output. what are both the local and master values for these?
    here's 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); in your previous thread, i have instructions on converting a query, that has php variables being put directly into it, into a prepared query.
    also from that thread - if you want to post examples of your existing code, i/we can show what it would look like using current practices.
    a lot of the coding suggestions given in that thread actually eliminate code, so that you can just remove things, rather than spending time updating them.
  13. mac_gyver's post in how to display one heading using for loop was marked as the answer   
    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... } }  
  14. mac_gyver's post in unset() not working within foreach loop was marked as the answer   
    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.
  15. mac_gyver's post in preg_split(): No ending delimiter '_' found in was marked as the answer   
    all the split() statements that your search/replace change to preg_split() can simply use explode()
    there's was an existing preg_split() in the code that your search/replace changed to preg_preg_split() that needs to be changed back to just preg_split()
  16. mac_gyver's post in mysqli_connect suddenly not working was marked as the answer   
    one of the great points of using exceptions for errors is that your main code will only 'see' error free execution. no discrete error checking logic will ever get executed upon an error and should be removed, simplifying the code.
    php's error_reporting should always be set to E_ALL. temporarily set display_errors to ON so that php will display all the reported errors, which will now include any uncaught database exceptions.
  17. mac_gyver's post in Display problem in mpdf php with database was marked as the answer   
    here's a note about AddPage(), which does the same as the <pagebreak> tag -
    apparently WriteHtml() adds the first page at the beginning of a new document, so the specific <pagebreak> adds a second one.
  18. mac_gyver's post in PHP help needed. Webpage php script works for all teams except team "0" was marked as the answer   
    this checks the datatype of the variable, not what's in the variable. get, post, cookies are by definition strings, regardless of what value they hold. change this to is_numeric().
  19. mac_gyver's post in Design of a database for a price list was marked as the answer   
    i/we don't understand abbreviations like tpu, pu, n, n 2, r, r 2 that would give meaning to the posted information. can you provide some context, in English, for the two examples you have posted? are these different categories of items?
    ultimately,  your task boils down to database normalization. you can search on the web to find out what this means.
    to start with, you need an item table that holds the unique information about the items, one row per item. at a minimum, this table would have columns for - id (autoincrement primary index), and name.  this will establish the item ids that will get used when storing data related to the items.
    if these various wookbooks are for different categories of items, you also need a category table that holds the unique information about the categories, one row per category. at a minimum, this table would have columns for - id (autoincrement primary index), and name.  this will establish the category ids that will get used when storing data related to the categories. if this is the case, the above item table would also have a category_id column that will hold the corresponding category id for each item.
    since i/we don't know if pricing is per category, per item, or per list of items. i.e. what the extent and scope of the data is, i cannot offer any specific suggestions beyond the above.
  20. mac_gyver's post in PHP calculation was marked as the answer   
    here's some coding pointers -
    don't copy variables to other variables for nothing. just use the original variable(s) that data is in. don't write out code for every possible value. use a data-driven design and let the computer operate on each value for you. here's what I came up with. in your initialization section -
    // define the month number and names (columns) $months = [1=>"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Decm"]; // note: the reason you needed to use decm is because dec is a reserved word. you can use dec if you surround it in back-tacks in any sql statement inside the while(){...} loop -
    // array to hold the data for the current row $data = []; // loop over the month number and month names foreach($months as $mo=>$month) { // produce the year-month value $ym = $row['Year'] .'-'. str_pad($mo,2,'0',STR_PAD_LEFT); // test if the year-month is between the start and end dates if($ym >= $row['start'] && $ym <= $row['end']) // use whatever you have named the start and end date columns { // put the value into the data array // use zero for any empty value $data[] = $row[$month] == '' ? 0 : $row[$month]; } } // at this point, $data contains the entries to use for the current row of fetched data // examine the result echo '<pre>'; print_r($data); echo '</pre>'; // calculate the average $TotalMark = round((array_sum($data)) / count($data), 2); // examine the result echo $TotalMark; note: you should use a value like 9999-12 for the end date for a person who is still employed
  21. mac_gyver's post in Experiencing problems with CODE tags was marked as the answer   
    the correct way of including code in the forum is to use the menu's <> button.
  22. mac_gyver's post in num_rows with object mysqli and statements was marked as the answer   
    i also recommend the much simpler and more modern PDO extension. you can directly fetch data from a prepared query, the same as how you would fetch it for a non-prepared query.
    if you are going to use the mysqli extension, forget about mysqli_int/mysqli_stmt_prepare. just use mysqli_prepare(). also, forget about the num_rows property. just fetch the data and test if there was any fetched data.
    if you are querying to find a row of data matching an (active) user, you would not include the password comparison in the WHERE ... term. also, you should be using php's password_hash() and password_verify() for password hashing.
    php finally realized the it should use exceptions for errors for things like database statement errors. as of php8, the mysqli (and PDO) connection, query, exec, prepare, and execute calls throw exceptions for errors. this means that any conditional error handling logic you have for these statements can be removed since they won't ever get executed upon an error, simplifying the code.
    there's also generally no need to close prepared query handles, free up result sets, or close database connections in your code, since php destroys all resources when your script ends, simplifying the code.
    pdo version -
    $sql="SELECT * FROM users WHERE username=? AND active=1"; $stmt = $pdo->prepare($sql); $stmt->execute([ $uname ]); if($user_data = $stmt->fetch()) { // a row was found // you can reference elements in $user_data, such as $user_data['id'], $user_data['added'], ... } else { // no row was found }  
     
     
     
     
     
  23. mac_gyver's post in Query Failed : SQLSTATE[HY093]: Invalid parameter number: parameter was not defined was marked as the answer   
    when using named prepared query place-holders, the name must match between what you use in the sql query and the binding. in your code, they don't. e.g. :LogID is not the same as :LOGIN_ID. ...
    i recommend that you use simple positional ? place-holders. there's less to type and keep track of. regardless of the place-holder type, you can simply supply an array of the input values to the ->execute([...]) call, saving more typing.
    you should not manage the id value yourself in code. this is not concurrent safe. instead, use an autoincrement primary index. the database engine will perform the necessary table locking to insure that concurrent queries will generate unique values.
    your database must enforce uniqueness, it is the last step in the process. the username column must be defined as a unique index. you would then attempt to insert a row of data, and test in the exception handling catch block for that query if an duplicate index error (number) occurred. if it did, setup a message for the user letting them know that the username is already in use. for all other error numbers, rethrow the exception and let php handle it.
    there's also nothing to fetch from an insert query. why are you doing that?
  24. mac_gyver's post in Self submitting AJAX was marked as the answer   
    provided the code for the page is 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 end of item #2, if the request was an AJAX request, you would build and output the response to the ajax request, then exit/die, so that the rest of the code on the page isn't executed.
    here's a snippet of code to detect an AJAX request -
    define('IS_AJAX_REQUEST', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); you can then conditionally run AJAX request only code using -
    if(IS_AJAX_REQUEST) { // build and output the response to the AJAX request // typeically json_encode([some meaningful error or success data]); // stop php code execution die; }  
  25. mac_gyver's post in Row count based on the two condition was marked as the answer   
    OR you can use the complement -
    select count(*) as CustomerActual, Month from sbms.customerdata WHERE EmpID='83201858' AND (VisitType = 'No Due' OR VisitDate !='') group by Month  
×
×
  • 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.