Jump to content

Help with MySQLi and object oriented design


RyanMinor

Recommended Posts

I am trying to build an object-oriented interface for a website. My classes include a "Database" class with a constructor method that connects to a database and a destructor method that disconnects from the database, a child class called "Content" that will display content stored in the database, another child class called "User" that handles registration, updating user info, logging in, and logging out, etc., and a "Validator" class that will validate all forms. So far I have the database class, the content class, and the index.php page started. My problem is that I cannot get the data returned from the function (using mysqli prepared statements) to display on the main page. I have read tutorials using MySQL, but I am using MySQLi with prepared statements. Any help is appreciated.

 

Database.php
/*
The Database class handles connecting to and disconnecting from the database. All interaction with the database is then extended from this class. The constructor will be run automatically each time a new instance of the Database class (or one of its child classes) is made.
*/
abstract class Database {
// assign variables to use in the constructor
private $host 		= 'localhost';
private $user 		= '';
private $password 	= '';
private $database 	= '';

// define constructor method to connect to database
public function __construct() {		
	$this->connect = new mysqli($this->host, $this->user, $this->password, $this->database);
	// if the connection failed kill the script and display an error
	if($this->connect->connect_errno) {
		die('Critical database error: ' . $this->database->error . '. Please contact a site administrator.');
	}
}

// define destructor method to disconnect from the database
public function __destruct() {
	$this->connect->close();
}
}


Content.php

require_once('Database.php');
/*
This class will display all website content that is held in the database. Anything that is stored in the database that needs to be shown on the front end of the website will go through this class.
*/
class Content extends Database {

public function pageInfo($page) {
	$query = $this->connect->prepare('SELECT pageTitle, pageHeading, pageContent FROM pageInfo WHERE pageName = ?');
	$query->bind_param('s', $page);
	$query->execute();
	$query->bind_result($title, $heading, $content);
	return $query->fetch(); 
	// procedurally this returns the values of the bound variables which then I can use just by typing echo $variableName
	// if i echo the variables out inside this method, they display at the top of index.php
	// how do i call them into my variables to display where i want
	// return $query->fetch(); should return that object to main script but then how do i call those values
}

public function displayUsers() {

}

public function searchUsers() {

}

}


index.php
<?php 
$page = 'index.php';
require_once('modules/Content.php');
$page = new Content();
list($title, $heading, $content) = $page->pageInfo('index.php');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><?php echo $title; ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="includes/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="scripts/cufon-yui.js"></script>
<script type="text/javascript" src="scripts/arial.js"></script>
<script type="text/javascript" src="scripts/cuf_run.js"></script>
</head>
<body>

<!--begin main-->
<div class="main">
  
<?php include('header.php'); ?>

<?php include('menu.php'); ?>
  
<!--begin content-->
    <div class="content">
    
    <!--begin content_resize-->
    <div class="content_resize">
      
	<!--begin mainbar-->
        <div class="mainbar">
        
        <!--begin article-->
        <div class="article">
		<h2><span><?php echo $heading; ?></span></h2>
		<div class="clr"></div>
			<p><?php echo $content; ?></p>
	</div>
	<!--end article-->

	</div>
    	<!--end mainbar-->

	<?php include('sidebar.php'); ?>
      
	<div class="clr"></div>
    
    </div>
    <!--end content_resize-->
  
</div>
<!--end content-->
  
<?php include('footer.php'); ?>
    
</div>
<!--end main-->

</body>
</html>


Link to comment
Share on other sites

You're looking at your design in the wrong way.  Your Database class should be a wrapper for MySQLi.  It should handle preparing queries, binding and returning results.  Your other classes should not inherit from the Database class, but rather contain a reference to it, which is passed in through the constructor. 

 

Why?  Because right now your entire system is based on you using MySQLi.  This is very inflexible, and not the way to do things in OOP.  Also, inheritance describes an is-a relationship, where a child object is also a parent object, just with more functionality.  It doesn't make sense to look at your content as a database, or your users as databases.  In most cases, what you really want to do is compose objects - have one contain a reference to another.  This allows you to swap out an object representing a particular kind of functionality (say, MySQLi) for an object representing another kind of functionality (say, PostgreSQL) with no (if written correctly) changes needed to the containing object.

 

Inheritance has its place, but composition is typically the way to go.

 

For your specific issue, simply store the data you want to return in an array, and return that.  As in:

 

$query->fetch();

$results = array($title, $heading, $content);

return $results;

 

And here's how I suggest you look at your design:

 

class Content
{
   private $db;

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

   public function pageInfo($page)
   {
      $query = "SELECT pageTitle, pageHeading, pageContent FROM pageInfo WHERE pageName = ?";
      $results = $this->db->query($query, $page);

      return $results;
   }
}

class Database
{
   private $mysqli;

   public function __construct()
   {
      // construct your db instance 
   }

   public function query($query, $args)
   {
      // figure out a way to abstract your MySQLi statements

      return $results;
   }
}

$db = new Database();
$content = new Content($db);

$pageInfo = $content->pageInfo($page);

 

There are ways to further refine this (dependency injection, for one), but you should get the idea.

Link to comment
Share on other sites

Thanks for the replies..

 

Nightslyr, you actually answered the question I had intended to ask. I am new to the whole OOP game, but I didn't want to ask "How do I design such and such?" I am reading some object-oriented PHP books now, but figured the best way to learn is to dive right in. I think once I code a few projects using OOP I will be on my way. Just out of curiosity, how would you map out a design for a website that register users and allows users to login, update their info, and log out?

 

Thnaks Again,

 

Ryan

Link to comment
Share on other sites

I typically use some sort of factory class in order to construct/populate a User object.  So, the process would be something along the lines of:

 

User submits login info.

User Factory takes the info, and returns a populated User object*.  The factory method is static since an object does not need to exist for it to work.

Through the User object, the end user can modify their profile info and save it.

 

$user = UserFactory::LogIn($_POST['username'], $_POST['password']);

$user->ChangePassword($_POST['newPass']);
$user->SaveChanges();

 

*You may not want to lug around a complete User object from page to page via sessions.  You only really need the full object when work needs to be done on it.  Instead, you could simply pass around the username through sessions until you really need the full object.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.