Jump to content
Larry Ullman's Book Forums


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Matt

  1. Thanks Larry! My case is simpler because it's a service, so there is no shipping info. I will do it with sessions then. Matt
  2. Larry, I had a quick question about the checkout process in Example 2 of the book. Is it possible to use sessions to store data between the pages (i.e. shipping, billing, etc...) and inserting the data in the database at the end rather than after each page is completed? There are two benefits that I can see from using this approach: 1) There will not be any uncompleted orders in the database if the user decides to back out at the last minute. 2) The user can go back and change their information at any time in the process by clicking the link at the top for each checkout step. Is this a sound way of doing it or are there any logistics problems that might come up? Thanks, Matt
  3. Larry, Thank you very much for the endorsement of my code! I know we don't always agree on everything (usually it just has to do with the way we approach things), but it really means a lot to me! Excellent point, Larry! I didn't think about that! Thanks again, Matt
  4. Larry, Thanks for the reply! As far as what happens when the session is lost, when the user returns all the data will be queried again and loaded into the session. I took out the database queries to make the code shorter, so it wasn't obvious. Basically, the code is essentially the same as yours, but instead of working directly with the database, most of the communication is done with the session. It is acting as a kind of intermediary between the user and the database. When the user first goes to the site and a function is called to get some information from the cart, like get_cart_count(), that function will check if the 'cart' array is set in the session. If it's not, it will call set_cart() which will then call get_cart_contents() where the database query is performed. The data returned will be added to the session by set_cart(). From that point on, all calls to get information from the user's cart will get it from the 'cart' session variable. The database will only ever be queried again if the user either adds or removes an item from their cart. Of course, if the user closes their browser and returns, then the database will have to be queried again and the session variable recreated, but the cart data will still be there. So far it is working great! Since it is getting almost everything from the session, it is lightening fast as well! Good point about the 'no such product' message. I didn't think about that. I will add it! Thanks Larry!
  5. Larry, Thanks for the advice! I thought about the things I need the cart to do over the weekend and I came up with the following list: 1) On every page that contains a link to the cart (which is almost every one), the count of products in it should be visible. 2) Users should be able to add / remove items from the cart and have the product count update immediately. 3) Queries to the database should be minimized so that the cart information is queried only when an item is added / removed. The solution I came up with was quite simple: store everything in a session variable! I created a file called cart_functions.inc.php and I include it on every page that has a link to the cart, including the shopping cart page itself. Also, I am not using stored procedures, so functions in this file acts as the model as well. Here is the code for it: function get_cart_count($uid) { if (!(Session::get('cart'))) { set_cart($uid); } $cart_count = count(Session::get('cart')); return $cart_count; } function add_to_cart($uid, $product_id) { // Code for inserting an item into the database set_cart($uid); // $result is equal to "true" or "false" depending on insert success return $result; } function remove_from_cart($uid, $product_id) { // Code for deleting an item from the database set_cart($uid); // $result is equal to "true" or "false" depending on delete success return $result; } function get_cart_contents($uid) { // Code for getting the cart from the database } function set_cart($uid) { if (!(Session::get('cart'))) { $cart = get_cart_contents($uid); if (is_array($cart) && count($cart) > 0) { Session::set('cart', $cart); } else { Session::set('cart', 0); } } } function get_cart($uid) { if (!(Session::get('cart'))) { set_cart($uid); } $cart = Session::get('cart'); return $cart; } Then, at the top of each page which has a link to the cart I just do the following: set_cart($uid); $cart_count = get_cart_count($uid); Since the data is used on almost every page, this is a perfect case for storing the data in the session. The user may not even look at their shopping cart during a visit, but the count data will be available, and if they do a search for a product, then I can use the data in the session do display a message if the item is already in the cart. As far as displaying a message if the item doesn't exist, I could do it if the add_to_cart() function returns "false", but the only way this would happen is if the user were trying to break the site by passing in a random product id. Should I display a message anyway? Larry, please let me know what you think about this. I have already implemented it and it works great, but let me know if you see any potential problems that could happen. Because this section of the site deals with sales, I want to make sure that it is solid! If you give me the "green light" on it, I can then move forward with the checkout! Thanks Larry, Matt
  6. Larry, I have created a shopping cart using the code in the book, but I had a question about how to optimize the queries. I wanted to add a check to ensure that a product id actually exists in the product's table before adding it to the cart. I decided to do the check to make sure that a record with the user_session_id and product_id doesn't already exist in the carts table as a separate query. My site only allows one of each product to be in a user's cart at any time, so I don't need to update the quantity if they try to add the same product again. If the result is empty, then I do a check to make sure that the product exists in the products table. If it does, then I do the insert into the carts table. The problem is that now I have 3 queries just to do an insert into the carts table. I want to do the query on the products table and the insert query together. I did some research into this and there a few options: The first creates a temp table where the values don't exist in an inner query result: INSERT INTO carts (user_session_id, product_id) SELECT * FROM (SELECT '34hu4hr78wrhu', '18') AS tmp WHERE NOT EXISTS ( SELECT user_session_id FROM carts WHERE user_session_id = '34hu4hr78wrhu' AND product_id = '18' ) LIMIT 1; There is INSERT IGNORE, but I have heard that it just creates a warning if the record exists and then aborts, which is a little hacky to me. There is also INSERT... ON DUPLICATE KEY IGNORE, but I have heard that it can have strange behavior on InnoDB tables. The AUTO_INCREMENT column gets incremented even on failed attempts. This also happens with INSERT IGNORE! Then, there is this DUAL thing I have been hearing about. What is that and why would you use it? Anyway, I just want to find a way to combine these queries so that they will be more efficient. What is the best way to approach this Larry? Thanks for any help or advice you can give! Matt
  7. Abigail, Good to hear that you have it sorted out! Yeah, I don't think having them fill out the information again is a big deal if they won't be coming back to the site often. Matt
  8. Abigail, The thanks for the reply! With my site, I am actually dealing with people's services. At any time they can choose to stop providing their services or be blocked if they are doing something they shouldn't be doing. I need to make sure that everything is current at all times, especially during checkout. That being the case, I think I am going to check that the person is available when I add them to the shopping cart and process the customer's order at checkout. I also thought about using sessions, however, once the user closes their browser all shopping data in the session will lost, so I went with the cookie and database solution Larry uses in his book. If you are having problems with orders being placed and put into the orders table, but inventory not being updated correctly when the server is down, then you should probably be using transactions for this. This sounds like it could cause some serious problems with data integrity. Matt
  9. Abigail, I am building a checkout system and have been doing a lot of research on this very subject. As a general rule do not force your users to register and login to make a purchase. It is a distraction that can cause them to stop finishing the checkout process. Statistics show that this is one of the biggest reasons why users do not complete an online purchase. Instead, give them a link somewhere at the top where they can chose to login if they already have an account and they want to save time and use the billing information they have already entered previously. If not, then they will have to enter that information again. There are also sites that auto detect if a user is already in the system by checking if the email address they have entered is already in the database. If it is, then it prompts them to login, but they can choose to ignore it and continue the checkout as a guest. Matt
  10. Larry, I had a question about the shopping cart in the Example 2 site. I have implemented a similar shopping cart using your code and it works fine. I have discovered a potential problem though. When a user adds an item to the shopping cart it does check to make sure that it has a product id that is a positive integer and a type that is either set to 'coffee' or 'goodies' but, it does not make sure that the product actually exists in the 'general_coffees', 'specific_coffees', or 'non_coffee_products' tables. Of course, this shouldn't happen under normal circumstances, but if a user were to try and change the product id in the get request for adding a product to the cart, this might cause a problem. I think it would be fine for displaying the cart, because any product id not found in any of those tables won't return a result and therefore won't be displayed. However, when the user goes to checkout, it might generate an error. Is it good to add another query to the 'add_to_cart' stored procedure which first checks to see that the product actually exists before adding it to the carts table? Also, should we check to make sure the product exists again when displaying the cart at checkout? Doing this will slow the process down a bit, but will help data integrity! I have also found a way to combine both the insert and select queries together, so that it will only insert a product if the id is found in the result set of the select subquery. What do you think? Thanks, Matt
  11. Larry, Thanks for that! I have implemented the robots.txt file. Matt
  12. Larry, I just had a quick question. I implemented the separate page for handling login requests and it was pretty easy! Is there anything I can do to make sure that search engines don't index the 'login' (and 'logout') pages as well as handling it when a user tries to access the page directly? Thanks, Matt
  13. Larry, Thanks a lot for the detailed explanation! That clears everything up and I will implement the forms the way you suggested! Matt
  14. Larry, Thanks for the great advice! So, just to clarify, I would set the action of the login form to go to another page for processing and then redirect to a default page on successful login (which I do anyway). This makes perfect sense as the 'logout' link does exactly the same thing, even though it isn't actually a form. When a user fails their first attempt at login, I redirect them to a dedicated 'Login' page (similar to what Facebook and this forum does). In that case, I could just use the usual way of listening for the $_SERVER['REQUEST_METHOD'] === 'POST' as I have been doing since there won't ever be another form on that page. For the other public facing forms, I could just use AJAX, even though progressive enhancement would suffer. The problem is, once a user is logged in there are a couple long forms for updating profile information and settings. In those cases I could submit the form to a different page and then redirect back to the original page like you suggested, but there is a problem, which is how to get the errors back to the original form as well so that they can be displayed to the user? Thanks again, Matt
  15. Larry, I had a quick question! I have a login form similar to the one in example 1 of the book. It appears on several of the public pages, however, I also sometimes have another form in the content area of the same page. What is the current best practice for determining which form has been submitted when there are multiple forms on the same page? Obviously, this is not going to cut it: if ($_SERVER['REQUEST_METHOD'] === 'POST') { process form... } I have heard that there are a couple ways of doing this: 1) Include a hidden field with a unique name in the form and look for it in the $_POST array. 2) Give each submit button a unique name and look for it in the $_POST array. The problem with the first option is that it creates extra markup in the page, but this is probably ok. The problem with the second is that in older versions of IE, if a user hits the 'Enter' key to submit a form, the submit button's name will not appear in the $_POST array. What do you do in this situation? Thanks for any help or advice you can give? Matt
  16. Larry, Thanks for the reply! So I should do it with a .htaccess file (I'm on a hosted server)? Thanks, Matt
  17. Larry, Sorry for the late reply! Thanks for the advice! I agree that the HTML should be simple, but I think users almost expect it nowadays. I have looked into this and I also found out about Campaign Monitor. I will try it! Thanks, Matt
  18. Larry, I was reading the section in the book about gzipping files, but it seems like it is more directed towards compressing text/database output. What I want is to gzip all html, css, and image files before sending them to the browser. I have done some research on this topic and it seems there are a few ways to do it. I heard that it can be done with a directive in an .htaccess file also. What is the best practice for gzipping site resources before sending them to the client? Thanks, Matt
  19. Larry, Thanks for your help! So I should put a .htaccess file in each folder where I want to change a setting? That makes sense! Thanks again, Matt
  20. @Larry - Thanks for the info about Digital Ocean! It sounds great! @Jonathan - Thank you for recommending Mandrill! I got phpMailer and Mandrill set up without a problem and was sending mail after very little work! Also, I wanted to ask you guys if we should use html email? I know Larry does in the book, but I found out that complex layout can be difficult (because of inconsistencies among mail clients) and that some clients mark html email as spam. Thanks, Matt
  21. Larry, I was thinking about protecting directory browsing on the site as a whole and what I've learned is that you can put the following into the top level .htaccess file: Options -Indexes In the folders where I don't want to allow file access at all (i.e. inc, utilities, etc...) I thought I could add the rest of the settings you have in the book. What's the best way to approach this? Thanks, Matt
  22. Larry and Jonathan, Thanks for the replies! It sounds like Digital Ocean is a good choice for a web host. Thanks for telling me about them! Matt
  23. Larry, Thanks for looking at the code! I ended up getting rid of the http_response_code stuff as it wasn't really necessary for the form to function correctly. Also, what should I be checking for with the name and message fields (I can't use a regex because the form allows both English and Japanese to be entered)? Thanks, Matt
  24. Thank you both for the help! I am going to install phpMailer and see how it goes! As far as Digital Ocean, it sounds good, but is it the kind of host you would put a business on, or is it more of a "casual" type of host? Matt
  25. Larry, Thanks for the advice! I wasn't thinking when I did that, and I looked at the Javascript/Ajax section of the E-Commerce book and you actually use a folder called "ajax". Sorry for not checking that!
  • Create New...