Go Back   vb.org Archive > vBulletin Article Depository > Read An Article > vBulletin 3 Articles

Reply
 
Thread Tools
Cache System Explanation (datastore)
Logikos
Join Date: Jan 2003
Posts: 2,924

 

Show Printable Version Email this Page Subscription
Logikos Logikos is offline 03-16-2006, 10:00 PM

I'm going to try and explain the datastore system used in vBulltin. This tutorial is based around users who are already familar with PHP and MySQL.
What is Cache?
A memory area where frequently accessed data can be stored for rapid access. (View Definitions). Basicly, you can store information into the database, and grab all this information with just using 1 query. Some may question this and say: "Isn't all information in the database retrived by queires?". Yup, all information in the database is retrived using MySQL queries, though the method used is diffrent when using the datastore system in vBulletin.
I'll show you way using the datastore is a better solution for you and the users who will use your hacks.

Datastore Method

Lets say you want to use a drop down form with 3 options to choose from. Obviously you would need to create alittle script to add, delete, and edit the information; and when you make this script. Where does the info go? Well it would go into the database. Lets call the MySQL table "dropdownoptions" with 3 fields. ID, Name, and Value.

Attachment 44423
Now everytime you add, edit, or delete your information, it will be changed in the database. Here is an example of the database tree. We have 3 rows of information.
  • ID = (1) Name = (Dog) Value(Dog)
  • ID = (2) Name = (Cat) Value(Cat)
  • ID = (3) Name = (Cow) Value(Cow)
Attachment 44424

After you insert this information into the database, the next step would be to insert this info in the datastore. You can do that like this.

PHP Code:
$query $vbulletin->db->query_read("
        SELECT *
        FROM " 
TABLE_PREFIX "dropdownmenu
        ORDER BY id DESC
"
);

while (
$variable $vbulletin->db->fetch_array($query))
{
        
$variable_array[] = $variable;
}

build_datastore('dropmenu'serialize($variable_array)); 
Let me go ahead and tell you exacly what the above does. What we did was just grab all in the information in the database from the table dropdownmenu. The while() function will loop the information from the begging to the end. While it's getting all this information, It's storing it all into the variable named $variable_array.

Then you need to use the function called build_datastore(). This function requires the following. build_datastore(1, 2). #1 is the name of your datastore item, and number two is the serialize information to store. This function will create a new datastore item with the name and all your info.

The serialize info will look like this...
Code:
a:3:{i:0;a:3:{s:2:"id";s:1:"1";s:4:"name";s:3:"Dog";s:5:"value";s:3:"Dog";}i:1;a:3:{s:2:"id";s:1:"2";s:4:"name";s:3:"Cat";s:5:"value";s:3:"Cat";}i:2;a:3:{s:2:"id";s:1:"3";s:4:"name";s:3:"Cow";s:5:"value";s:3:"Cow";}}
So now we have all our infomation stored in another area of the database, in one row. Heres a picture so you can compair it to the other ones.

Attachment 44425

Don't let the serialize data freak you out. You don't really NEED to read that data. Though I kinda like doing it, so I'll break it down alittle for you. Here is a tree of the serialize data.

Code:
a:3:{
        i:0; a:3:{
                s:2:"id";s:1:"1";
                s:4:"name";s:3:"Dog";
                s:5:"value";s:3:"Dog";
        }

        i:1; a:3:{
                s:2:"id";s:1:"2";
                s:4:"name";s:3:"Cat";
                s:5:"value";s:3:"Cat";
        }

        i:2; a:3:{
                s:2:"id";s:1:"3";
                s:4:"name";s:3:"Cow";
                s:5:"value";s:3:"Cow";
        }
}
In PHP it would look like this.
PHP Code:
$data = array(
        
'0' => array(
                
'id' => '1',
                
'name' => 'Dog',
                
'value' => 'Dog'
        
),
        
'1' => array(
                
'id' => '2',
                
'name' => 'Cat',
                
'value' => 'Cat'
        
),
        
'2' => array(
                
'id' => '3',
                
'name' => 'Cow',
                
'value' => 'Cow'
        
),
); 
So now we have the info stored, lets get it back out in a readable formate. This is the easy part. This is the code I use.

PHP Code:
$vbulletin->dropmenu unserialize($vbulletin->dropmenu);
foreach (
$vbulletin->dropmenu AS $dropmenu)
{
        echo 
"(ID: "  $dropmenu['id'] . ") (Title: " $dropmenu['title'] . ") (Value: " $dropmenu['title'] . ")<br />";

This will print the following:
(ID: 1) (Title: Dog) (Value: Dog)
(ID: 2) (Title: Cat) (Value: Cat)
(ID: 3) (Title: Cow) (Value: Cow)

What your doing is simple. The variable $vbulletin->dropmenu holds the information though it's still serialize. The reason why $vbulletin->dropmenu is the variable is because you need to tell vBulletin which datastore row to get. In this case it is dropmenu because remember we stored it in there like this: build_datastore('dropmenu', serialize($variable_array));

Now in order for vBulletin to know about that specific row, you need to add it to the $specialtemplates array. Example:

PHP Code:
$specialtemplates = array(
        
'dropmenu'
); 
So now that you understand where the variable is coming from, we need to unserialize the data, cause it looks all ugly and weird.

So $vbulletin->dropmenu = unserialize($vbulletin->dropmenu); baiscly gets the serialize info and unserialize's it using the function called unserialize() Once that is finished you want to loop the info using a foreach() function. foreach ($vbulletin->dropmenu AS $dropmenu). Doing that is storing the array info into $dropmenu and you can get each one by using the following vaiables. $dropmenu['id'], $dropmenu['title'], and $dropmenu['value'].

The reason why this is better is because vBulletin allready runs one global query to get all the datatore information. So instead of running a query everytime you want to get the drop down information, you just get it from the datastore and save that query. Some may think this is kinda extreme when you can just run a query, though as your site grows; you want to save as many queires as possiable.

If your interested in saving queries and bandwidth. I would suggest taking a look at Trigunflames profile. He has released many hacks to help in these areas.

Copyright ?2004-2006 vBHackers.com All Rights Reserved.
This tutorial may not be redistributed in whole or significant part.
Reply With Quote
  #22  
Old 09-28-2007, 02:23 PM
dwh's Avatar
dwh dwh is offline
 
Join Date: Feb 2002
Posts: 278
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

This was a great article and it explained the concept very well. I do have a minor quibble in your example. Rather than name= dog, value=dog, it might help people understand better if the var name and var value were different, e.g. name=dog, value=terrier.

Something I'd add to the discussion is that cron and serialize go hand in hand. The best place to use serialize is when accessing data frequently, therefore using vb's cached datastore w/o adding a query...but the updating of data is relatively infrequent. A classic way to update that data periodically is cron.
https://vborg.vbsupport.ru/showthrea...highlight=cron
Reply With Quote
  #23  
Old 11-09-2007, 06:34 PM
vertigo jones vertigo jones is offline
 
Join Date: May 2007
Posts: 70
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

I really hope they add a hook that will allow us to add to $specialtemplates before it's actually used. It's kind of a bummer to have to hack up a file over something so simple.

Not to suggest that adding the hook is simple. I think there's some initialization for the hook system in the datastore, or something along those lines. It's just a pain and it would be cool if they stumble across some fix in the future.
Reply With Quote
  #24  
Old 11-09-2007, 07:53 PM
Logikos Logikos is offline
 
Join Date: Jan 2003
Posts: 2,924
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by vertigo jones View Post
I really hope they add a hook that will allow us to add to $specialtemplates before it's actually used. It's kind of a bummer to have to hack up a file over something so simple.

Not to suggest that adding the hook is simple. I think there's some initialization for the hook system in the datastore, or something along those lines. It's just a pain and it would be cool if they stumble across some fix in the future.
I think the trick around that is with the "array_merge()" function. It's been awhile so I'm not completely sure, but I believe it's due to the $specialtemplates array being called before global.php.
Reply With Quote
  #25  
Old 11-10-2007, 01:14 AM
vertigo jones vertigo jones is offline
 
Join Date: May 2007
Posts: 70
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

It's because the query that uses $specialtemplates and populates the datastore variables comes before global_start. I don't really understand why, but I think it has something to do with the hook system not being able to work until the datastore info is available.
Reply With Quote
  #26  
Old 11-10-2007, 08:31 AM
Opserty Opserty is offline
 
Join Date: Apr 2007
Posts: 4,103
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Have you tried the init_startup hook? There is another Datastore fetch executed after it I think. This isn't tested but you could maybe try:

Hook Location: init_startup
PHP Code:
$datastore_fetch[] = "'dropmenu'"
Reply With Quote
  #27  
Old 11-10-2007, 08:45 PM
vertigo jones vertigo jones is offline
 
Join Date: May 2007
Posts: 70
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Awesome, thanks man. I haven't tested it either, but it looks like that should work.

--------------- Added [DATE]1194736320[/DATE] at [TIME]1194736320[/TIME] ---------------

Ok, it did work. It added the extra query, but it works.

You have to be careful and make sure it's like this though:

Code:
$datastore_fetch[] = "'dropmenu'";
Doing it without both sets of quotes makes everything (including the admincp) inaccessbile until you go in and correct it in both the plugin table and the datastore entry. They try to warn against it in the code, but I wasn't exactly sure what it meant.
Reply With Quote
  #28  
Old 11-11-2007, 09:03 AM
Opserty Opserty is offline
 
Join Date: Apr 2007
Posts: 4,103
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Ooops yup you need to put it in quotes because otherwise MySQL will read it as a column name instead of a value.

I'll correct it in my original post.
Reply With Quote
  #29  
Old 02-13-2008, 01:51 AM
Antivirus's Avatar
Antivirus Antivirus is offline
 
Join Date: Sep 2004
Location: Black Lagoon
Posts: 1,090
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

The Function build_datastore also has a 3rd parameter which should be mentioned, as it seems all serialized data in the datastore table requires a value of 1...

PHP Code:
#######################################################
/**
* Saves the specified data into the datastore
* @param    string    The name of the datastore item to save
* @param    mixed    The data to be saved
* @param        integer 1 or 0 as to whether this value is to be automatically unserialised on retrieval
*/

function build_datastore($title ''$data ''$unserialize 0
By setting the 3rd param to true, it's no longer necessary to run unserialize like this:
$vbulletin->dropmenu = unserialize($vbulletin->dropmenu);

There'fore we can just access the info from the datastore like this:

PHP Code:
$vbulletin->dropmenu['id'
Reply With Quote
  #30  
Old 06-05-2008, 05:11 PM
RobDog888's Avatar
RobDog888 RobDog888 is offline
 
Join Date: Apr 2007
Location: Degabah Swamp
Posts: 293
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

<font color="darkgreen">What if I have my own class object and I want to build cache acessible from it only and not use the $vbulletin object?

Like ...
$myclass->mycache['something']

instead of $vbulletin->mycache['something']

How would I change it so its like that?</font>
Reply With Quote
  #31  
Old 06-06-2008, 05:50 AM
briansol's Avatar
briansol briansol is offline
 
Join Date: Apr 2006
Location: CT
Posts: 254
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

With a couple tweaks (probably because this is 2 years old...), i've successfully got my first datastore plugin working

Thanks for the write up Ken. Never experienced with the datastore much.
Reply With Quote
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 06:42 PM.


Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2024, vBulletin Solutions Inc.
X vBulletin 3.8.12 by vBS Debug Information
  • Page Generation 0.04807 seconds
  • Memory Usage 2,339KB
  • Queries Executed 26 (?)
More Information
Template Usage:
  • (1)SHOWTHREAD
  • (1)ad_footer_end
  • (1)ad_footer_start
  • (1)ad_header_end
  • (1)ad_header_logo
  • (1)ad_navbar_below
  • (1)ad_showthread_beforeqr
  • (3)bbcode_code
  • (7)bbcode_php
  • (1)bbcode_quote
  • (1)footer
  • (1)forumjump
  • (1)forumrules
  • (1)gobutton
  • (1)header
  • (1)headinclude
  • (1)modsystem_article
  • (1)navbar
  • (4)navbar_link
  • (120)option
  • (1)pagenav
  • (1)pagenav_curpage
  • (4)pagenav_pagelink
  • (11)post_thanks_box
  • (1)post_thanks_box_bit
  • (11)post_thanks_button
  • (1)post_thanks_javascript
  • (1)post_thanks_navbar_search
  • (1)post_thanks_postbit
  • (11)post_thanks_postbit_info
  • (10)postbit
  • (11)postbit_onlinestatus
  • (11)postbit_wrapper
  • (1)spacer_close
  • (1)spacer_open
  • (1)tagbit_wrapper 

Phrase Groups Available:
  • global
  • inlinemod
  • postbit
  • posting
  • reputationlevel
  • showthread
Included Files:
  • ./showthread.php
  • ./global.php
  • ./includes/init.php
  • ./includes/class_core.php
  • ./includes/config.php
  • ./includes/functions.php
  • ./includes/class_hook.php
  • ./includes/modsystem_functions.php
  • ./includes/functions_bigthree.php
  • ./includes/class_postbit.php
  • ./includes/class_bbcode.php
  • ./includes/functions_reputation.php
  • ./includes/functions_post_thanks.php 

Hooks Called:
  • init_startup
  • init_startup_session_setup_start
  • init_startup_session_setup_complete
  • cache_permissions
  • fetch_threadinfo_query
  • fetch_threadinfo
  • fetch_foruminfo
  • style_fetch
  • cache_templates
  • global_start
  • parse_templates
  • global_setup_complete
  • showthread_start
  • showthread_getinfo
  • forumjump
  • showthread_post_start
  • showthread_query_postids
  • showthread_query
  • bbcode_fetch_tags
  • bbcode_create
  • showthread_postbit_create
  • postbit_factory
  • postbit_display_start
  • post_thanks_function_post_thanks_off_start
  • post_thanks_function_post_thanks_off_end
  • post_thanks_function_fetch_thanks_start
  • fetch_musername
  • post_thanks_function_fetch_thanks_end
  • post_thanks_function_thanked_already_start
  • post_thanks_function_thanked_already_end
  • post_thanks_function_fetch_thanks_bit_start
  • post_thanks_function_show_thanks_date_start
  • post_thanks_function_show_thanks_date_end
  • post_thanks_function_fetch_thanks_bit_end
  • post_thanks_function_fetch_post_thanks_template_start
  • post_thanks_function_fetch_post_thanks_template_end
  • postbit_imicons
  • bbcode_parse_start
  • bbcode_parse_complete_precache
  • bbcode_parse_complete
  • postbit_display_complete
  • post_thanks_function_can_thank_this_post_start
  • pagenav_page
  • pagenav_complete
  • tag_fetchbit_complete
  • forumrules
  • navbits
  • navbits_complete
  • showthread_complete