Thread: Second opinion

Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    9
    Rep Power
    0

    Some advice...


    Hi All,

    I'm just messing around with PHP and have some questions on something I'm working with.

    What I want to create is a form, with 4 or 5 drop down menus of different items. The items are going to be fasteners and fixings nuts, bolts, washers(n, b, w) etc.. So there will be a drop down menu for nuts, another for bolts, another for washers, you get the idea...

    The items will be categorised into what they are (n,b,w) but there will be Metric and Imperial items in the same lists.

    Next to each list of items will be a quantity list and next to that an add to list button. Next to the form will be a table, which will act as a list, with two headings, Imperial and Metric.

    Each item will have a monetary value. When the user chooses the item from the list, selects a quantity and click add to list, I want it to place the items in another table on the same page, where it will echo and store what they have added and what they add to that after.

    So say somebody chooses a 10mm washer from the washers drop down menu, selects a quantity of 10 and hits add to list, it will add the information, (including price) to a list on the right, which will be on the same page under the Metric heading. If somebody then selects a 1/4" washer (Imperial), chooses quantity it then adds the item, quantity and price under the Imperial heading of the list. At the bottom of the list I'd like a grand total too (where it shows the sum of the two items).

    I guess what I'm trying to create is an on-screen shopping list, just without the payment, but I want it all storing on the one page, if possible. As opposed to a page for the items, a page for the cart etc.

    So a few questions:

    1.What is the best way to populate multiple drop down lists with the items? Would it be through a database?

    2. Would using the store session attribute be the best/only way to handle the chosen items?

    3. Processing the form, would it be best to use the PHP_SELF function?

    I've tried to include an example of what I'm after (as an image) but apparently as a "newbie" I can't post image URL's just yet, so I would be willing to PM you the link to the image, as I think it will show what I'm trying achieve a little better.

    Thanks in advance
    Last edited by josh_90; August 20th, 2013 at 01:53 PM. Reason: Change of title
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2010
    Posts
    153
    Rep Power
    5
    Originally Posted by josh_90

    1.What is the best way to populate multiple drop down lists with the items? Would it be through a database?
    Yes, a database is the most conventional way to load this.

    2. Would using the store session attribute be the best/only way to handle the chosen items?
    That's one way to do it. The old school way to do it is to put the submitted data in hidden form fields. The new school way is to use javascript & ajax calls to keep track of what's been clicked and never refresh the page.

    3. Processing the form, would it be best to use the PHP_SELF function?
    If you want to keep submitting back to the same form, then yes.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Dec 2004
    Posts
    2,972
    Rep Power
    375
    you shouldnt use PHP_SELF.. it can be used for attacking your form. Instead use the actual script/page name.
  6. #4
  7. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,957
    Rep Power
    1046
    Originally Posted by paulh1983
    you shouldnt use PHP_SELF.
    No, this is a misunderstanding. PHP_SELF is perfectly safe as long as you escape it -- just like any other user input.

    Trouble begins when people assume the URL is safe instead of treating it like user input (which it is).
    The 6 worst sins of securityHow to (properly) access a MySQL database with PHP

    Why can’t I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    9
    Rep Power
    0
    Hi,

    Thanks for the prompt replies all. I've got my MySQL database setup, using a table called items.

    The structure is as follows:

    id l item l value l unit l category

    Note: unit refers to Metric or Imperial.

    An example row is:

    1 l 10mm washer l 0.10 l Metric l Washer

    What would be the best way to differentiate between the different items (n,b,w) to allow me to pull the results into the various drop-down menu's? Would you recommend storing all the items in one table, just with a column called category, or something similar, where I can put the item under the correct category (as the above example shows)? Or creating different tables for the different categories, so all the nut items would be in one table, bolts in another etc. The reason I ask is I've only ever used one drop down menu within a form before, not too sure what would make it easiest to populate the different drop down menus with just that particular category.

    Depending on your suggested method, would bring another question. How would the SELECT Statement look?If you suggest the way I've currently done it, I'd use:

    SELECT * FROM items;

    Alternatively if you suggest to split the items across multiple tables, I guess it'd just be:

    SELECT *
    FROM items, table2, table3; etc etc.

    Anything wrong with using SELECT * in this example? Just thinking with the table not containing many columns (5) and rows (<50) it won't be a big query. Or do you recommend specifically calling for the colums I want (which will be all anyway)?

    Thanks for your help and time.
  10. #6
  11. Web Developer/Musician
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Nov 2004
    Location
    Tennessee Mountains
    Posts
    2,408
    Rep Power
    1031
    Originally Posted by josh_90
    1.What is the best way to populate multiple drop down lists with the items? Would it be through a database?
    Yes a database is the best choice. The only possible exception is if you have a dropdown of the 50 states or similar divisions within a country (or state like counties) in a form which at leat in terms of the US haven't and aren't going to change any time soon. If they aren't needed for some cross reference query in the db, you can load those from a text file.[/QUOTE]
  12. #7
  13. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,957
    Rep Power
    1046
    Originally Posted by josh_90
    Would you recommend storing all the items in one table, just with a column called category, or something similar, where I can put the item under the correct category (as the above example shows)?
    Yes, use a column to specify the category. Do not duplicate the table for each category, because it will be a pain keeping them synchronized (whenever you change the structure of one table, you have to do the same thing in all others).



    Originally Posted by josh_90
    How would the SELECT Statement look?If you suggest the way I've currently done it, I'd use:

    SELECT * FROM items;

    Alternatively if you suggest to split the items across multiple tables, I guess it'd just be:

    SELECT *
    FROM items, table2, table3; etc etc.
    No, this is very inefficient and error-prone.

    SELECT * is crap, because you never know what you get. Maybe you know that now, but what if rename the columns, add new ones, remove others? Your code won't reflect that, so you're almost guaranteed to get it wrong sooner or later.

    List the columns explicitly.

    This table list syntax is also bad and long obsolete. I'm not even sure if MySQL fully supports it (I'm talking about left and outer joins, which require a special annotation).

    Use proper joins:

    sql Code:
    SELECT
    	foo.x
    FROM
    	foo
    	LEFT JOIN bar ON foo.x = bar.x
    WHERE
    	...

    I suggest that you read up on SQL basics so that you don't end up with a mess of broken data and bad queries.
    The 6 worst sins of securityHow to (properly) access a MySQL database with PHP

    Why can’t I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    9
    Rep Power
    0
    Originally Posted by Jacques1
    Yes, use a column to specify the category. Do not duplicate the table for each category, because it will be a pain keeping them synchronized (whenever you change the structure of one table, you have to do the same thing in all others).

    Ok so I'll stick with the category column to distinguish between the items.

    No, this is very inefficient and error-prone.

    SELECT * is crap, because you never know what you get. Maybe you know that now, but what if rename the columns, add new ones, remove others? Your code won't reflect that, so you're almost guaranteed to get it wrong sooner or later.

    List the columns explicitly.

    This table list syntax is also bad and long obsolete. I'm not even sure if MySQL fully supports it (I'm talking about left and outer joins, which require a special annotation).

    Use proper joins:

    sql Code:
    SELECT
    	foo.x
    FROM
    	foo
    	LEFT JOIN bar ON foo.x = bar.x
    WHERE
    	...

    I suggest that you read up on SQL basics so that you don't end up with a mess of broken data and bad queries.
    Ok, perhaps I've picked up some bad habits, or am using obsolete methods. I've taken a lot of my tuition from sites that I assumed knew the standards, or updated their tutorials as statements were superseded.

    I've had a look at the MySQL documentation, as suggested. Although it's not laid out as simple/or is as easy to understand, imo (perhaps because I'm not used to reading it in this way), I want to code using current/recognised practices.

    That said, my SELECT statement now looks like this:

    sql Code:
    SELECT 
    id, item, VALUE, unit, category
    FROM items;


    What is confusing me about the documentation is (taken from the documentation):

    Code:
    SELECT
        [ALL | DISTINCT | DISTINCTROW ]
          [HIGH_PRIORITY]
          [STRAIGHT_JOIN]
          [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
          [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
        select_expr [, select_expr ...]
        [FROM table_references
        [WHERE where_condition]
        [GROUP BY {col_name | expr | position}
          [ASC | DESC], ... [WITH ROLLUP]]
    Red highlights the bits I don't think are relevant to my query, correct me if I'm wrong, but that would make the query actually look like:

    sql Code:
    SELECT
    id [, item, VALUE, unit, category]
    [FROM items];


    The part that is confusing me, is as I read the example from the documentation, I'm thinking that the first column name appears outside of the square brackets and then each subsequent column name appears inside the square brackets, separated by a comma and a space. However, in their example, I would assume that if the column name of the second and each subsequent column had to appear inside the square brackets, they wouldn't have used the same column name.

    Am I reading more into the example than I should be? Are the brackets used if the column name actually contains square brackets? Or is this how the statement should be?

    Thanks
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2010
    Posts
    153
    Rep Power
    5
    The brackets indicate optional components of the statement, they are not meant to be literally included in your SQL.
  18. #10
  19. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    9
    Rep Power
    0
    Originally Posted by admoore
    The brackets indicate optional components of the statement, they are not meant to be literally included in your SQL.
    Thanks for clearing that up admoore.

    So I now have the following php code:
    PHP Code:
    <?php
    //Database connection string
    $connection mysql_connect('localhost''****''****');
    if (!
    $connection) {
        die(
    'Could not connect: ' mysql_error());
    }
    //Choose the DB:
    mysql_select_db("****");
    //Result
    $result=mysql_query("SELECT id, item FROM items"); 
    echo 
    "<select name=nuts>"
    while(
    $row=mysql_fetch_assoc($result)) { 
       echo 
    '<option value="'.$row['id'].'">'.$row['item'].'</option>'

    echo 
    "</select>";

    mysql_close($connection);
    ?>
    It works, in as much as it shows all the items in a drop down menu. Any feedback/improvements on the above please?

    Now I want to build on this. Any pointers/stuff to read up on regarding getting a second drop down menu now, but filter the existing and the second drop down using the category column on the table, to show only the relevant items for that category?

    I've not called for the other columns in the query string at the moment, as it appears if I call for them, but don't output them anywhere, it breaks the drop down menu.

    Thanks
  20. #11
  21. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,957
    Rep Power
    1046
    Unfortunately, you got several security holes in your code, and the mysql_*() functions are long obsolete.

    It's clear to me that you're learning from bad sources. Whatever book or online tutorial you got this from: Throw it away. It will massively hamper your learning process, and you may even end up getting your server "hacked".

    Check out The 6 worst sins of security in my signature to get a basic understanding of security requirements. This particular piece of code has two vulnerabilities: In case the database connection fails, you print the exact error message on the screen. This will give attackers detailed information about your database system while irritating legitimate users. You also failed to escape the strings from the database before inserting them into the HTML document, which can lead to JavaScript injections or at least screw up your HTML. Those are just two typical mistakes. The more your application grows, the more security risks you have to consider.

    The mysql_*() functions are obsolete since almost 10 years and have officially been deprecated. This means they'll be removed sooner or later. The PHP developers have actually put up big red warning signs begging people to move to one of the modern extensions, but many outdated and bad tutorials still promote the old functions.

    The problem with those functions is that it's very hard to use them securely. Every single input value has to be manually escaped using the right function and the right character encoding -- without making any mistake at any time. This has proven to be an almost impossible task, and it has lead to a long history of security failures (both in amateur an professional code). So I strongly suggest using the modern database extensions, which have a special security feature called prepared statement.

    To give you a start, this is how you might rewrite your code:

    inc/database.php
    PHP Code:
    <?php

    $db_options 
    = array(
        
    PDO::ATTR_EMULATE_PREPARES => false                     // important! use actual prepared statements (default: emulate prepared statements)
        
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION           // throw exceptions on errors (default: stay silent)
        
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC      // fetch associative arrays (default: mixed arrays)
    );
    $database_connection = new PDO('mysql:host=localhost;dbname=YOURDB;charset=utf8''YOURUSER''YOURPW'$db_options);    // important! specify the character encoding in the DSN string, don't use SET NAMES
    inc/functions.php
    PHP Code:
    <?php

    function html_escape($raw_input) {
        return 
    htmlspecialchars($raw_inputENT_QUOTES ENT_HTML5'UTF-8');     // important! don't forget to specify ENT_QUOTES and the correct encoding
    }
    index.php
    PHP Code:
    <?php

    require_once dirname(__FILE__) . '/inc/database.php';
    require_once 
    dirname(__FILE__) . '/inc/functions.php';


    $items $database_connection->query('
        SELECT
            id
            , item
        FROM
            items
    '
    );
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <title>Test Page</title>
        </head>
        <body>
            <form action="index.php" method="post">
                <fieldset>
                    <legend>Select items</legend>
                    <label for="nuts">Nuts</label>
                    <select id="nuts" name="nuts">
                        <?php foreach ($items as $item): ?>
                        <option value="<?php echo html_escape($item['id']) ?>"><?php echo html_escape($item['item']) ?></option>
                        <?php endforeach; ?>
                    </select>
                </fieldset>
                <div>
                    <input type="submit" />
                </div>
            </form>
        </body>
    </html>
    This is what I changed:
    • I replaced the old MySQL extension with the modern PDO library.
    • I put the database stuff into a separate file so that it can be reused in different scripts.
    • I escaped the strings coming from the database to make sure they do not change the HTML document.
    • I put the PHP logic on top of the file to separate PHP and HTML as much as possible, trying to make the code more readable.
    The 6 worst sins of securityHow to (properly) access a MySQL database with PHP

    Why can’t I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  22. #12
  23. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    9
    Rep Power
    0
    Thanks for the helpful and thorough reply Jacques1. I've read up on your "6 worst sins of security" as you recommended, I must say it's informative and interesting. Had I seen it before posting my query, I'd probably not made such a hash of it!

    since certain security vulnerabilities are so common that you have to start almost every reply with the same warnings and explanations, I thought it makes sense to collect all the info in a kind of “FAQ”.
    Guess it was tailor made for the likes of me!

    Code:
    Whatever book or online tutorial you got this from: Throw it away.
    I think I may just do that, trouble is I'd have no books left, is there any modern tutorials you can recommend?

    I've looked and looked and am unable to find any modern material that explains how to setup the multiple drop down menu's which I want.

    Your test script works fine, but it doesn't categories the results as I want. Is this where arrays come in?

    Thanks
  24. #13
  25. Web Developer/Musician
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Nov 2004
    Location
    Tennessee Mountains
    Posts
    2,408
    Rep Power
    1031
    If I let it bother me too much I start going out to these blogs and other sites where these terrible coding examples are being published and raise hell. Luckily I'm not currently maintaining code done by anyone who learned from such examples or cleaning up servers hacked by people who took advantage of such vulnerabilities. That is someone else's job now.
  26. #14
  27. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,957
    Rep Power
    1046
    First of all: I find it great that you take the security risk seriously and wanna fix them. That's a good start.

    Unfortunately, it's very hard to find good PHP tutorials on the Internet. I've looked for them myself, and I really couldn't find anything I'd fully recommend. Most of them are obsolete or insecure or both.

    I think the best we can do is search for particular topics. For example, now that you know PDO, you might look for PDO tutorials. Check their code and see if they adhere to the security practices you already know. If they do, they probably know what they're doing.

    Another good way of learning is to check out old threads in communities like stackoverflow (or this one). A lot of the posts you'll see are garbage as well, but there are enough knowledgeable people to downvote the bad replies and explain what's wrong with them.



    Originally Posted by josh_90
    I've looked and looked and am unable to find any modern material that explains how to setup the multiple drop down menu's which I want.
    Do it step by step.

    This is how you might split the task into smaller problems:

    1. Create a downdown menu with only nuts. You'll need a WHERE clause in your query.
    2. After an item and a quantity has been submitted, store it in the database.
    3. Create a table listing the stored items and quantities.

    Each of those tasks is relatively simple and doesn't require any special knowledge. But if you put them all together, you've already covered a big part of the overall problem.

    Try it. And if you're stuck at some point, just ask.
    The 6 worst sins of securityHow to (properly) access a MySQL database with PHP

    Why can’t I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  28. #15
  29. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    9
    Rep Power
    0
    Originally Posted by Jacques1
    First of all: I find it great that you take the security risk seriously and wanna fix them. That's a good start.
    Well I believe in the old saying, "If you're going to do something, do it right!"

    Code:
    Unfortunately, it's very hard to find good PHP tutorials on the Internet. I've looked for them myself, and I really couldn't find anything I'd fully recommend. Most of them are obsolete or insecure or both.
    I'm glad it's not just my surfing methods and others are experiencing similar problems, just out of interest are you self taught and is this a hobby for you?

    Code:
    I think the best we can do is search for particular topics. For example, now that you know PDO, you might look for PDO tutorials. Check their code and see if they adhere to the security practices you already know. If they do, they probably know what they're doing.
    Ok, I'll give that some thought and start searching.

    Code:
    Another good way of learning is to check out old threads in communities like stackoverflow (or this one). A lot of the posts you'll see are garbage as well, but there are enough knowledgeable people to downvote the bad replies and explain what's wrong with them.
    I must admit I've noticed quite a lot of the topics posted on stackoverflow usually end up in slanging matches and the problem doesn't get solved.

    Code:
    Do it step by step.
    
    This is how you might split the task into smaller problems:
    
    
    1. Create a downdown menu with only nuts. You'll need a WHERE clause in your query.
    2. After an item and a quantity has been submitted, store it in the database.
    3. Create a table listing the stored items and quantities.
    Each of those tasks is relatively simple and doesn't require any special knowledge. But if you put them all together, you've already covered a big part of the overall problem.
    Just to clarify, I want the submitted information only to be held and displayed for the duration of that session (as soon as the user leaves the page, I want the data to vanish with it). I don't want the information to be stored. Is this still what you recommend me do?

    Thanks
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo