Blog app #3: the model

Published on Wednesday 27 April 2016. Tagged as PHP.

In a model-view-controller concept, the model is the part that handles stored data. In my case, I am using PDO to interact with a MySql database.

The class can be found in sys/classes/blogmodel.php. Not only does it retrieve a list of posts or all the data of a single post, it also takes care of pagination of the list, a basic search and previous/next links on the single post display.

The constructor method

Here, the db config data is extracted and then a connection to the database is made using PDO:

function __construct( $db ){
	extract( $db );
	try{ $db=new PDO( "mysql:host=$host;dbname=$name;charset=utf8", $user, $password ); }
	catch( PDOException $e ){ die( 'Error: '.$e->getMessage() ); }
	$this->db=$db;
}

The getPost method

This is the easiest of the methods: it retrieves a single post based on it's 'slug': it's user friendly URL:

function getPost( $slug ){
	$r=$this->db->prepare( 'SELECT * from posts WHERE slug=:slug' );
	$r->execute( array( ':slug'=>$slug ) );
	return $r->fetch( PDO::FETCH_ASSOC );	
}

The getPrevNext method

This method is called separately when an single post is displayed to retrieve links to the previous and next posts (if any) based on the publishdate:

function getPrevNext( $date ){
	$prevNext=array( 'prev'=>null, 'next'=>null );
	foreach( $prevNext as $key=>$value ){
		$r=$this->db->prepare('SELECT slug,subject FROM posts WHERE publishdate'.($key=='prev'?'<':'>').':date ORDER BY publishdate '.($key=='prev'?'DESC':'').' LIMIT 1');
		$r->execute( array( ':date'=>$date ) );
		$prevNext[ $key ]=$r->fetch(PDO::FETCH_ASSOC);
	}
	return $prevNext;		
}

The getPosts method

This classes works together with the getPagination method to get a part of a list and the corresponding data for pagination. In the getPosts method, first the total number of elements is calculated. Then the getPagination class is called to get the offset and limit parameters for the query. Then the part of the list is retrieved. The function returns a mixed object with the items of the list and the pagination data:

function getPosts( $thisPage, $perPage=10 ){
	$count=$this->db->query( 'SELECT COUNT(*) FROM posts' )->fetch()[0];
	$pagination=$this->getPagination( $thisPage, $perPage, $count );
	$r=$this->db->query( 'SELECT slug, subject, publishdate, description from posts ORDER BY publishdate DESC'.$pagination['queryAdd'] );
	return array( 'list'=>$r->fetchAll( PDO::FETCH_ASSOC ), 'pagination'=>$pagination );
}

The getPagination method

This method calculates the data needed to get part of the posts list and the pagination data based on the current page. If none is given, the current page is set to 1:

function getPagination( $currentPage, $perPage, $count ){
	if( !$currentPage )$currentPage=1;
	$numPages=ceil($count/$perPage);
	$offset=($currentPage-1)*$perPage;
	return array( 'count'=>$count, 'currentPage'=>$currentPage, 'numPages'=>$numPages, 'queryAdd'=>" LIMIT $offset, $perPage" );
}

In a next post, I'll explain the third part of my MVC system: the view which renders all the HTML to send to the browser.

The Blog app project on GitHub