Reputation: 311
I'm new to doing things the oop way. Here's what I got.
First I've made a class that connects me to my database. Then I made a class to fetch the results from the database.
/engine/classes.php
class DB
{
public static function dbConnect()
{
$db = new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if ($db->connect_error) {
die('A connection to the database cannot be made.');
}
}
}
class Blog
{
public function fetchBlog()
{
DB::dbConnect();
$results = array();
if ($blog = $db->query('SELECT * FROM blog')) {
if ($blog->num_rows) {
while ($row = $blog->fetch_object()) {
$results[] = $row;
}
$blog->free();
}
}
}
}
Then I have a core.php
file where I include my classes.php
file and instantiate these classes. Like so
/engine/core.php
require_once 'classes.php';
$con = new DB();
$con->dbConnect();
$blog = new Blog();
Then finally I have my index.php
where the I'd like to echo the results I get. That looks like this
index.php
<?php include 'engine/core.php'; ?>
html stuff
<div id="blog">
<?php
$blog->fetchBlog();
if (!count($results)) {
echo'There are no blog posts at this time.';
} else {
foreach ($results as $r) {
echo'<div class="blogPost">
<em>', escape($r->postDate), '</em>
<h1>', escape($r->postTitle), '</h1>
<div>', escape($r->postBody), '</div>
</div>';
}
}
?>
</div>
I do have error reporting on and do not get errors on core.php
or classes.php
. However on my index.php
page I am getting these errors
Notice: Undefined variable: db in C:\wamp\www\website\engine\classes.php on line 138
Fatal error: Call to a member function query() on a non-object in C:\wamp\www\website\engine\classes.php on line 138
How can I correct this? I assume I need a __construct somewhere in there and I also assume I'm not calling the dbConnect
method correctly. I have tried a lot of things but listing them here would just be too much? Can anyone tell me what I am doing wrong?
Upvotes: 1
Views: 571
Reputation: 2877
The issue is that your $db
variable is local to the DB::dbConnect()
function, which means once that function is done running it is destroyed.
There's also an issue with the $results
where you didn't return it from the function or assign a value from the function call.
With the following edits you will be able to make it work, I'll comment it to hopefully allow you to better understand why I've done things the way I did.
/engine/classes.php
class DB
{
/**
* keep the variable available for all instances of the DB class since it's static.
*/
static protected $db;
/**
* get database instance, connect if necessary
*/
public static function conn()
{
/**
* automatically connect to the database if it's not connected
* this is known as lazy loading, which means it only creates
* the resource at the exact time that it needs it
*/
if (false === (self::$db instanceof mysqli) {
self::connect();
}
return self::$db;
}
/**
* create a connection to the database
*/
protected static function connect()
{
self::$db = new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if (self::$db->connect_error) {
die('A connection to the database cannot be made.');
}
}
}
class Blog
{
public function fetchBlog()
{
$results = array();
/**
* Since the db method is static, you can just call it without an instance
*/
if ($blog = DB::conn()->query('SELECT * FROM blog')) {
if ($blog->num_rows) {
while ($row = $blog->fetch_object()) {
$results[] = $row;
}
$blog->free();
}
}
/**
* you didn't do anything with the results, presumably you want to return them so you can do something with them
*/
return $results;
}
}
/engine/core.php
require_once 'classes.php';
/**
* It is unnecessary to create an instance of the DB class
* as all methods are defined statically
*/
//$con = new DB();
//$con->dbConnect();
$blog = new Blog();
index.php
<?php include 'engine/core.php'; ?>
<!-- html stuff -->
<div id="blog">
<?php
/**
* You must assign the output of the function call so you can make use of it
*/
$results = $blog->fetchBlog();
if (!count($results)) {
echo'There are no blog posts at this time.';
} else {
foreach ($results as $r) {
echo'<div class="blogPost">
<em>', escape($r->postDate), '</em>
<h1>', escape($r->postTitle), '</h1>
<div>', escape($r->postBody), '</div>
</div>';
}
}
?>
</div>
Upvotes: 2
Reputation: 6174
In you line if ($blog = $db->query('SELECT * FROM blog')) {
, $db
is never declared.
What you need to do is to return DB
object from constructor, so your class DB
should look like below:
class DB
{
public static function dbConnect()
{
$db = new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if ($db->connect_error) {
die('A connection to the database cannot be made.');
}
// Note this line :)
return $db;
}
}
Apart from this there are lot many improvements, that can be done in your code. Just to start with I would suggest you to dive into OOP in detail from here: http://php.net/manual/en/language.oop5.php
Off topic but I would like to add few more suggestions. As you have created your DB object creation method as a static. I would suggest to implement Singleton
design pattern for such objects because you will need only and only one object of this class across your application. Read More.
Upvotes: 0
Reputation: 25
In your class Blog
you just access a variable $db
that is never declared in the line:
if ($blog = $db->query('SELECT * FROM blog')) {
You would have to add a variable $db
to your class DB and then create a new instance of that class in your class Blog
.
Upvotes: 0