0

Just trying to get my head around OOP. I have been told that I am doing the script below wrong. I was previously trying to call a method from the database class. When really the database class should only be dealing with database stuff. So I have now created an html_class.php where I believe I need to access the database class and then output the html via this class?.

The method I am trying to call on the index.php is the getBlogPost()method located in the html_class.php file. I am trying to call this using echo $htmlObject->getBlogPosts();

I am assuming this is the proper way to go about doing this?

I am currently getting the following errors:

Notice: Undefined variable: db_login_info in C:\xampp\htdocs\xampp\oop\CMS\classes\html_class.php on line 14

Fatal error: Cannot access private property database::$objDbConn in C:\xampp\htdocs\xampp\oop\CMS\classes\html_class.php on line 15

index.php

<?php 
require_once("includes/header.php");
require_once("includes/footer.php");
require_once("classes/database_class.php");
require_once("classes/blog_post_class.php");
require_once("classes/html_class.php");
require_once("conf/config.php");

$header = new header();
// createHeader( Title | Description | Keywords)
echo $header->createHeader('Home - Nissan Skyline GTR Blog', 'This is a blog site about the Nissan GTR', 'Nissan, GTR, R35');

$dbObject = new database($db_login_info);
$htmlObject = new makeHTML();


 ?>
    <div id="container">
        <div id="top_nav">
        <a href="admin.php" class="admin_link">Admin Login</a>
        </div>

            <div id="header"></div>

            <div id="nav">
                <ul>
                    <li><a href="index.php">Home</a></li>
                    <li><a href="create-blog.php">Create Blog</a></li>
                    <?php 
                    $sql = "SELECT * FROM create_page";
                    echo $dbObject->createNavigation($sql);
                     ?>
                </ul>
            </div>

            <div id="content_area">
                <?php 
                echo $htmlObject->getBlogPosts(); // Calling the getBlogPost function located in the html_class.php

                // echo $dbObject->getBlogPosts();

                 ?>


            </div>
<?php 
$footer = new footer();
echo $footer->createFooter();
 ?>

database_class.php

<?php    

class database {
        private $objDbConn;

        function __construct($db_login_info){
            $this->objDbConn = new mysqli($db_login_info['host'], $db_login_info['username'],
                                        $db_login_info['password'], $db_login_info['database']);

             if (mysqli_connect_errno()) {
                        die("Database connection failed". mysqli_connect_error());
                }
        }
        // I was previoulsy calling this method below on the index.php page and it was working great
        // function getBlogPosts(){
        //  $objRes = mysqli_query($this->objDbConn, "SELECT * FROM `blog_posts` ORDER BY id DESC");
        //   if(mysqli_errno($this->objDbConn)) {
        //      die("Failed query: $strSql". $this->objDbConn->error);
        //   }
        //   $allrows ='';
        //   while ($row = mysqli_fetch_array($objRes)) {

        //      $time = strtotime($row['date']);
        //      $my_format = date("m/d/y @ g:ia", $time);

        //      $allrows .= '<div id="blog_post">';
        //      $allrows .= '<h2 id="blog_title">'.$row['title'].'</h2>';
        //      $allrows .= '<h5> Posted on the '.$my_format.'</h5>'."<br>";
        //      $allrows .= '<div id="blog_content">'.nl2br($row['content']).'</div>'."<br>";
        //      $allrows .= '<b>ID:</b>'.$row['id'].'<a href="delete.php?id='.$row['id'].'" name="delete" onclick="return confirm(\'Are you sure you want to delete this post?\');"> Delete</a></div>';
        //   };

        //   return $allrows;



        // }

    ?>

html_class.php

<?php 
require_once("includes/header.php");
require_once("includes/footer.php");
require_once("classes/database_class.php");
require_once("classes/blog_post_class.php");
require_once("classes/html_class.php");
require_once("conf/config.php");


class makeHTML {


    function getBlogPosts(){
        $dbObject = new database($db_login_info); // This is where the Notice: Undefined variable: db_login_info is happening
        $objRes = mysqli_query($dbObject->objDbConn, "SELECT * FROM `blog_posts` ORDER BY id DESC");
         if(mysqli_errno($dbObject->objDbConn)) {
            die("Failed query:". $dbObject->objDbConn->error);
         }
         $allrows ='';
         while ($row = mysqli_fetch_array($objRes)) {

            $time = strtotime($row['date']);
            $my_format = date("m/d/y @ g:ia", $time);

            $allrows .= '<div id="blog_post">';
            $allrows .= '<h2 id="blog_title">'.$row['title'].'</h2>';
            $allrows .= '<h5> Posted on the '.$my_format.'</h5>'."<br>";
            $allrows .= '<div id="blog_content">'.nl2br($row['content']).'</div>'."<br>";
            $allrows .= '<b>ID:</b>'.$row['id'].'<a href="delete.php?id='.$row['id'].'" name="delete" onclick="return confirm(\'Are you sure you want to delete this post?\');"> Delete</a></div>';
         };

         return $allrows;
    }
}



 ?>

config.php

<?php 

// Database login details below

$db_login_info = array(
    'host'=>'localhost',
    'username'=>'root',
    'password'=>'',
    'database'=>'cms'
    );

 ?>

Updated html_class.php

<?php 
require_once("includes/header.php");
require_once("includes/footer.php");
require_once("classes/database_class.php");
require_once("classes/blog_post_class.php");
require_once("classes/html_class.php");
require_once("conf/config.php");


class makeHTML {

    private $database;

    public function __construct(database $database){
        $this->database = $database;
    }

    function getBlogPosts(){

        $objRes = mysqli_query($this->database, "SELECT * FROM `blog_posts` ORDER BY id DESC");
         if(mysqli_errno($this->database)) {
            die("Failed query:". $this->database->error);
         }
         $allrows ='';
         while ($row = mysqli_fetch_array($objRes)) {

            $time = strtotime($row['date']);
            $my_format = date("m/d/y @ g:ia", $time);

            $allrows .= '<div id="blog_post">';
            $allrows .= '<h2 id="blog_title">'.$row['title'].'</h2>';
            $allrows .= '<h5> Posted on the '.$my_format.'</h5>'."<br>";
            $allrows .= '<div id="blog_content">'.nl2br($row['content']).'</div>'."<br>";
            $allrows .= '<b>ID:</b>'.$row['id'].'<a href="delete.php?id='.$row['id'].'" name="delete" onclick="return confirm(\'Are you sure you want to delete this post?\');"> Delete</a></div>';
         };

         return $allrows;
    }
}

Update database_class.php

class database {
    public $objDbConn;

    function __construct($db_login_info){
        $this->objDbConn = new mysqli($db_login_info['host'], $db_login_info['username'],
                                    $db_login_info['password'], $db_login_info['database']);

         if (mysqli_connect_errno()) {
                    die("Database connection failed". mysqli_connect_error());
            }


    } 

     ?>

fetchall method in database_class.php:

function fetchall($sql) {
        $query = mysqli_query($this->objDbConn, $sql);
        if ($this->objDbConn->connect_errno) {
            die("Database connection failed with message: " . $objDbConn->connect_error);
        }
    }

3 Answers 3

4

You should use "Dependency Injection" to give your makeHtml class the database object.

Add a __construct method to your makeHtml class:

class makeHtml
{
    private $database;

    public function __construct(database $database)
    {
        $this->database = $database;
    }

When you instantiate your makeHtml class:

$htmlObject = new makeHTML($dbObject);

Then inside your class, instead of creating a new database object (and a new connection every time) you can just refer to your database object with $this->database.

Further note to your case above, you will need to make the $objDbConn variable in the database class public so that you can access that variable in the other class. However, it would be "good practice" to have a method within your database class that deals with performing queries and returning the result. Ideally you should end up with something like:

$sql = 'SELECT * FROM `blog_posts` ORDER BY id DESC';
$allRows = $this->database->fetchAll($sql);

That will appear in your makeHtml class.

Sign up to request clarification or add additional context in comments.

4 Comments

Because of this comment I learned that I can semi-statically type php functions using Type Hinting. Thanks!
Thank you for your help so far. I have added and updated version of the 2x classes to my original post. Is this how it should be now?
Almost. Your mysqli_query will fail because you are passing in a database object instead of the mysqli resource. You will need to modify the mysqli_query to have the first parameter of $this->database->objDbConn. Once you have that working though, I would very much recommend trying to implement a generic query method like I suggested at the end of my answer.
Yay awesome, that now works :) Thank you! Now I will try and implement this generic query that you have mentioned :) On to the next mission haha :)
1

Okay, a few different things are going on with your code.

For starters, you are mixing procedural and object-oriented versions of MySQLi. The fact that you are using MySQLi is a big plus instead of going with the old deprecated version of MySQL. However, you need to pick between procedural or OOP, and then stick with it.

As for your error messages. You are getting the notice about $db_login_info because it does not exist in the getBlogPosts() method. When you are inside of a method your variable scope becomes limited. Meaning that variables declared outside of it are not visible within the method unless they are passed in as parameters.

The second message is about class scope. Your variable $dbObjConn is declared as private, which is fine, but you can only access a private variable from within the same class. If you declare it public then you can access it the way you are.

So here are some modifications I can suggest making to your code. Having a database class isn't a bad thing, it is easier to create a connection as an object and then pass that object around to other classes that need it. But, when you do this you should not mix the procedural versions of MySQLi with the OOP version. (I recommend you stick with the OOP version).

Your database_class.php could look something like this:

class database {
    private $objDbConn;

    function __construct($db_login_info){
        $this->objDbConn = new mysqli($db_login_info['host'], $db_login_info['username'],
                                      $db_login_info['password'], $db_login_info['database']);

        //This is where you are using the procedural interface
        //if (mysqli_connect_errno()) {
        //    die("Database connection failed". mysqli_connect_error());
        //    }
        //}

        //Use the OOP version instead
        if ($this->objDbConn->connect_errno) {
            die("Database connection failed with message: " . $this->objDbConn->connect_error);
        }

    }

    //Keep populating this class with more stuff.  Like:
    public function getDB() {
        return $this->dbObjConn; //use this method to access your private database variable from outside the class
    }
}

The html_class.php file could use some love as well:

class makeHTML {

    private $database; //Here is a place for your shiny database object.

    public functon __construct($database) {
        $this->database = $database;
    }

    public function getBlogPosts() {
        $dbObject = $this->database->getDB();
        $objRes = $dbObject->query($dbObject->objDbConn, "SELECT * FROM `blog_posts` ORDER BY id DESC");
         if($dbObject->errno) {
            die("Failed query:". $dbObject->error);
         }
         $allrows ='';
         while ($row = $objRes->fetch_array()) {

            $time = strtotime($row['date']);
            $my_format = date("m/d/y @ g:ia", $time);

            $allrows .= '<div id="blog_post">';
            $allrows .= '<h2 id="blog_title">'.$row['title'].'</h2>';
            $allrows .= '<h5> Posted on the '.$my_format.'</h5>'."<br>";
            $allrows .= '<div id="blog_content">'.nl2br($row['content']).'</div>'."<br>";
            $allrows .= '<b>ID:</b>'.$row['id'].'<a href="delete.php?id='.$row['id'].'" name="delete" onclick="return confirm(\'Are you sure you want to delete this post?\');"> Delete</a></div>';
         };

         return $allrows;
    }

    //Again, keep adding more to this class as you see fit....
}

Then to put all of this together, your calling code would look something like:

<?php 

include "config.php";

$myDatabase = new database($db_login_info);

$html = new makeHTML($myDatabase);

$posts = $html->getBlogPosts();

print($posts);

?>

Comments

0

you cannot use private member of object. Instead you could use method or make member public. Also instead of creating connection object every time you should create connection object in config file and include this file once.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.