1

I need to make a form where users can insert products in a database. The database has columns "Name", "SKU", "Type", "Attributes". The form has fields "Name", "SKU", "Price" and a select box "Type" with three options - "Furniture", "Dvd-disc" and "Book".

Additional form fields are show based on what user chooses in the "Type" selection. For example, if the user chooses "Furniture" from the select box, then three fields, "Height", "Width", "Length", appear. If he chooses "Books", a "Weight" field appears, and if he chooses "DVD-disc", the field "Size" appears.

The jQuery funcion to hide/show required fields is not implemented yet, so don't mind that.

EDIT: When I post, for example, the type Disc and Size 700, and do "var_dump($_POST);" I get:

array(8) { ["sku"]=> string(8) "BT944RUR" ["name"]=> string(22) "Third insert from page" ["price"]=> string(5) "56.25" ["type"]=> string(8) "DVD-disc" ["size"]=> string(3) "700" ["dimensions"]=> array(3) { ["height"]=> string(0) "" ["width"]=> string(0) "" ["length"]=> string(0) "" } ["weight"]=> string(0) "" ["submit"]=> string(6) "Submit" }

It collects the Size value from the form but doesn't pass it further.

HTML form:

<form action="" method="post">
    <div class="form-group">
        <label for="sku">SKU</label>
        <input type="text" class="form-control" id="sku" name="sku">
    </div>
    <div class="form-group">
        <label for="name">Name</label>
        <input type="text" class="form-control" id="name" name="name">
    </div>
    <div class="form-group">
        <label for="price">Price</label>
        <input type="text" class="form-control" id="price" name="price">
    </div>
    <div class="form-group">
        <label for="type">Disabled select menu</label>
        <select id="type" name="type" class="form-control">
            <option></option>
            <option>DVD-disc</option>
            <option>Book</option>
            <option>Furniture</option>
        </select>
    </div>
    <div class="form-group">
        <label for="size">Size</label>
        <input type="text" class="form-control" id="size" name="size">
    </div>
    <div class="form-group">
        <label for="dimensions[height]">Height</label>
        <input type="text" class="form-control" id="height" name="dimensions[height]">
    </div>
    <div class="form-group">
        <label for="dimensions[width]">Width</label>
        <input type="text" class="form-control" id="width" name="dimensions[width]">
    </div>
    <div class="form-group">
        <label for="dimensions[length]">Length</label>
        <input type="text" class="form-control" id="length" name="dimensions[length]">
    </div>
    <div class="form-group">
        <label for="weight">Weight</label>
        <input type="text" class="form-control" id="weight" name="weight">
    </div>
    <input type="submit" name="submit" id="submit" class="btn btn-default">
</form>

PHP code so far (to pass the variables to the insert):

if(isset($_POST['submit'])) {
    $sku = $_POST['sku'];
    $name = $_POST['name'];
    $price = $_POST['price'];
    $type = $_POST['type'];
    $attributes = '';

    if(isset($_POST['dimensions']) && !empty($_POST['dimensions'])) {
        $attributes = implode(' x ', $_POST['dimensions']);
    }
    else if(isset($_POST['weight']) && !empty($_POST['weight'])) {
        $attributes = $_POST['weight'];
    }
    else if(isset($_POST['length']) && !empty($_POST['length'])) {
        $attributes = $_POST['length'];
    }

    $fields = [
        'SKU'=>$sku,
        'Name'=>$name,
        'Price'=>$price,
        'Type'=>$type,
        'Attributes'=>$attributes
    ];

    $product = new Products();
    $product->insert($fields);
}

Insert function (in a different file):

    public function insert($fields) {

        $implodeColumns = implode(', ', array_keys($fields));
        $implodeValues = implode(", :", array_keys($fields));

        $sql = "INSERT INTO products ($implodeColumns) VALUES (:".$implodeValues.")";

        $result = $this->connect()->prepare($sql);

        foreach ($fields as $key => $value) {
            $result->bindValue(':'.$key, $value);
        }

        $resultExec = $result->execute();

        if($resultExec) {
            header('Location: index.php');
        }
    }

I think the if statements are wrong. I can pass the dimensions to the database in such a way but if I try to send size or weight it just passes epmty values with two "x" between them.

And additional question: can I achieve this without using conditional statements? I'm open to different approaches.

Lorkhan
  • 71
  • 7
  • Thanks for posting a good question. Dump `$_POST` so you can see exactly what you are getting. Edit your question and add that output. – ryantxr May 20 '19 at 18:17

2 Answers2

0

A few notes.

Since you're only interested if the user has submitted values, you can simplify your if statements:

if($_POST['dimensions']) {
    $attributes = implode(' x ', $_POST['dimensions']);
}
else if($_POST['weight']) {
    $attributes = $_POST['weight'];
}
else if($_POST['length']) {
    $attributes = $_POST['length'];
}

I do however wonder why you don't record height/width/length separately in the database?

If I were you, I would update my database table to reflect what you're collecting from your users (or vice versa), and do a straight insert of all columns every time a user submits a form, even if some of the fields values have been submitted empty. This has the added bonus of simplifying your life later on if/when you decide to add or remove columns in the database or front-end form.

And finally, please, please either clean the user input, or use prepared SQL statements to avoid SQL injection attacks.

dearsina
  • 4,774
  • 2
  • 28
  • 34
  • Your suggestion didn't fix the problem. I get the same result - empty strings are passed to the database. I would like to avoid creating a separate db column for each parameter because I really just need to pass them as strings and later list all the products in the index page. I would simplify things but that's not what I need to achieve. Thanks for the suggestion to clean inputs. I wanted to work on that later after I get everything else fixed. – Lorkhan May 21 '19 at 06:16
0

The problem is your first if:

if(isset($_POST['dimensions']) && !empty($_POST['dimensions'])) {

As seen in your HTML, dimension is an array of inputs: length, height, width. This means the variable will never be empty.

$dimensions = [
    'length' => '',
    'width'  => '',
    'heigth' => '',
];

echo empty($dimensions) ? 'dimensions is empty': 'dimensions is not empty'; //output: dimensions is not empty

As solution would to "clean" out nullable values from your array before testing if its empty. To do this, you can resort to array_filter

echo empty(array_filter($dimensions)) ? 'dimensions is empty': 'dimensions is not empty'; //output: dimensions is empty

demo

DarkBee
  • 16,592
  • 6
  • 46
  • 58