Back to vBulletin 3 Articles

Datamanagers: Objects as Data and Methods
by Guest190829 25 Mar 2008

If you haven't read this article on how to create custom data managers or perhaps you read it and don't see what the big deal is - please read further!

Why go through the complexity of a data manager when I can just manage my data with direct queries and procedural code?

vBulletin's data managing classes can look pretty complicated if you are unfamiliar with OO programming - but the benefits far surpass the few hurtles of adopting a more OO approach to your programming.

A Live Example

We'll start off with a project simulation. A client wants an application that keeps tracks of restaurant reviews. In order to achieve this, we need to set up a database tables that would look something like this:
Table: restaurant

| restaurant id | title | location | menuid | totalreviews

Table: review

| review id | restaurant id | rating | comments | userid

As you can, each review has a rating and user comments and links to a particular restaurant in the database.

A Procedural Approach

Tackling the project is a pretty standard task - the most obvious coding tasks being the insertion, updating, and deleting of restaurant reviews.

(Of course, there could be other aspects too this type of project, but the overall focus will be narrow only to supplement the article's message.)

Here is sample code for restaurant review insertion:

PHP Code:

# Clean variables
$vbulletin->input->clean_array_gpc('p', array('comments' => TYPE_STR,
                                               
'rating' => TYPE_UINT,
                                               
'restaurantid' => TYPE_UINT)
);

# Does the restaurant exist?
$restaurant $vbulletin->db->query_first("SELECT title FROM " TABLE_PREFIX "restaurant
                                             WHERE restaurant_id = " 
$vbulletin->GPC['restaurantid']);

if(!
$restaurant) {
   
// Submit error
}

# Is the rating valid? (1-5)
if($rating OR $rating 5) {
  
// Submit Error
}

# Error checking is done, we can add it to the database
$vbulletin->db->query_write("INSERT INTO " TABLE_PREFIX "review (userid, restaurant_id, rating, comments)
             VALUES (
                           " 
intval($vbulletin->userinfo['userid'] . ", "
                            
$vbulletin->GPC['restaurantid'] . ", "
                            
$vbulletin->GPC['rating'] . ", "           
                            
$vbulletin->db->escape_string($vbulletin->GPC['comments']) . ")"
);
// Print Redirect "You're review of $restaurant['title'] was submitted." 
We did basic error checking and then submitted it into the database. Now let's see some sample code for updating a restaurant review:

PHP Code:
#Clean variables
$vbulletin->input->clean_array_gpc('p', array('comments'      => TYPE_STR,
                                               
'rating'       => TYPE_UINT,
                                               
'restaurantid' => TYPE_UINT,
                                                
'reviewid'    => TYPE_UINT    
                                        
));
                                        
#Does the review exist?
$review $vbulletin->db->query_first("SELECT id FROM " TABLE_PREFIX ."review 
                                       WHERE reviewid = " 
$vbulletin->GPC['reviewid']);
                                    
if(!
$review) {
    
// submit error
}

#Is the new rating correct?
if($rating OR $rating 5) {
    
// Submit errror
}

#Update database
$vbulletin->db->query_write("UPDATE " TABLE_PREFIX ."review
                                SET comments = '" 
$vbulletin->db->escape_string($vbulletin->GPC['comments'])) . "'
                                    rating = " 
$vbulletin->GPC['rating'] . "
                                WHERE reviewid = " 
$vbulletin->GPC['reviewid']); 
The code between updating and inserting looks familiar, doesn't it? Your first thought should be that it looks a little too familiar. One of the quickest signs that your application is going down hill is seeing repeated logic in your code.

But what does this have too do with OO programming and objects? Can't we just code functions to prevent this code duplication?

The OO Mentality: Objects as Data and Methods

With procedural programming, data and behavior are two completely separate entities. You input data into a function and get specific data back. This may not be a problem at times but the data manager classes bring up a specific benefits when handling data.

Since objects are both data and methods, you can avoid messy situations with verifying data. The vBulletin Data Managers offer a nice clear and encapsulated way to check inputted variables. The class contains an array of valid fields which specify methods to verify the inputted data.

Our restaurant review would look something like this:

PHP Code:
var $validfields = array('reviewid'                =>             array(TYPE_UINT,    REQ_INCR,    VF_METHOD,    'verify_nonzero'),
                         
'restaurantid'            =>            array(TYPE_UINT,    REQ_YES,    VF_METHOD,    'verify_restaurant'),
                         
'comments'                    =>        array(TYPE_NOHTML,    REQ_YES),
                         
'rating'                =>            array(TYPE_UINT,    REQ_YES,    VF_METHOD,    'verify_rating')
                        ); 
See how the validfields key VF_METHOD maps to a specific method within the class that only performs one piece of logic. This not only offers a clear view on what method is handling what data, but it also encapsulates logic such that if you ever wanted to extend this data manager in the event of a future version with more extensive features or a simple change in feature, you can do it very easily.

Here would be some of the basic verification methods, all short and sweet:

PHP Code:
function verify_restaurant($restaurantid) {
        
$restaurant $this->registry->db->query_read("SELECT title FROM " TABLE_PREFIX ."restaurant WHERE restaurantid = " $restaurantid);
        if(!
$restaurant) {
            return 
false;
        }
        
        return 
true;
}

function 
verify_rating($rating) {
    return (
$rating OR $rating 5) ? false true;

With the data manager object, you neatly encapsulate the data and methods into a single entity. With a procedural approach, you'd have to pass the data quite messily along each function - or even worse, couple separate logic into a single function.

Also, with the object - you get increased portability. Adopting to the original insertion and update code with the data manager.

PHP Code:
$reviewdm =& datamanager_init('Review', &$vbulletin$errtype ERRTYPE_STANDARD$forcefile 'review');
$reviewdm->set('restaurantid'$vbulletin->GPC['restaurantid']);
$reviewdm->set('comments'$vbulletin->GPC['comments']);
$reviewdm->set('rating'$vbulletin->GPC['rating']);
$reviewdm->pre_save();
if (
count($reviewdm->errors) > 0)
{
    
$errors "<ul>";
   foreach(
$reviewdm->errors As $err)
   {
           
$errors .= '<li>' $err '</li>';
   }
   
$errors .= '</ul>';
  eval(
standard_error($errors));
}
else
{
    
$reviewdm $reviewdm->save();

Benefits:

  • It's not just your datamanager class data and methods you have at hand, but the base datamanager class you are extending from. This class hierarchy and code reuse you can not achieve with just procedural functions alone. You can simply alter some basic settings (the valid fields array, the table array, etc...etc...) and leave the bulk of the processing to the default class.
  • Easily portable: You can call the datamanager class from anywhere, the forums, the admin cp, and even any custom scripts you create powered by the vBulletin engine. (Calling global.php)
  • Keeps separate operations in there own methods and reduces code duplication.If you have to make an alteration to the business logic (say you want to restrict review comments to 500 characters) you only have to add a verify_comments() method to your class and alter the valid fields array.
  • Inheritance allows for easy extension of feature and entire sub-systems. If your client now wants the review system to accept not only restaurants but clubs and casinos, you can accomplish it easily by just extending from the default Review data manager class.
Conclusion:

The intention of this article was to shed to light the benefits of OO programming through a tool utilized and available to you in vBulletin. This article is focused on custom data managers, but the sky is the limit for creating OO applications. Good luck, and don't be afraid to take the dive into the powerful paradigm of object oriented programming.

Additional Reading:

Similar Mods

Miscellaneous Hacks [AJAX] Tabbed Personal Statistics (YUI) vBulletin 3.7 Add-ons

vblts.ru supports vBulletin®, 2022-2024