How would I use PDO+PHP to retrieve data from a table connected by a many-to-many relationship, using the primary key from the first table?

Denver Thomas :

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?

Asher Gunsay :

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=31623&siteId=1