Search code examples
phpsqlmysqliforum

Why is a file not connecting to the others in PHP forum system?


I'm working on a PHP forum that involves multiple pages leading into each other. I'm at the point where I'm trying to get category topics to appear on a separate page, but for some reason, the topics.php file is connecting to the rest of the files. When I click the home button or try to log out the page doesn't change. I'm doing everything via separate function file.

Here's the topics.php file:

    <?php
session_start();
include ('../db.php');
$first_name = $_SESSION['first_name'];
$last_name = $_SESSION['last_name'];
$email = $_SESSION['email'];
$active = $_SESSION['active'];

// Check if user is logged in using the session variable
if ( $_SESSION['logged_in'] != 1 ) {
  $_SESSION['message'] = "You must log in before viewing your profile page!";
  header("location: error.php");
}
else {
    // Makes it easier to read
    $first_name = $_SESSION['first_name'];
    $last_name = $_SESSION['last_name'];
    $email = $_SESSION['email'];
    $active = $_SESSION['active'];
}

include ('content_function.php');

 ?>
<!DOCTYPE html>
<html lang="en">

  <head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Home</title>

    <!-- Bootstrap core CSS -->
    <link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom fonts for this template -->
    <link href="vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    <link href='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>

    <!-- Custom styles for this template -->
    <link href="css/clean-blog.min.css" rel="stylesheet">
    <link href="main.css" type="text/css" rel="stylesheet" />
  </head>

  <body>

    <!-- Navigation -->
    <nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
      <div class="container">
        <a class="navbar-brand" href="../logout.php">Logout</a>
        <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
          Menu                                      <!-- Right above this ^ comment was this code: data-toggle="collapse" #NeverForget-->
          <i class="fa fa-bars"></i>
        </button>
        <div  class="nav-link" id="navbarResponsive">
          <ul  class="navbar-nav ml-auto">
            <li class="nav-link" class="nav-item">
              <a  href="index2.php">Home</a>
            </li>
            <li class="nav-link" class="nav-item">
              <a  href="about.html">About</a>
            </li>
            <li class="nav-link" class="nav-item">
              <a  href="msgBoard.php">Posts</a>
            </li>
            <li class="nav-link" class="nav-item">
              <a  href="contact.html">Contact</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>

    <!-- Page Header -->
    <header class="masthead" style="background-image: url('img/bible.jpg')">
      <div class="overlay"></div>
      <div class="container">
        <div class="row">
          <div class="col-lg-8 col-md-10 mx-auto">
            <div class="site-heading">
              <h1>Hi <?= $first_name ?>!</h1>
              <span class="subheading">Have Fun Exploring the Fellowship Wall</span>
            </div>
          </div>
        </div>
      </div>
    </header>

    <!-- Main Content -->
    <!-- <h1>Categories</h1>-->
    <style>
  body{
    background: tan;}
    </style>
    <!-- The above code is for the bacckground color on index2.php -->
          <hr>
          <!-- Pager -->
          <!--<div class="clearfix">
            <a class="btn btn-primary float-right" href="#">Older Posts &rarr;</a>
          </div>-->
        </div>
      </div>
    </div>
    <?php
  /*
   $select = mysqli_query($mysqli, "SELECT * FROM categories");
    while($row = mysqli_fetch_assoc($select)){
      echo  "<h1>", $row['category_title']."</h1>" ;
    }*/

    disptopics($_GET['cid'], $_GET['scid']);
    /*if (isset($_GET['cid'], $GET['scid'])){

      disptopics();
    }*/

     ?>
    <hr>

    <!-- Footer -->
    <footer>
      <div class="container">
        <div class="row">
          <div class="col-lg-8 col-md-10 mx-auto">
            <ul class="list-inline text-center">
              <li class="list-inline-item">
                <a href="#">
                  <span class="fa-stack fa-lg">
                    <i class="fa fa-circle fa-stack-2x"></i>
                    <i class="fa fa-twitter fa-stack-1x fa-inverse"></i>
                  </span>
                </a>
              </li>
              <li class="list-inline-item">
                <a href="#">
                  <span class="fa-stack fa-lg">
                    <i class="fa fa-circle fa-stack-2x"></i>
                    <i class="fa fa-facebook fa-stack-1x fa-inverse"></i>
                  </span>
                </a>
              </li>
            <!--  <li class="list-inline-item">
                <a href="#">
                  <span class="fa-stack fa-lg">
                    <i class="fa fa-circle fa-stack-2x"></i>
                    <i class="fa fa-github fa-stack-1x fa-inverse"></i>
                  </span>-->
                </a>
              </li>
            </ul>
            <p class="copyright text-muted">Copyright &copy; Your Website 2018</p>
          </div>
        </div>
      </div>
    </footer>

    <!-- Bootstrap core JavaScript -->
    <script src="vendor/jquery/jquery.min.js"></script>
    <script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

    <!-- Custom scripts for this template -->
    <script src="js/clean-blog.min.js"></script>

  </body>

</html>

Here is the functions file (content_function.php):

    <?php

  function dispcategories(){
    include ('../db.php');
    $select = mysqli_query($mysqli, "SELECT * FROM categories");

    while($row = mysqli_fetch_assoc($select)){
      echo "<table class = 'category-table'";
      echo "<tr><td class= 'main-category'colspan='2'>".$row['category_title']."</tr></td>";
      dispsubcategories($row['cat_id']);
      echo "</table>";
    }
  }

  function dispsubcategories($parent_id){
    include ('../db.php');
    $select = mysqli_query($mysqli, "SELECT cat_id, subcat_id, subcategory_title, subcategory_descr FROM categories, subcategories
                                     WHERE ($parent_id = categories.cat_id) AND ($parent_id = subcategories.parent_id)");
    echo "<tr><th width='90%'>Categories</th><th width='10%'>Topics</th></tr>";

    while($row = mysqli_fetch_assoc($select)){
      echo "<tr><td class='category_title'><a href='(A)Book 2.0/Bootstrap/topics.php/".$row['cat_id']."/".$row['subcat_id']."'>
                    ".$row['subcategory_title']."<br/>";
      echo $row['subcategory_descr']."</a></td>";
      echo "<td class='num-topics'>".getnumtopics($parent_id, $row['subcat_id'])."</td></tr>";
    }
  }
  //Displays categories
  function getnumtopics($cat_id, $subcat_id){
    include ('../db.php');
    $select = mysqli_query($mysqli, "SELECT category_id, subcategory_id FROM topics WHERE ".$cat_id." = category_id
                    AND ".$subcat_id." = subcategory_id");
$get = mysqli_num_rows($select);

return $get;
  }
  //Displays Topics Within categories
  function disptopics($cid, $scid){
    include ('../db.php');
    $select = mysqli_query($mysqli, "SELECT topic_id, author, title, date_posted, views, replies FROM categories, subcategories, topics
                                     WHERE ($cid = topics.category_id) AND ($scid = topics.subcategory_id) AND ($cid = categories.cat_id)
                                     AND ($scid = subcategories.subcat_id) ORDER BY topic_id DESC");


   if(mysqli_num_rows($select) != 0) {
      echo "<table class='topic-table'>";
      echo "<tr><th>Title</th><th>Posted By</th><th>Date Posted</th><th>Views</th><th>Replies</th></tr>";

      while($row = mysqli_fetch_assoc($select)){
        echo "<tr><td><a href='readtopic.php/".$cid."/".$scid."/".$row['topic_id']."'>
              ".$row['title']."</a></td><td>".$row['author']."</td><td>".$row['date-posted'].".</td><td>".$row['views']."</td>
              <td>".$row['replies']."</td></tr>";
      }
      echo "</table>";
    } else {
      echo "<p>This category has no topics yet! <a href='newtopic.php/".$cid."/".$scid."'> Add a new one!</a></p>";
    }

  }


?>

I've been looking for days and I can't seem to find a syntax error. Maybe I'm entering something wrong? I'm still pretty new to PHP.


Solution

  • There is a lot of bad going on here. Please don't take that in a mean way, we all have to learn and it's a process. I don't know If I can specifically answer your question but I can point a few things out.

    session_start();
    include ('../db.php');
    $first_name = $_SESSION['first_name'];
    $last_name = $_SESSION['last_name'];
    $email = $_SESSION['email'];
    $active = $_SESSION['active'];
    
    // Check if user is logged in using the session variable
    if ( $_SESSION['logged_in'] != 1 ) {
      $_SESSION['message'] = "You must log in before viewing your profile page!";
      header("location: error.php");
    }
    else {
        // Makes it easier to read
        $first_name = $_SESSION['first_name'];
        $last_name = $_SESSION['last_name'];
        $email = $_SESSION['email'];
        $active = $_SESSION['active'];
    }
    

    Nuke the top half of this:

    session_start();
    include ('../db.php');
    
    // Check if user is logged in using the session variable
    if ( $_SESSION['logged_in'] != 1 ) {
      $_SESSION['message'] = "You must log in before viewing your profile page!";
      header("location: error.php");
      exit; //<--- add this
    }else {
        // Makes it easier to read
        $first_name = $_SESSION['first_name'];
        $last_name = $_SESSION['last_name'];
        $email = $_SESSION['email'];
        $active = $_SESSION['active'];
    }
    

    It's redundant, because of the If below it. If they are not logged in you redirect the page (these no longer matter), if they are you set these again. Always add exit; after doing the redirect as header doesn't necessarily end the execution of the current script, and it can cause unexpected things to happen.

    In your HTML you have

    <body>
    
    <!-- Navigation -->
    <nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
    

    Than later in the page you have

    <style>
      body{background: tan;}
    </style>
    

    You should put the style before the Tag, preferably in the HEAD of the page. I am not sure what problems if any this will cause as it likely depends on several things including what browser is being used. It's just that depending on how the page is rendered it may not pick up the style in time to apply it to the tag if the tag is first.

    For the functions, I can't say this with certainty because I cant know the full scope of you project but if you only call them once there is no need to make them functions, in fact it complicates things by moving the logic away from where it's used. You can ignore part of that if you do re-use them. But generally, it's best not to echo HTML from a function separate from the HTML, this makes formatting the HTML hard because you have to have both files open. And in the case it's reused, you may be modifying a page it's used on without knowing that ahead of time. It's better to return the data then do the formatting inline. This too is subjective because it really depends on how it's done in the grand scheme of the project. But a word of caution. Some of this is based on the procedural nature of the code, but even in Object orientated programming (OOP) where classes are used, it's still not a good idea to output HTML directly from a class for the same reason.

    Connection.

    function getnumtopics($cat_id, $subcat_id){
      include ('../db.php');
    

    Your including this multiple times, besides wasting processing power and time, you also create a hard dependency on that file. If you choose later to replace that file you have a lot of code to edit. It's better to include/require that once like you do at the top of the page and then pass the connection into the functions when calling them. So instead of this:

          function getnumtopics($cat_id, $subcat_id){
             include ('../db.php');
             $select = mysqli_query($mysqli,  ...
    

    Do something like this

         function getnumtopics($cat_id, $subcat_id, $mysqli){
             $select = mysqli_query($mysqli,  ...
    

    And when you call it you just add that to the call, provided it's included/require in the file that called it. If you are not sure and you need it in multiple files then you can use 'require_once' (more on this later). An example of the problems this causes. Say sometime later you want to create a new DB file (for whatever reason, I cant think of one, but it could happen). With that filename backed into all the functions you can't test it just on one page without modifying all the functions used in the page, some of which may be used on other pages. So you are stuck going though all that code searching and replacing the filename. That is probably a bad example but it's the best I can think of right now. It's just a bad practice for several reasons.

    Require Vs Require Once

    File 1.

      require_once('../db.php');
      require_once('../file2.php');
      ....
      getnumtopics($cat_id, $subcat_id, $mysqli);
    

    File 2.

      require_once('../db.php');
      ....
      dispsubcategories($cat_id, $subcat_id, $mysqli);
    

    In this example File1 needs the DB, but also File2 does. But maybe you use File2 also in a File3 that doesn't need it:

    File 3.

    require_once('../file2.php');
    

    In this case if you just require it, and you should require not include it. Then you get 2 copies in the File1 case and 1 copy in the File3 case. You cannot just include it in File2 because File1 needs it as well. So you can use the _once this insures that if its all ready been included you won't include it again, but also if it hasn't that it will be (this made more sense in my head).

    Include Vs Requre

    As for include vs require. Include will not throw any errors if the file is missing, require will. So you have to ask yourself will this script function properly if file x (file to be included) is not found. In this case that answer is no. So you should make it required. This will help you debug errors in the event that the file goes missing. You could move it to Linux where casing (capital vs lowercase) matters, and it worked fine on Windows but now it's busted. This will help you by telling you the required file is missing, instead of getting a general error for failing to connect to the DB or for calling the DB functions on a NULL resource.

    Summery

    As to why it's combining the pages, I am not sure it could be due to not calling exit, but I can't say that for sure as I haven't studied the behavior of not calling exit in any great detail I only know that you should always call it after a redirect or weird things can happen.

    I also can't say this is everything that is wrong, it's just what I see right away that I would change.

    Hope that helps.