简体   繁体   中英

Getting specific products from database with one-to-many relationship

I am making a products catalog using mySQL and PHP framework Codeigniter 4. Here I will show a simplified example. I have two tables in my database. One has common data like product name and price. The other has various attributes like color, material etc. So one product has many attributes. Something like that:


Products

| id -- | name ----- | price -- |

| 0 --- | Chair 1 -- | 50 ----- |

| 1 --- | Chair 2 -- | 75 ----- |


Attributes

| id -- | product_id -- | attribute -- | value -- |

| 0 --- | 0 ------------ | color ------ | black -- |

| 1 --- | 0 ------------ | size -------- | small -- |

| 2 --- | 1 ------------ | color ------ | white -- |

| 3 --- | 1 ------------ | size -------- | large -- |


My problem involves getting specific products, as when there is a filter of products and the user wants to see all products with certain attributes. If I need to get one product with one attribute, I have no problem with that. I do this:

$product = $productsModel->join('attributes', 'attributes.product_id = products.id')
                         ->where('attribute', 'color')
                         ->where('value', 'black')
                         ->find();

However I cannot get products according to multiple attributes. Like if I need a chair that is black and small, I cannot add ->where('attribute', 'size')->where('value', 'small') because color and size are different rows. It is easy to see if I use the same join and try to get the product with id 0. The result is:

Array
    (
        [0] => Array
            (
                [id] => 0
                [name] => Chair 1
                [price] => 50
                [product_id] => 1
                [attribute] => color
                [value] => black
            )    
        [1] => Array
            (
                [id] => 1
                [name] => Chair 1
                [price] => 50
                [product_id] => 0
                [attribute] => size
                [value] => small
            )    
    )

Any idea how to solve this problem? I need to create a filter with checkboxes that will display all available attributes of products and allow users to search for any combination.

In raw MySQL your current query reads:

SELECT products.*
FROM products 
INNER JOIN attributes ON attributes.product_id = products.id
WHERE attribute = 'color' AND value = 'black';

Adding a second join could look something like this:

SELECT P.*
FROM products AS P
INNER JOIN attributes AS A1 ON A1.product_id = P.id
INNER JOIN attributes AS A2 ON A2.product_id = P.id
WHERE A1.attribute = 'color' AND A1.value = 'black' AND
      A2.attribute = 'size'  AND A2.value = 'small';

See: https://www.mysqltutorial.org/mysql-inner-join.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM