Jump to content
Larry Ullman's Book Forums

All Activity

This stream auto-updates     

  1. Yesterday
  2. Two things do stand out for me here. First, any time you're talking about handling money, the requirements are way more strict. You'll need to think a lot about security, but there are also legal and regulatory requirements like licensing, KYC (Know Your Customer), illegal money transmissions, etc. I can't exactly tell if these will be concerns of yours or not, but something to be aware of, at least. Second, that you're trying to use an API that's poorly documented is a cause for concern! In any case, good luck with your project and let us know if you have any specific questions!
  3. Last week
  4. Any updates on the next release of Yii2 book? I'm a little concerned that lack of activity here means Yii popularity and support is dipping?
  5. I have a current project that i want to develop but i am getting confused along the way and would need valuable support from this forum. The project is about an organization that lends money(loan) to some set of government workers whose salaries details and bank accounts are with the Web Service which the website will be integrated into. The logic of the program is that the loan applicant will first of all enter his/her first name, last name, email and phone number on a front-end form on the loan issuer website, then when he/she clicks the submit button, his data will be sent to the web service API to check the applicants data in their database to know if they are eligible to be granted loan. If yes, then the loan applicant proceeds in requesting for loan. The web service API did not provide detailed documentation on how to do the integration. But they listed some headers like MERCHANT_ID, API_KEY, REQUEST_ID, REQUEST_TS, API_ENDPOINT, API_METHOD, AUTHORIZATION_TOKEN etc that must be used to construct the request to the API. I therefore seek for helpful php codes that can educate me on how to go about making calls to API, retrieving data from its response and possibly saving the data into database. Looking out for your supports in this forum.
  6. OK, I'll use the timestamp approach. Thanks for the advice. Cheers, Necuima
  7. You can't rely upon a browser event for something like this. But if you use sessions or cookies, those will automatically expire. Or you can store a timestamp in the database to reflect the most recent activity and then add logic that checks that value.
  8. Hi Larry, I finally got to the point in my complete software re-load/re-build where I could test your suggestion. I re-downloaded the script from your website and made the suggested change but unfortunately I am still getting the error "on line 29: session_write_close(): Session callback expects true/false return". Here is my modified code: // Define the close_session() function: // This function takes no arguments. // This function closes the database connection. function close_session() { global $sdbc; mysqli_close($sdbc); return true; // return mysqli_close($sdbc); } // End of close_session() function. My environment is XAMPP 7.3.5 with PHP 7.3.5 both 64 bit under Windows 10 (64 bit). I know that you are a very busy man so please treat this as low priority - I will use a work-around. Best regards, Necuima.
  9. Earlier
  10. Hi Larry, On pages 284-5 you mention the browser unload event. I'd appreciate your advice re what I imagine is a common issue in that if someone just closes the browser without logging out I want to be able to update a database table to set a logged-out condition. Can this be done reliably either with native JavaScript or jQuery initiating an AJAX call to a PHP module to effect the database update? My program is PHP with lots of jQuery. Looking forward to your advice re this or similar functionality and thank you in anticipation. Cheers, Necuima
  11. Understanding what makes a password strong requires thinking about how passwords can be cracked. Without getting into the system itself (e.g., breaking into the database), passwords are most often cracked by brute force: trying as many possible combinations as possible. Dictionary attacks would be an easy way to do this: start by trying common words such as "password", etc. This is why sites wanted you to not use common words as a password, which was enforced by requiring numbers and symbols. Capital letters would also be required, so that "password" wouldn't match "Password". This wasn't an unreasonable solution at the time, but two developments have since occurred. Most importantly, computers are just crazy fast now and they can brute force millions of passwords in seconds, or milliseconds. Second, most people ended up doing number substitutions that were pretty easy to guess, like "passw0rd" or "p4ssw0rd". Sidenote: These systems that require numbers and symbols also inadvertently encourage bad behavior on the part of users, such as writing down the password b/c they can't be remembered. Given all this, how do you make passwords actually more secure? The answer is by making them longer. Each character added to the length of a password makes it exponentially harder to crack. Just using the lowercase English alphabet, a single-character password can be one of only 26 possible values. A two-character password can be 676. A three-character password can be 17,576. And so on. It's exponential. So requiring longer passwords is way more important than putting restrictions on what's in the password. Two final thoughts... - In terms of customer security, the most important factors are out of your control: users shouldn't re-use passwords across sites and they should store them security (e.g., in a tool like 1Password). - Your goal shouldn't be the strongest password system or maximum customer security. Requiring passwords of at least 1,000 characters will be pretty secure--but not maximally so--but is ridiculously impractical. Your goal should be to find the right middle ground between security and user convenience for your application. This forum, for example, doesn't need very strong security, but my bank's website does.
  12. Hi Greetings, Thank You Sir for the guidance. And there is no need for sorry - I can understand you have lots of work to do. If I go with the latter option as you have mentioned. What could be the strongest password system and pattern for the maximum customer security. Thank You,
  13. Hi Larry, Thanks for this. I have been having computer troubles and am having to re-build ALL my software from a clean Win 10 installation. Fortunately I have great backups :-) I'll test again when I have re-installed XAMPP. Thank you for following this up. Cheers from Oz, Necuima
  14. OK, have just got it. There is no need to use YEAR() function as the Date column will accept SELECT * FROM Timeline WHERE Date LIKE '%$i%' SORT BY Date ASC All working now. www.gssr.es/timeline.php Adios!
  15. Hi Larry and everyone, I have really painted myself into a corner with this one. Above is the database that I created for a timeline. The issue is that not all of the dates at my disposition have days and months. Some are just years. Hence, I had to make a separate column for years only. What I want to do is create a timeline using tables so that any year that has either a YYYY date and/or a YYYY-MM-DD date appears in chronological order. I tried it with a for loop starting at $i = 1700 - 2000 which works for the first year but the while ($enquiry3 = @mysqli_fetch_array($enquiry2)) { will only iterate once and then stops. The alternative is to use MySQL such as: for($i = 1700; $i <= 2000; i++) { $enquiry = "SELECT * from Timeline WHERE Year = $i ORDER BY Year ASC" } which works OK for getting the year only files. Then we need to get the full date files so we try: for($i = 1700; $i <= 2000; i++) { $enquiry = " SELECT * from Timeline WHERE Date = YEAR($i, %Y) ORDER BY Date ASC" } ....but the date function doesn't seem to work. Any ideas??? Regards Max
  16. Hello, i'm new to javascript and currently in a bootcamp course to become a software developer. that being said there are a lot of new ideas that have been thrown at me in the past couple weeks and i'm having trouble completing our assignment for the week. I've been tasked with creating a site that takes an input and pushes it into an array and when a button is clicked that array gets made into a card that houses a name, a hogwarts house and a button. the button on these cards needs to be able to delete the card that the button is on. I've been able to do everything up until this point. i. can't get the button to only delete one card. it deletes every card, and even when i get the button to delete one card it won't delete any other card. how do i get this to work? I'll post my code so that gives better context. //html below <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <link rel="stylesheet" href="main.css"> </head> <body> <div id="jumbo" class="jumbotron"> <h1 class="display-4">Sorting Hat</h1> <p class="lead">Hello muggles, are you a big fan of Harry Potter? </p> <hr class="my-4"> <p>Well you are in luck. Now you will be able to use this website to try on the sorting hat and see which house you will be sorted into.</p> <p class="lead"> <a id="initForm" class="btn btn-primary btn-lg" onclick="openForm();" href="#" role="button">Lets Get It Started!</a> </p> </div> <div id="form"> <form class="form-inline"> <h3 class="display-6">Enter First Year's Name</h3> <div class="form-group mx-sm-3 mb-2"> <label for="insertName" class="sr-only">name</label> <input type="text" class="form-control" id="insertName" placeholder="Harry Potter"> </div> <button id="sort" type="submit" class="btn btn-primary mb-2">Sort</button> </form> </div> <div id="studentCard"></div> <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script> <script src="main.js"></script> </body> </html> //css below body { background-color: slategray; } #form{ display: none; } .expel{ background-color: blueviolet; padding: 15px 30px; } a{ list-style-type: none; color: white; } a:hover{ list-style-type: none; color: white; } //javascript below console.log("HelloWorld!"); //print to dom function for innerhtml const printToDom = (divId, textToPrint) => { console.log(textToPrint); const selectedDiv = document.getElementById(divId); selectedDiv.innerHTML = textToPrint }; //this is my hogwarts array const hogwartsHouse = [ 'Griffindor', 'Hufflepuff', 'Slytherin', 'Ravenclaw' ]; //this variable grabs the users input into my form const names = document.getElementById("insertName"); //this variable sets the student id to 0 //student id is located inside the sort init function let studentId = 0; const students = []; //this function allows my form to be seen function openForm() { x = document.getElementById("form"); if(x.style.display === "none") { x.style.display = "block"; } else { x.style.display = "none"; } }; //this function builds the card const sortBuilder = (sortingHat) => { let domString = ''; for(let i = 0; i < sortingHat.length; i++){ domString += `<div id="cardContainer">` domString += `<div class="card" style="width: 18rem;">` domString += `<div class="card-body">` domString += `<h5 class="cardTitle">${sortingHat[i].name}</h5>` domString += `<p class="card-text">${sortingHat[i].house}</p>` domString += `<a onclick="expelStudentEvent()" id="${sortingHat[i].id}" href="#" class="expel">Expel</a>` domString += `</div>` domString += `</div>` domString += `</div>` } printToDom('studentCard', domString) }; //make function for expel students events //loops over all of the expel buttons //adds the remove student function to each button //need remove student function //remove student with the id that is equal to the id of the button, e.target.id //pass in id of the card i'm clicking //i want this function to delete 1 card when the button on said card is clicked const expelStudentEvent = () => { let domString = ''; for(let i = 0; i < students.length; i++){ domString += `` } if(students.length = 0){} console.log(students) printToDom('studentCard', domString); }; //this function takes my users input into the form and my hogwarts array into an array that gives each input an id const sortInit = (e) => { const student = { id: studentId, name: names.value, house: hogwartsHouse[Math.floor(Math.random() * hogwartsHouse.length)], } students.push(student); console.log(students); studentId++; sortBuilder(students); }; // const removeCard = () => { // let myCard = document.getElementById(e.target.id); // } //this function holds my event listeners const events = () =>{ document.getElementById('sort').addEventListener('click', sortInit) document.getElementById(e.target.id).addEventListener('click', expelStudentEvent) } //this function holds all of the previous functions const init = () => { openForm(); sortBuilder(students); events(students) expelStudentEvent(e) sortInit(expelStudentEvent) }; //this function executes all functions init(); any advice or solutions you can give would be most welcome.
  17. Thanks for the nice words and sorry for the problems! I just did this: echo ucwords('this is a test'); This Is A Test I wonder if it's because you're adding the ,<br> and then doing the ucwords(). Try it this way: $string_array = ucwords(strtolower($_POST['words'])); $array_string = explode(' ' , $string_array); $string_array = implode(',<br>' , $array_string);
  18. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- I adore your website, and just thought that there is a need to give you small feedbacks about my experience. 1) I couldn't post my html and php codes separately. 2) later, tried to add html code underneath the php code but it didn't allow me to insert anymore code to an existing one. 3) Didn't get notified about your reply. I'm very thankful for anything you do for us Larry. This forum feels like a huge rescue to me because it doesn't kick me out if I ask a question in a wrong way like other websites do. And your books are amazing!
  19. It might be working for one word but it doesn't work for the string of words. Is it supposed to work on a single word only? I apologize for not being able to post the whole code here(technical issues I guess). The idea is that you input some words separated by space. explode() converts the words to an array. Then implode() changes it back to string. after implode() happens, I need to convert the first letter of every word to uppercase. Do you think it's possible?
  20. Could you clarify what you mean when you say it doesn't work? If, for example, I do echo ucwords('test'); it returns "Test".
  21. <!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <?php $string_array = explode(' ' , $_POST['words']); $array_string = implode(',<br>' , $string_array); $array_string = ucwords(strtolower($array_string)); print "<p> Alphabetized:<br><br>$array_string</p>"; ?> </body> </html>
  22. I played around with this a bit. Again, I might entirely rethinking the logic, but assuming we want to keep two date columns, this create works: CREATE TABLE `carts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `user_session_id` CHAR(32) NOT NULL, `product_type` enum('coffee','goodies') NOT NULL, `product_id` MEDIUMINT(8) UNSIGNED NOT NULL, `quantity` TINYINT(3) UNSIGNED NOT NULL, `date_modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `date_created` DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `product_type` (`product_type`,`product_id`), KEY `user_session_id` (`user_session_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; I put `date_created` second and changed it to a DATETIME and then it can use the CURRENT_TIMESTAMP as the default so the INSERT query doesn't need to be changed.
  23. Okay, I just installed the DB and script and upgraded PHP to 7.3.8. Sadly, I am NOT seeing the error at all. This is using PHP's built-in server, although it'd surprise me if this was an Apache issue. I'm also testing this on a Mac. Unfortunately it's really hard for me to come up with a solution without being able to replicate the problem. From everything I'm reading online, having the _destroy() return a boolean solves the problem for some, but of course the code in the book already does that.
  24. Sorry for the delayed reply; had to take the time to set this all up on a server again. I ran the script with the 6 changed to 8 and it did also allow me to register. Then I realized it was probably because of the forward lookahead and the parens and where the minimum does and does not apply. Changing the minimum to apply to the whole grouping works better: if (preg_match('/^((\w*(?=\w*\d)(?=\w*[a-z])(?=\w*[A-Z])\w*)){8,}$/', $_POST['pass1']) ) { All that being said, since I wrote this edition, both the industry and my personal feelings how validating passwords has changed. If I were to do this again today, I'd just require a minimum length (say 12 characters) and not care at all what characters are in that password. With modern computers, "thisismypassword" or "this-is-my-password" is more secure than "1Ad92q" for a number of reasons.
  25. Upon re-written of the SQL below I got this error: #1067 - Invalid default value for 'date_modified' but When I removed "DEFAULT '0000-00-00 00:00:00' " the SQL ran successfully. I want to know if I am correct or not but Based on the link you sent I think I am on the way " For the first column that uses the TIMESTAMP data type in a specific table, MariaDB automatically assigns the following properties to the column: • DEFAULT CURRENT_TIMESTAMP • ON UPDATE CURRENT_TIMESTAMP. CREATE TABLE `carts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `user_session_id` CHAR(32) NOT NULL, `product_type` enum('coffee','goodies') NOT NULL, `product_id` MEDIUMINT(8) UNSIGNED NOT NULL, `quantity` TINYINT(3) UNSIGNED NOT NULL, `date_modified` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', ` date_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `product_type` (`product_type`,`product_id`), KEY `user_session_id` (`user_session_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  26. I've reviewed the MariaDB documentation for timestamp: https://mariadb.com/kb/en/timestamp/ It looks like the first timestamp column in a table has different behavior than the second. We want date_created to be automatically set on creation, but not update. We want date_modified to be automatically updated on each change. To get that behavior you'll need to change the DB and the SQL queries. Assuming we want both the date_modified and the date_created, I'd be inclined to put the date_modified column first and then populate date_created to the current timestamp upon INSERT. Or just drop the date_created column entirely and update the SQL commands accordingly.
  27. Dear all. I am having SQL issues with Table Carts and Wish_lists table on page 189, 192. the date_modified column was given error it was saying MySQL said: #1067 - Invalid default value for 'date_modified' should I just remove TIMESTAMP Data type from date_modified column and change it to DATETIME?. I am using Maria DB 10.3.15 version bundled with xampp.
  1. Load more activity
  • Create New...