Dipping toes into OOP

Hi,

I’ve been doing PHP for a few years now and recently started trying OOP. I’m sure I’ve made the right decision to try it out.

I’m trying (unsuccessfully) to list some blog entries from my web site with a function:
snippet-


	/**
	 * @return string	a message indicating the action status
	 */
	public function listEntries()
	{
  	$sql = "SELECT title
  				FROM entries";
  
  		if($stmt = $this->_db->prepare($sql))
  		{
    		$stmt->execute();
  			$order = 0;
  			while($row = $stmt->fetch())
  			{
  				$title = $row['title'];
  				echo $this->$row['title'];
  				++$order;
  			}
  			$stmt->closeCursor();
    		}  	
	}

Is this the right way to select the data from the database? Also, how would I then output it?

Many thanks for any pointers.

Separate the responsibilities out into different objects…

  • One to obtain the data
  • One to render the data
  • One to combine the two

Given the code below, we create a Blog object which accepts another object which implements the BlogEntryFinderInterface.

The Blog object doesn’t care what the object is, as long as it implements the methods defined in BlogEntryFinderInterface.

For instance, we define a method name BlogEntryFinderInterface::getAll(), this will return an array containing all the blog entry data.

I’ve created 2 example objects, DatabaseBlogEntryFinder & FlatFileBlogEntryFinder, both of these objects implement BlogEntryFinderInterface so we can safely pass them to our Blog object. Note how the Blog object doesn’t change even though we can now obtain our data from a FlatFile or Database, or any other source in fact.

The Blog object asks the finder for the entries and potentially renders them.


class Blog
{
    protected
        $blog_entry_finder;
        
    public function __construct(BlogEntryFinderInterface $blog_entry_finder){
        $this->blog_entry_finder = $blog_entry_finder;
    }
    
    public function showAll(){
        $entries = $this->blog_entry_finder->getAll();
        #render
    }
}

interface BlogEntryFinderInterface
{
    public function getAll();
    
    public function getOneById($id);
}
class DatabaseBlogEntryFinder implements BlogEntryFinderInterface
{
    protected
        $pdo;
    
    public function __construct($pdo){
        $this->pdo = $pdo;
    }
    
    public function getAll(){
        $result = $this->pdo->execute('SELECT * FROM blog');
        return $result->fetchAll();
    }
    
    public function getOneById($id){
        $result = $this->pdo->execute('SELECT * FROM blog WHERE id = $id');
        return $result->fetchOne();
    }
}

class FlatFileBlogEntryFinder implements BlogEntryFinderInterface
{
    protected
        $file_data;
    
    public function __construct($file){
        $this->file_data = file_get_contents($file);
    }
    
    public function getAll(){
        return explode(PHP_EOL, $this->file_data);
    }
    
    public function getOneById($id){
        $entries = explode(PHP_EOL, $this->file_data);
        return $entries[$id];
    }
}

This allows you to debug easier too, we create a MockBlogEntryFinder…


class MockBlogEntryFinder implements BlogEntryFinderInterface
{
    public function getAll(){
        return array(
            array(
                'title'     => 'Demo',
                'content'   => 'Hi!'
            ),
            array(
                'title'     => 'Demo two',
                'content'   => 'Hello!'
            )
        );
    }
    
    public function getOneById($id){
        return array(
            'title'     => 'Demo',
            'content'   => 'Hi!'
        );
    }
}

Wow Anthony, that’s great!

Is there any chance I could post an example script or two of what I’m working with? Just so I can easily implement the listEntries using my own system.

Here’s a little example of my add_entry.php script interacting with my BlogEntries class.

class.blog.inc.php:


<?php

/**
 * Handles user interactions within the app
 */
class BlogEntries
{
	/**
	 * The database object
	 * 
	 * @var object
	 */
	private $_db;

	/**
	 * Checks for a database object and creates one if none is found
	 * 
	 * @param object $db
	 * @return void
	 */
	public function __construct($db=NULL)
	{
		if(is_object($db))
		{
			$this->_db = $db;
		}
		else
		{
			$dsn = "mysql:host=".DB_HOST.";dbname=".DB_NAME;
			$this->_db = new PDO($dsn, DB_USER, DB_PASS);
		}
	}

	/**
	 * Checks and inserts a new blog entry into the database
	 * 
	 * @return string	a message indicating the action status
	 */
	public function addEntry()
	{
		$t = trim($_POST['title']);
		$v = sha1(time());
		
		if (!empty($t)) {
		
  		$sql = "INSERT INTO entries(title) VALUES(:title)";
  		if($stmt = $this->_db->prepare($sql)) {
  			$stmt->bindParam(":title", $t, PDO::PARAM_STR);
  			$stmt->execute();
  			$stmt->closeCursor();
  			return "<h2> Success! </h2>" . "<p> Your blog entry was added successfully "	. "created with the title, '<strong>$t</strong>'.";
  		}
  	
    }	
  	
	}

addentry.php:


<?php
	include_once "common/base.php";
	$pageTitle = "Add Entry";
	include_once "common/header.php";

	if(!empty($_POST['title'])):
		include_once "inc/class.blog.inc.php";
		$entry = new BlogEntries($db);
		echo $entry->addEntry();
	else: 	
?>

		<h2>Add Entry</h2>
		<form method="post" action="addentry.php" id="registerform">
			<div>
				<label for="title">Title:</label>
				<input type="text" name="title" id="title" /><br />
				<input type="submit" name="register" id="register" value="Add" />
				<input type="hidden" name="token"	value="<?php echo $_SESSION['token']; ?>" />
			</div>
		</form>

<?php
	endif;
	include_once 'common/close.php';
?>

Of course.

Is there anything in particular you’re having an issue with Michael?

Aaah yes, I just wanted to know how I then display the current blog entries in a list.

I think my OP code may need to be tweaked a little. I’m just not totally sure where to start. I don’t think it needs much.

Thanks for any pointers.

Ah, so no general tips, just a fix huh? Maybe I should’ve kept my mouth shut! :stuck_out_tongue:

You need to add some conditionals to your add method. Check if the connection is valid, else log, check if the statement was created, else log, check if it executed, else log…

I’m sure you get the point.

Hah, oh it’s not like that at all :slight_smile:
I’m reading the first post you made right now, but I’m just not pro enough to take it all in :slight_smile:

edit: Sounds good, I’ll play about with it some more and see how I go. Thanks again.

News Flash :slight_smile:

Got it working.

Just changed: echo $this->$row[‘title’]; to simply echo $title;

Thanks again for the guidance Anthony.