Eddy
Eddy

Reputation: 51

How to view persons profile when their name is clicked in the table? php database

Basically I am building this site/portal where a user is able to log in, fill out some information and store it (stores in the database). There is also admins. When admin logs in it opens up an admin page which has a table of all registered users on the site. What I need to to is when an admin presses on the name from the table (or button that says "view profile") it stores the email of the user in $_SESSION['email'] and id of the user in $_SESSION['user_id'] after which it redirects him to the profile overview page where it (using the email and user id) pulls up all the information from database about the user.

Now the problem... Currently I can't wrap my mind around how it would know which data to save in the new variables, and how it would save it exactly since it's only printing out data (as far as I know) while it builds the table, after which I don't think theres a way to isolate rows and basically say that "if this user was clicked, pick the email that was on the same row, as well as his id".

Here is my php. (first part is at the very top of the page. And the second part is the php thats inside the html body

<?php
  // The user is redirected here from login.php.
  session_start();// Start the session.
  // If no session value is present, redirect the user:
  if (!isset($_SESSION['id'])) {
    exit;
  }

    // Print a customized message
    echo "<img src=\"skcac_logo.png\" alt=\"SKCAC Logo\" width=\"300px\">";
    //<p align='right'><a href=\"logout.php\">Logout</a></p>";

    //connect to database
    require ('mysqli_connect.php');
    //make the query
    $q = "SELECT id, CONCAT(lastName, ', ', firstName) AS name, email FROM 
    Client ORDER BY lastName ASC";
    $r = @mysqli_query($dbc, $q);

    //count the number of returned rows
    $num = mysqli_num_rows($r);

second part

<?php

      if ($num > 0)
      {
          //print how many users there are
          echo "<p> There are currently $num registered participants.</p>";

          //table header
          echo '<div class="col col-2"></div>
                <div class="col col-8 table_div"><table class="table">
                <thread>
                <tr>
                  <th scope="col" align="center">ID</th>
                  <th scope="col" align="center">Name</th>
                  <th scope="col" align="center">Email</th>
                </tr>
                </thread>
          <tbody>';

          //Fetch and print all the records:
          while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC))
          {
              echo
                  '<tr>
                    <td align="center">' . $row['id'] . '</td>
                    <td align="center"><a class="client_name" href="client_profile_overview.php">' . $row['name'] . '</a></td>
                    <td align="center">' . $row['email'] . '</td>
                    <td align="center"><button type="button" class="btn btn-default btn-sm view_profile_btn" id="view_profile_btn">View Profile</button></td>
                  </tr>';
              if (isset($_POST['view_profile_btn']))
              {
                  $_SESSION['participants_id'] = $row['id'];
                  $_SESSION['participants_name'] = $row['name'];

                  redirect_user('client_profile_overview.php');
              }
          }
          //close the table and free up the resources.
          echo '</tbody></table></div>
           <div class="col col-2"></div>';
          mysqli_free_result($r);
      }
      else //if no records were returned
      {
          //Public message
          echo '<p class="error">There are currently no registered users.</p>';

          //debuggin message
          echo '<p>' . mysqli_error($dbc) . '<br><br>Query: ' . $q . '</p>';
      }//end of if ($r) IF
      ?>'

Upvotes: 0

Views: 3157

Answers (3)

Xer Charles
Xer Charles

Reputation: 251

You can rather use a GET Method in order to redirect the id of selected profile to client_profile_overview.php page by using <a href="client_profile_overview.php?rowid='.$row['id'].'">View Profile</a> instead of button.

From there, you can perform a select query to retrieve and print the necessary details. $sql = "SELECT id, firstName, lastName, email FROM Client WHERE id ='.$_GET['rowid'].' LIMIT 1";

Upvotes: 0

PajuranCodes
PajuranCodes

Reputation: 481

Here is my solution proposal to the task you asked.

The working principle:

... is based on the clear separation between the admin and the client functionalities (see the paragraph entitled "File system structure" in the code part below):

In the admin area:

  • The admin logs-in (in admin/login.php). If the operation is successful, then the $_SESION['adminId'] value is set and the admin is redirected to the clients list page (admin/index.php).
  • In the clients list page, the $_SESION['adminId'] value is validated. If not valid, the admin is redirected to the admin login page (admin/login.php).
  • The clients list table is enclosed in a form. Each record contains a submit button - View profile - which holds the corresponding client id as the value attribute.
  • When the admin clicks on the View profile button, the form is POST-submitted to self (e.g. to admin/index.php). The posted client id is read, the $_SESION['clientId'] value is set, and the admin is redirected to the client profile page (client/profile_overview.php).
  • The logout button redirects to the admin/logout.php page.

In the client area:

  • In the client's profile overview page (client/profile_overview.php), the $_SESION['clientId'] value is validated. If not valid, the user (admin OR client) is redirected to the client login page (client/login.php). Otherwise the $_SESION['clientId'] value is read and, based on it, the client details are fetched from the database and displayed.
  • The logout button redirects to the client/logout.php page.

Resources for both areas:

These are contained in separate folders, like includes (for the php resources needed to be included - db connection, functions, error handlers, etc), images (used overall), etc.

Some suggestions:

  • The code contains my own naming conventions. In principle, maintain your established conventions over all of your pages. See Clean, high quality code guide.
  • Don't create (e.g. output, print) html code from php code/constructs.
  • Separate the db querying code (top) from the html code (bottom).
  • Use the object-oriented MySQLi library, not the procedural one. For example, use fetch_array instead of mysqli_fetch_array.
  • Don't suppress any errors (like with @ operator, as in @mysqli_query). Let the errors be catched and handled. See this and this for a proper error/exception handling.
  • Don't send anything more than id's between pages. All other details (emails, names, etc) are to be fetched from the db in the target pages.
  • Try to send POST requests whenever possible.
  • If not really needed to be displayed, but only to have the values referenced, the id columns in tables should be hidden. If not needed at all, they should not be created at all.
  • You had a typo: it is thead tag, not thread.
  • Please note that the number of th's in thead must be the same as the number of td's in tbody.
  • For client-side formatting tasks use css classes and css rules. And, of course, avoid using deprecated attributes - for example, the align attribute is not supported in HTML5. Always check caniuse.com for elements/classes/rules availability/compatibility.
  • If you have the View profile buttons, then you don't really need the anchors on the client names column. Though, in the constellation of your task, if you still want to use anchors, then you have two options. The simplest one: to send a GET request, passing the client id as query string value. The complicated option: For example, you'd have to create hidden inputs to hold the client id's, and to POST the corresponding one using the javascript submit() function. But that would mean that your code would have to create a lot of hidden inputs (number equal with the number of clients in the clients list). And, if you would also need to display the client id's in the ID column, then you'd need to use text inputs instead and to format them to appear as normal table cell text. In my code I kept it simple: no client name column anchors. Though, if you still want to choose another option, I could show it to you to a later time.
  • Tip: you might want to use Font-Awesome icons in the buttons (maybe instead of the button texts).
  • Tip: you might want to use DataTables for elegantly displaying and handling tables data.
  • Compared with the query operation performed in the clients list page (admin/index.php) - where no user input is passed to the sql statement, in the client's overview page (client/profile_overview.php) you will notice that the sql statement is prepared. Only after this operation are the user input values - here the client id - passed to it, e.g. bound into it (with bind_param()). This technique is used to avoid the so-called SQL injection, and you should always use it when user input values are to be passed to sql statements. See this answer too.
  • Please search for "@todo" in my code and act accordingly.

File system structure:

admin
    index.php
    login.php
    logout.php

client
    login.php
    logout.php
    profile_overview.php

images
    skcac_logo.png

includes
    connection.php
    functions.php

includes/functions.php:

<?php

/**
 * Redirect to the given location.
 * 
 * @param string $location Target page location.
 */
function redirect($location) {
    header('Location: ' . $location);
    exit();
}

includes/connection.php:

<?php

// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'yourdb');
define('USERNAME', 'youruser');
define('PASSWORD', 'yourpassword');

/*
 * Enable internal report functions. This enables the exception handling, 
 * e.g. mysqli will not throw PHP warnings anymore, but mysqli exceptions 
 * (mysqli_sql_exception).
 * 
 * MYSQLI_REPORT_ERROR: Report errors from mysqli function calls.
 * MYSQLI_REPORT_STRICT: Throw a mysqli_sql_exception for errors instead of warnings. 
 * 
 * @link http://php.net/manual/en/class.mysqli-driver.php
 * @link http://php.net/manual/en/mysqli-driver.report-mode.php
 * @link http://php.net/manual/en/mysqli.constants.php
 */
$mysqliDriver = new mysqli_driver();
$mysqliDriver->report_mode = (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$connection = new mysqli(HOST, USERNAME, PASSWORD, DATABASE, PORT);

admin/index.php:

<?php
require '../includes/functions.php';

session_start();

/*
 * Just for testing: set the id of the logged-in admin. It should be set in the admin login page.
 * @todo Remove the line.
 */
$_SESSION['adminId'] = 173;

// If no admin id is set, redirect to the admin login page.
if (!isset($_SESSION['adminId']) || empty($_SESSION['adminId'])) {
    redirect('login.php');
}

// Operations performed upon form submission.
if (isset($_POST['submit'])) {
    $clientId = $_POST['submit'];

    // Set the client id, in order to be used in the client's profile overview page.
    $_SESSION['clientId'] = $clientId;

    // Redirect to the client's profile overview page.
    redirect('../client/profile_overview.php');
}

require '../includes/connection.php';

$sql = 'SELECT 
            id,
            CONCAT(lastName, ", ", firstName) AS name,
            email 
        FROM Client 
        ORDER BY lastName ASC';

$result = $connection->query($sql);
$clients = $result->fetch_all(MYSQLI_ASSOC);
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo - Clients list</title>

        <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" type="text/css" rel="stylesheet" />
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" type="text/css" rel="stylesheet" />

        <script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" type="text/javascript"></script>

        <style type="text/css">
            body {
                padding: 50px;
            }

            .logo {
                /* ... */
            }

            .page-links {
                margin-bottom: 30px;
            }

            .logout {
                float: right;
            }

            .records-number {
                margin-bottom: 30px;
            }

            .table-container {
                /* ... */
            }

            .clients-list th,
            .clients-list td {
                /*text-align: center;*/
            }

            .id-col {
                /* If not really needed to be displayed, then hide the *id* columns in tables. */
                /* If not needed at all, then don't create any *id* columns. */
                /* display: none; */
            }
        </style>
    </head>
    <body>

        <img src="..images/skcac_logo.png" class="logo" alt="SKCAC Logo" width="300px">

        <p class="page-links">
            <a href="logout.php" class="logout">
                Logout
            </a>
        </p>

        <div class="page-content">
            <?php
            if ($clients) {
                ?>
                <p class="records-number">
                    There are currently <?php echo count($clients); ?> registered participants.
                </p>

                <div class="col col-2"></div>
                <div class="col col-8 table-container">
                    <form action="" method="post">
                        <table class="table clients-list">
                            <thead>
                                <tr>
                                    <th class="id-col">ID</th>
                                    <th>Name</th>
                                    <th>Email</th>
                                    <th>&nbsp;</th>
                                </tr>
                            </thead>
                            <tbody>
                                <?php
                                foreach ($clients as $client) {
                                    // Create variables for better usage/readability in the further cells creation codes.
                                    $id = $client['id'];
                                    $name = $client['name'];
                                    $email = $client['email'];
                                    ?>
                                    <tr>
                                        <td class="id-col">
                                            <?php echo $id; ?>
                                        </td>
                                        <td>
                                            <?php echo $name; ?>
                                        </td>
                                        <td>
                                            <?php echo $email; ?>
                                        </td>
                                        <td>
                                            <!-- Notice the button value. It holds the client id to be passed to the profile overview page. -->
                                            <button type="submit" id="viewProfileButton" name="submit" value="<?php echo $id; ?>" class="btn btn-default btn-sm btn-view-profile">
                                                <i class="fa fa-user" aria-hidden="true"></i> View profile
                                            </button>
                                        </td>
                                    </tr>
                                    <?php
                                }
                                ?>
                            </tbody>
                        </table>
                    </form>
                </div>
                <?php
            } else {
                ?>
                <p class="error">
                    There are currently no registered clients.
                </p>
                <?php
            }
            ?>
        </div>

    </body>
</html>

client/profile_overview.php:

<?php
require '../includes/functions.php';

session_start();

// If no client id is set, redirect to the client login page.
if (!isset($_SESSION['clientId']) || empty($_SESSION['clientId'])) {
    redirect('login.php');
}

// Read the client id set in the admin's clients list page.
$clientId = $_SESSION['clientId'];

require '../includes/connection.php';

/*
 * The SQL statement to be prepared. Notice the so-called markers, 
 * e.g. the "?" signs. They will be replaced later with the 
 * corresponding values when using mysqli_stmt::bind_param.
 * 
 * @link http://php.net/manual/en/mysqli.prepare.php
 */
$sql = 'SELECT 
            id,
            firstName,
            lastName,
            email 
        FROM Client 
        WHERE id = ? 
        LIMIT 1';

/*
 * Prepare the SQL statement for execution - ONLY ONCE.
 * 
 * @link http://php.net/manual/en/mysqli.prepare.php
 */
$statement = $connection->prepare($sql);

/*
 * Bind variables for the parameter markers (?) in the 
 * SQL statement that was passed to prepare(). The first 
 * argument of bind_param() is a string that contains one 
 * or more characters which specify the types for the 
 * corresponding bind variables.
 * 
 * @link http://php.net/manual/en/mysqli-stmt.bind-param.php
 */
$statement->bind_param('i', $clientId);

/*
 * Execute the prepared SQL statement.
 * When executed any parameter markers which exist will 
 * automatically be replaced with the appropriate data.
 * 
 * @link http://php.net/manual/en/mysqli-stmt.execute.php
 */
$statement->execute();

/*
 * Get the result set from the prepared statement.
 * 
 * NOTA BENE:
 * Available only with mysqlnd ("MySQL Native Driver")! If this 
 * is not installed, then uncomment "extension=php_mysqli_mysqlnd.dll" in 
 * PHP config file (php.ini) and restart web server (I assume Apache) and 
 * mysql service. Or use the following functions instead:
 * mysqli_stmt::store_result + mysqli_stmt::bind_result + mysqli_stmt::fetch.
 * 
 * @link http://php.net/manual/en/mysqli-stmt.get-result.php
 * @link https://stackoverflow.com/questions/8321096/call-to-undefined-method-mysqli-stmtget-result
 */
$result = $statement->get_result();

// Fetch data and save it into an array.
$client = $result->fetch_array(MYSQLI_ASSOC);
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo - Profile Overview</title>

        <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" type="text/css" rel="stylesheet" />
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" type="text/css" rel="stylesheet" />

        <script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" type="text/javascript"></script>

        <style type="text/css">
            body {
                padding: 50px;
            }

            .logo {
                /* ... */
            }

            .page-links {
                margin-bottom: 30px;
            }

            .logout {
                float: right;
            }
        </style>
    </head>
    <body>

        <img src="..images/skcac_logo.png" class="logo" alt="SKCAC Logo" width="300px">

        <p class="page-links">
            <!-- Here you can create a link to go back to the clients list page. For this you must check if adminId is set in the SESSION variable first. -->
            <a href="logout.php" class="logout">
                Logout
            </a>
        </p>

        <div class="page-content">
            <?php
            if ($client) {
                // Create variables for better usage/readability in the further cells creation codes.
                $id = $client['id'];
                $firstName = $client['firstName'];
                $lastName = $client['lastName'];
                $email = $client['email'];
                ?>
                <p>
                    The profile of the client with ID <?php echo $id; ?>.
                </p>

                <div class="col col-2"></div>
                <div class="col col-8">
                    <div>
                        First Name: <?php echo $firstName; ?>
                    </div>
                    <div>
                        Last Name: <?php echo $lastName; ?>
                    </div>
                    <div>
                        Email: <?php echo $email; ?>
                    </div>
                </div>
                <?php
            } else {
                ?>
                <p class="error">
                    No client details found.
                </p>
                <?php
            }
            ?>
        </div>

    </body>
</html>

Upvotes: 1

Chetan J Rao
Chetan J Rao

Reputation: 969

It's better you use a get request from the admin page to profile page. Based on the email or any unique id like registration id retrieved from the get request, you can retrieve all the details about him from the database using the query like if you are using email as you unique factor then perform SELECT * FROM table_name WHERE email=$_GET['email']; and from mysqli_fetch_array get all the details.

Upvotes: 1

Related Questions