skip to Main Content

I have set up a mysql database through PHPMyAdmin, and can access the data through a single table using PDO in PHP. However I do not know where to begin in trying to retrieve data from a many-to-many relationship.

Here is my table structure:
image of structure

products -> one/many -> productImages <- many/one <- images

The productImages table contains a PK ID, and two foreign keys, the PK ID from the other two tables.

I know how to use PDO to retrieve information from the products table in a simple solution. Here is a reduced code snippet showing this:

<?php
$products = $mypdo->prepare('SELECT * FROM products');
$products->execute();
$products_ids[] = array();
$products_names[] = array();
$products_prices[] = array();

$i = 0;
$columnCount = 1;

foreach($products as $product)
{
    $products_ids[$i] = $product['product_ID'];
    $products_names[$i] = $product['product_Name'];
    $products_prices[$i] = $product['product_Price'];
    ?>
        //output product data in styled HTML
        <div class="example"><?php echo $products_names[$i];?></div>
    <?php

    $i++;
    $columnCount++;

    if($columnCount > 3)
    {
        $columnCount = 1;
    ?>
        //start new row using HTML/CSS
    <?php
    }
}
?>

However I want to retrieve an image_filename and image_extension from the images table, using only the product_id from the products table. The product_id is a foreign_key in the productImages table (I think this is the correct way to do it), which is also linked to an image_id from the images table. Currently all images have a single entry in productImages, and they all link to a single “placeholder image” in the images table.

I have this mysql example:

select *
from products inner join productImages
on productImages.product_ID=product_ID

And I think that it takes all entries from the productImages and products tables. My main problems with this solution are:

  1. If it is indeed taking all entries from 2 tables, I also need the entries from the third table
  2. I am not sure how a PDO object stores a prepared statement so don’t know the correct syntax to access information from each table. For example, the product_ID has the same name on 2 different tables and so do not know how to differentiate between one table or the other when using $product['product_ID'].

What I need to do is retrieve the corresponding image_name and image_extension data for each product into separated (or looped array) variables so that they can be individually output on to the page.

Am I on the right track, and so would be able to develop my code further from here? Or am I doing something fundamentally wrong and need to change my approach?

Update:

I have updated my code using the answer from Asher Gunsay. Accessing data from the third table now works! Unfortunately though, the loop does not, and the end result is that only the first product image, name, and price are displayed, with nothing afterwards. My code (edited to reduce size and keep previous naming conventions):

<?php
$products = $mypdo->prepare('
SELECT
products.product_name as product_name,
products.product_price as product_price,
images.image_fileName as image_fileName ,
images.image_fileExtension as image_fileExtension 
FROM
products
JOIN
productsimages on productsimages.product_ID = products.product_ID
JOIN
images on images.image_ID = productsimages.image_ID
');
$products->execute();
$i = 0;
$columnCount = 1;

foreach($products as $product)
{
    ?>
        //output product data in styled HTML
        <div class="example"><?php echo $product['product_name'];?></div>
        <div class="exampl2"><?php echo $product['image_fileName'];?></div>
    <?php

    $i++;
    $columnCount++;

    if($columnCount > 3)
    {
        $columnCount = 1;
    ?>
        //start new row using HTML/CSS
    <?php
    }
}
?>

I have also tried a variant more similar to my original code:

<?php
$products = $mypdo->prepare('
SELECT
products.product_name as product_name,
products.product_price as product_price,
images.image_fileName as image_fileName ,
images.image_fileExtension as image_fileExtension 
FROM
products
JOIN
productsimages on productsimages.product_ID = products.product_ID
JOIN
images on images.image_ID = productsimages.image_ID
');
$products->execute();

$products_names[] = array();
$products_prices[] = array();
$images_fileNames[] = array();

$i = 0;
$columnCount = 1;

foreach($products as $product)
{
    $products_names[$i] = $product['product_name'];
    $products_prices[$i] = $product['product_price'];
    $images_fileNames[$i] = $product['image_fileName'];
    ?>
        //output product data in styled HTML
        <div class="example"><?php echo $products_names[$i];?></div>
        <div class="exampl2"><?php echo $images_fileNames[$i];?></div>
    <?php

    $i++;
    $columnCount++;

    if($columnCount > 3)
    {
        $columnCount = 1;
    ?>
        //start new row using HTML/CSS
    <?php
    }
}
?>

However both code snippets have the same problem: only the first product from the products table is displayed. How do I fix this?

Update 2:
The code works fine. I had forgotten to add more records to my productImages table. I have posted my own answer below showing the final working solution using my naming conventions, combined with the answer from Asher Gunsay.

2

Answers


  1. Chosen as BEST ANSWER

    For reference, the answer I used combining my naming conventions with the solution provided by Asher Gunsay in his answer and comments:

    <?php
    $products = $mypdo->prepare('
    SELECT
    products.product_name as product_name,
    products.product_price as product_price,
    images.image_fileName as image_fileName ,
    images.image_fileExtension as image_fileExtension 
    FROM
    products
    LEFT JOIN
    productsimages on productsimages.product_ID = products.product_ID
    LEFT JOIN
    images on images.image_ID = productsimages.image_ID
    ');
    $products->execute();
    
    $columnCount = 1;
    
    foreach($products as $product)
    {
        ?>
            //output product data in styled HTML
            <div class="example"><?php echo $product['product_name'];?></div>
            <div class="exampl2"><?php echo $product['image_fileName'];?></div>
        <?php
    
        $i++;
        $columnCount++;
    
        if($columnCount > 3)
        {
            $columnCount = 1;
        ?>
            //start new row using HTML/CSS
        <?php
        }
    }
    ?>
    

  2. For mysql, just continue adding in joins.

    SELECT 
      A.attribute as attribute, B.otherAttribute as otherAttribute, C.more as more
    FROM
      A
    JOIN
      AB on AB.aId = A.id
    JOIN
      B on B.id = AB.bId
    JOIN
      BC on BC.bId = B.id
    JOIN
      C on C.id = BC.cId
    ...
    

    Doing it this way, you can then access the variables exactly the same as you would normally.

    // Loop through rows with each as $row
    $row['attribute']; // Corresponds to A.attribute
    $row['otherAttribute']; // Corresponds to B.otherAttribute
    $row['more']; // And so on
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search