Programming with a Data Manager 
Programming with a data manager should make your code smaller, easier to read, and more bug proof as all the error checking and data validation is handled within the data manager itself.
Note:
PHP experience is assumed here. You should understand procedural programming as well as have a handle on object-oriented programming.
The general process for using a data manager from start to finish is as follows:
  1. Create the data manager object.
  2. If you are updating an existing record, set the existing data.
  3. Set the values for the fields you wish to change.
  4. Depending on the error handling method chosen, check for errors and abort the save if errors are found.
  5. Save the updated/new data.
Most of these steps are handled via single line function calls. Each of these steps are detailed below.
Note:
The code snippets below assume you are within the vBulletin environment already. They will need access to various vBulletin files, such as includes/functions.php and includes/class_core.php, and vBulletin data, such as $vbulletin.
1Creating the data manager object
To create the data manager, you need to call the datamanager_init function, defined in functions.php.

datamanager_init($classtype, &$registry, $errtype = ERRTYPE_STANDARD, $forcefile = '')

Arguments are as follows:
  1. $classtype - the name of the data manager you want to create. This is only part of the class name. For example, if you wish to create vB_DataManager_User, you should send "User" as this value.
  2. $registry - the main registry object used by vBulletin to hold application-level data. In most cases, this will be the variable $vbulletin.
  3. $errtype (optional) - the type of error handling the data manager will use. With certain types, execution will stop once an error occurs and a message will be displayed; other types allow more control over errors. The following constants are valid values for this argument:
    ERRTYPE_ARRAY - Execution continues after an error occurs as all errors are placed in the $errors member of the data manager. Be sure to prevent saving if necessary, as calling the save method will cause a fatal error. A good example of this usage is when an error occurs while posting a new message.

    ERRTYPE_STANDARD - Execution stops once an error occurs and the error message is displayed to the user using the front-end error page.

    ERRTYPE_CP - This is the same as ERRTYPE_STANDARD, except that the error is displayed as a control panel error message.

    ERRTYPE_SILENT - This is similar to ERRTYPE_ARRAY, except that if the save is called while there are errors will simply prevent the save from occurring instead of stopping execution. This is useful if placing a data manager within another data manager and you can't allow an error to be displayed if something goes wrong.
  4. $forcefile (optional) - this controls the name of the file that is read to retrieve the data manager class. If you do not specify this, the filename is based off the class type. If you specify this argument, the file that will be read is includes/class_dm_[forcefile].php. This argument is not needed for most classes.
This function will return a reference to the data manager object that was created. Be sure to use =& when you assign the value returned to a variable!

Example usage:
$dataman =& datamanager_init('Thread'$vbulletinERRTYPE_ARRAY'threadpost');

// or...

$dataman =& datamanager_init('User'$vbulletin); 
2Setting the existing data (if necessary)
If you are using the data managers to insert a new record into the database, you do not need to perform this step. However, if you are updating an existing record (eg, editing a post), this step is mandatory.

To set the existing data, you must call the set_existing method of the data manager object.

set_existing(&$existing)

The $existing is an array of data that is currently stored in the database. It should include all the fields this data manager handles as keys. For example, the array passed into the user data manager would have a structure similar to this:
$existing = array(
    
'userid' => 1,
    
'username' => 'Admin',
    
'usergroupid' => 6,
    
// ...and all the other fields related to a user
); 
The data manager will automatically pick out the field or fields that uniquely identify a record and update it upon saving (instead of inserting a new record).

The data passed into this function often comes from functions such as fetch_userinfo or fetch_threadinfo.

This function does not return a value.

Example usage:
$dataman->set_existing($vbulletin->userinfo); 
3Setting the values for data you wish to change
Most of your time spent dealing with data managers will be spent in this step. Each piece of data that is known must be set individually via one of several method calls. These calls will verify the validity of the data before using it to save the changes.

set($fieldname, $value, $clean = true, $doverify = true)
setr($fieldname, &$value, $clean = true, $doverify = true)


The functions set and setr are identical except that the second argument is passed by-reference in setr and by-value in set.
  1. $fieldname - the name of the field you are updating (eg, userid, username). The list of fields a data manager can handle are listed in the $validfields member.
  2. $value - the value you are changing this field to. Unless you specify the $clean argument, this value will be type cleaned to the correct data type. For example, if you specify a new user ID, it will be forced to an integer before saving.
  3. $clean (optional) - this controls whether the data specified in $value is cleaned to the correct data type. Normally, you will want this to be true (cleaning performed), however if you want to perform something like a relative value update (field = field + 3), you will need to make this be false.
  4. $doverify (optional) - controls whether to verify the data is valid before saving. For example, if you normally had a minimum of 10 characters in a post and you wanted to avoid that (and the other checks on the post text), you would set this argument to false.
These functions will return true on success and false on failure. However, note that this is the first step where the selected error handling type applies. If verification of the data fails and you have selected an error handler that displays the error immediately, execution will stop before these functions return!

Example usage:
$dataman->set('username''Admin');
$usergroupid 6;
$dataman->setr('usergroupid'$usergroupid); 
Another method of setting fields applies to yes/no options stored in a bit field. A bit field is a way of storing 32 yes/no options in a 4-byte integer value. To set a bit field value, call this method:

set_bitfield($fieldname, $bitname, $onoff)
  1. $fieldname - the name of the entire bit field you are updating (eg, userid, username). The name of the bit fields managed by a data manager are specified in the $bitfields member.
  2. $bitname - the name of the specific bit in the bit field that you wish to update. The bit field associated with a specific piece of data is also listed in the $bitfields member. Each member is defined in the includes/xml/bitfield_*.xml files.
  3. $onoff - Whether to set the option to on/yes/1 or off/no/0.
This function returns true on success and false on failure. Bit fields do not use the verification functions used by the set and setr functions, so this function will return true unless you try to write to a field that is not a bit field.

Example usage:
$dataman->set_bitfield('options''receivepm'true);
$dataman->set_bitfield('options''emailonpm'false); 
Note that some more complicated data managers have special functions to set specific fields as they require extra information that cannot by provided via set or setr. Documenting those functions is beyond the scope of this document.
4Checking for errors before saving (if necessary)
If you are using an error handler which does not stop execution, you will likely want to ensure that there are no errors up until the exact point at which the saving occurs. If you are using the ERRTYPE_ARRAY error handler, this is almost required since if errors have occurred, a PHP fatal error will occur.

The first thing you need to do is call the pre_save method. This does any last minute data verification and anything else necessary before saving. This method can throw additional errors, so you need to call this explicitly if you are using an error handler that does not stop execution. The save method will call this automatically, so if you are using an execution-stopping error handler, you do not need to bother with this.

Once this method has been called, you need to check to see if the $errors member is an empty array. If it is empty, then no errors have occurred and you may proceed with the save. If it is not empty, the array will consist of strings listing each of the errors; these are generally ready to be displayed to a user.

Example code would look like this:
$dataman->pre_save();
if (
count($dataman->errors) > 0)
{
    
// Errors occurred. Do not proceed with the save.
    // You may want to loop through $dataman->errors and 
    // display the results the user.
}
else
{
    
// No errors occurred.
    // Proceed with the save (see the next step).

5Saving the updated/new data
The final step is to save the data. This is simply done by calling the save method of the data manager object. The save method does not need any arguments.

The value this function returns varies depending on certain criteria:
  • All cases when the save fails - returns 0 or false. Note that if you are using the ERRTYPE_ARRAY error handler, a fatal error may occur first.
  • Updating a record successfully - returns true.
  • Inserting a new record when there is a unique identifier column - this occurs when the main table for the data contains a column marked as AUTO_INCREMENT. The value returned is the value inserted into this column. Most data manager inserts will follow this.
  • Inserting a new record when there is no unique identifier column - this occurs when the main table for the data does not contain a column marked as AUTO_INCREMENT. The value returned is -1. This does not occur very often.
Example usage:
// inserting a new user
$userid $dataman->save();

// updating an existing record
$dataman->save(); 
Copyright © 2024 MH Sub I, LLC dba vBulletin. All rights reserved. vBulletin® is a registered trademark of MH Sub I, LLC dba vBulletin.