Click here to Skip to main content
16,022,309 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello everyone,

I’m working on a PHP web application where administrators can upload products via admin_dashboard.php, and these products are displayed on the main page onlineshop.php. The upload seems to be working fine, as the images are being saved in the correct directory, and the product information is stored in the database. However, the images are not displaying on both admin_dashboard.php and onlineshop.php.

Here are the relevant details:

1. Directory Structure:

/var/www/html/online_shop/
    ├── adminaja/
    │   ├── admin_dashboard.php
    │   ├── login.php
    │   └── register.php
    ├── onlineshop/
    │   └── onlineshop.php
    └── photo_product/
        └── [uploaded_images]


2. PHP Version: 8.0
3. MySQL Version: 8.0
4. Apache Version: 2.4


admin_dashboard.php:
<pre><?php
session_start();

if (!isset($_SESSION['user_id'])) {
    header("Location: login.php");
    exit();
}

$conn = new mysqli('localhost', 'appuser', 'password', 'online_shop');

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    if (isset($_FILES['image'])) {
        $name = $_POST['name'];
        $description = $_POST['description'];
        $price = $_POST['price'];

        $target_dir = "/var/www/html/online_shop/photo_product/";
        $imageFileType = strtolower(pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION));
        $uniqueFilename = uniqid() . '.' . $imageFileType;
        $target_file = $target_dir . $uniqueFilename;
        $relative_path = "photo_product/" . $uniqueFilename;
        $uploadOk = 1;

        // Check file size (optional: 500KB)
        if ($_FILES["image"]["size"] > 500000) {
            echo '<div class="alert alert-danger" role="alert">Sorry, your file is too large.</div>';
            $uploadOk = 0;
        }

        // Allow certain file formats (optional: JPG, JPEG, PNG, GIF)
        $allowed_extensions = array('jpg', 'jpeg', 'png', 'gif');
        if (!in_array($imageFileType, $allowed_extensions)) {
            echo '<div class="alert alert-danger" role="alert">Sorry, only JPG, JPEG, PNG & GIF files are allowed.</div>';
            $uploadOk = 0;
        }

        if ($uploadOk == 0) {
            echo '<script>setTimeout(function(){ document.getElementsByClassName("alert")[0].style.display="none"; }, 2000);</script>';
        } else {
            if (move_uploaded_file($_FILES["image"]["tmp_name"], $target_file)) {
                $sql = $conn->prepare("INSERT INTO products (name, description, price, image) VALUES (?, ?, ?, ?)");
                $sql->bind_param('ssds', $name, $description, $price, $relative_path);

                if ($sql->execute()) {
                    echo '<div class="alert alert-success" role="alert">Product added successfully</div>';
                } else {
                    echo '<div class="alert alert-danger" role="alert">Error: ' . $sql->error . '</div>';
                }

                $sql->close();
            } else {
                echo '<div class="alert alert-danger" role="alert">Sorry, there was an error uploading your file.</div>';
            }
        }
    } elseif (isset($_POST['delete_product_id'])) {
        $product_id = $_POST['delete_product_id'];

        // Fetch the image path before deleting the product
        $sql_fetch_image = $conn->prepare("SELECT image FROM products WHERE id = ?");
        $sql_fetch_image->bind_param('i', $product_id);
        $sql_fetch_image->execute();
        $sql_fetch_image->bind_result($image_path);
        $sql_fetch_image->fetch();
        $sql_fetch_image->close();

        // Delete the product
        $sql = $conn->prepare("DELETE FROM products WHERE id = ?");
        $sql->bind_param('i', $product_id);

        if ($sql->execute()) {
            // Delete the image file from the server
            $file_to_delete = "/var/www/html/online_shop/" . $image_path;
            if (file_exists($file_to_delete)) {
                unlink($file_to_delete);
            }
            echo '<div class="alert alert-success" role="alert">Product deleted successfully</div>';
        } else {
            echo '<div class="alert alert-danger" role="alert">Error: ' . $sql->error . '</div>';
        }

        $sql->close();
    }
}

$sql_fetch_products = "SELECT * FROM products";
$result = $conn->query($sql_fetch_products);
$conn->close();
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Admin Dashboard</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1 class="mt-4 mb-4">Admin Dashboard</h1>

        <div class="card mb-4">
            <div class="card-header">
                Add Product
            </div>
            <div class="card-body">
                <form method="POST" enctype="multipart/form-data">
                    <div class="form-group">
                        <label for="name">Name:</label>
                        <input type="text" class="form-control" id="name" name="name" required>
                    </div>
                    <div class="form-group">
                        <label for="description">Description:</label>
                        <textarea class="form-control" id="description" name="description" rows="3" required></textarea>
                    </div>
                    <div class="form-group">
                        <label for="price">Price:</label>
                        <input type="text" class="form-control" id="price" name="price" required>
                    </div>
                    <div class="form-group">
                        <label for="image">Image:</label>
                        <input type="file" class="form-control-file" id="image" name="image" required>
                    </div>
                    <button type="submit" class="btn btn-primary">Add Product</button>
                </form>
            </div>
        </div>

        <h2 class="mb-4">Manage Products</h2>
        <div class="card-columns">
            <?php
            if ($result && $result->num_rows > 0) {
                while ($row = $result->fetch_assoc()) {
                    echo '<div class="card">';
                    echo '<img src="/online_shop/' . $row['image'] . '" class="card-img-top" alt="Product Image">';
                    echo '<div class="card-body">';
                    echo '<h5 class="card-title">' . $row['name'] . '</h5>';
                    echo '<p class="card-text">' . $row['description'] . '</p>';
                    echo '<p class="card-text">Price: ' . $row['price'] . '</p>';
                    echo '<form method="POST" onsubmit="return confirm(\'Are you sure you want to delete this product?\');">';
                    echo '<input type="hidden" name="delete_product_id" value="' . $row['id'] . '">';
                    echo '<button type="submit" class="btn btn-danger">Delete</button>';
                    echo '</form>';
                    echo '</div>';
                    echo '</div>';
                }
            } else {
                echo '<p>No products found.</p>';
            }
            ?>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
</body>
</html>


onlineshop.php:

<?php
session_start();

$conn = new mysqli('localhost', 'appuser', 'password', 'online_shop');

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

$sql_fetch_products = "SELECT * FROM products";
$result = $conn->query($sql_fetch_products);
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Online Shop</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1 class="mt-4 mb-4">Online Shop</h1>

        <div class="card-columns">
            <?php
            if ($result && $result->num_rows > 0) {
                while ($row = $result->fetch_assoc()) {
                    echo '<div class="card">';
                    echo '<img src="/online_shop/' . $row['image'] . '" class="card-img-top" alt="Product Image">';
                    echo '<div class="card-body">';
                    echo '<h5 class="card-title">' . $row['name'] . '</h5>';
                    echo '<p class="card-text">' . $row['description'] . '</p>';
                    echo '<p class="card-text">Price: ' . $row['price'] . '</p>';
                    echo '</div>';
                    echo '</div>';
                }
            } else {
                echo '<p>No products found.</p>';
            }
            ?>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
</body>
</html>


The Issue:

Despite the image files being successfully uploaded to the photo_product directory and the product information (including the image path) being stored in the database, the images are not displayed on either admin_dashboard.php or onlineshop.php.

Potential Causes:

1.Incorrect image paths in the HTML src attribute.
2.Issues with file permissions.
3.Path discrepancies between server-side paths and web-accessible paths.

Additional Information:

1.Apache configuration sets the DocumentRoot to /var/www/html/online_shop/adminaja.

2.The images are stored in /var/www/html/online_shop/photo_product.

How can I ensure the images are displayed correctly on both pages? Any insights or suggestions would be greatly appreciated!

What I have tried:

1.Verified the upload directory permissions.
2.Checked the database entries to ensure the image paths are stored correctly.
3.Confirmed that the files exist in the photo_product directory.
Posted

1 solution

Hello misbahkuy !

you are stuck at 'debug level' , by Php you have few functions to organize 'debug' :

the 'print_r( $_var );' function can dig and display all contents in all types of vars .
this function works with Objects , Arrays and all the others vars through Php .
the 'r' in this function is about 'Recursion' , obviously the 'print_r()' function can fetch in n-dimensions Arrays , and in Objects hierarchy by Design .

PHP
print_r($result);
// put that instruction just after $result built , you'll be able to check all the contents , before using that in the loop for display/echo.
// a Tree of values will be display for $result , and you will be able to check $result deeply .

That all about debug until now .
I take few more lines to make you advices :

PHP
if ($result && $result->num_rows > 0) {
                while ($row = $result->fetch_assoc()) {
                    echo '<div class="card">';
                    echo '<img src="/online_shop/' . $row['image'] . '" class="card-img-top" alt="Product Image">';
                    echo '<div class="card-body">';
                    echo '<h5 class="card-title">' . $row['name'] . '</h5>';
                    echo '<p class="card-text">' . $row['description'] . '</p>';
                    echo '<p class="card-text">Price: ' . $row['price'] . '</p>';
                    echo '</div>';
                    echo '</div>';
                }
            } else {
                echo '<p>No products found.</p>';
            }
// that your script , ok.

PHP
if ($result && $result->num_rows > 0) {
   $output = "" ;// temp for the 'output'
                while ($row = $result->fetch_assoc()) {
                    $output .= '<div class="card">'; // completing 'output'
                    $output .= '<img src="/online_shop/' . $row['image'] . '" class="card-img-top" alt="Product Image">';
                    $output .= '<div class="card-body">';
                    $output .= '<h5 class="card-title">' . $row['name'] . '</h5>';
                    $output .= '<p class="card-text">' . $row['description'] . '</p>';
                    $output .= '<p class="card-text">Price: ' . $row['price'] . '</p>';
                    $output .= '</div>';
                    $output .= '</div>';
                }
                echo $output ; //sending 'output' by echo to the php main buffer, before 'server' answer to 'client'
// by using a temporary var to be fill by all values , you'll be less on 'echo' use.
// echo is 'Php Buffer for global output' , when using echo , Php core add all 'right-sides' parts to the 'output system buffer' . to say that you can have just 'one echo' use in the page you are creating. ( belonging the need ) . it's possible to have thousand of Html codelines , and just one 'echo' to achieve and conclude with the page build .  
            } else {
                echo '<p>No products found.</p>';
            }


_another detail about Php_ :

when using 'super global vars' $_GET / $_POST / $_SERVER / $_COOKIE , and the others ,
keep in mind those vars are :
- arrays : you can fetch all those by a loop of your choice .
- in code use : they are used in all Php Scope , no limits with those super global 'vars'
- its contents and values : you don't need to copy them in one another vars

PHP
$twins = $_POST['the_data_I_need'] ; 
//$twins is useless for a simple instruction like that.
// you have to integrate $_POST['the_data_I_need']
// when you do "A = B ;"
// you are copying the value in another Memory slot , it's useless and a memory consumer.
// JUST keep 'super global vars' as they are , you'll be more on Php implemetation
// less codelines for nothing for a better Php use , and a better server resources use too



- OOPs / Classes / Objects :

Php is OOPs friendly , you can build classes , try to build a short 'conn' or 'DB' class , and use it every time you need it.
You will gain a lot of times, and your 'code design' will be more simple.
PHP
Class DB{

private $server;
private $db;
private $user;
private $pwd ;

private $conn ;
private $result ;

public function __construct($se , $dbase , $usr ; $pass){

$this->server = $se ;
$this->db = $dbase ;
$this->user = $usr ; 
$this->pwd = $pass ;

$this->conn = new mysqli($this->server, $this->db, $this->pwd, $this->user);

}

public function execute_query( $the_query ){

$this->result = $this->conn->query( $the_query );
return $this->result ;

}
}

by using this Class :
PHP
<?php

$myDB = new DB($se,$Dbase,$user,$pwd)
$datas_all_in = $myDB->execute_query("select * from TABLES") ;
//

// DO stuff with $datas_all_in

// and to erase , and clean memory :
unset( $myDB , $datas_all_in );
// good habits , best practices .
// It destroy vars before leaving the Php whole scripts.
// your server will like it every times .

?>
 
Share this answer
 
v4
Comments
misbahskuy 26-Jun-24 0:38am    
I applied the suggestions we discussed:

1.Debugging with print_r(): Used it to inspect data structures, but still facing issues.

2.Efficient Output Handling: Consolidated output with a $output variable, but output isn't as expected.

3.OOP Principles: Implemented a DB class for better organization, but encountering database interaction problems.

Could you please advise on resolving these issues? Your help is appreciated.
[no name] 26-Jun-24 3:15am    
for th -1 , and more about 'print_r($var)';

you can display all vars living in your php scopes.
print_r($sql-query) ;
print_r($my_big_array) ;
print_r($all_objects_contents) ;

about -2 :
you surely misplaced ".=" or "=" ... those twos are not same.
"=" is for initialization of a var , kind of header, or outside a loop use. ( header / starter for $output ).
when 'in the loop' , you have to use ".=" , the concatenation operator , to add all new 'html' to the current $output , once you are out of the loop : go by "echo $output;"

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900