Showing posts with label class. Show all posts
Showing posts with label class. Show all posts

Thursday, February 3, 2011

Using Memcached in PHP in addition to a MySQL Database

I've been hearing a lot of buzz lately about NoSQL solutions. I personally don't think that relational databases will ever be obsolete. However, I do know from experience that you can dramatically improve the performance and scalability of your MySQL based web app by implementing a caching layer using Memcached.

I am going to walk you through some basic examples here.

I am assuming that you already have your caching server or servers set up, this is just going to walk through the PHP code to talk to your existing servers. If you need set up instructions check out This Link.

I usually use objects to access my database so first I am going to create an abstract class with a memcached connection method for the child classes to inherit.

abstract class MasterData
{
 
   protected $myCache; //memcache object
 
   /********************************************************
   *************** Start MasterData Methods ****************
   *********************************************************/
 
   /* Constructer. Initialize all objects */
   public function __construct() {
      // here we call our memcache creation method
      // in real life our constructor would do more 
      // than this, but this isn't real life, this is
      // my blog
      $this->createCache();
   }
 
   /* Create memcache object */
   public function createCache() {
      // load a memcache object into the myCache property
      $this->myCache = new Memcache;
      
      // CACHE_HOST and CACHE_PORT are constants that should be set
      // in your configuration file to the ip address and port of 
      // your cache server
      $this->myCache->connect(CACHE_HOST, CACHE_PORT);
   }
  
   /********************************************************
   ************** End MasterData Methods *******************
   *********************************************************/

}

Now we are going to create a child object that can extend this MasterData object.

// our fictional CommentData class that extends our MasterData class
class CommentData extends MasterData
{
   /********************************************************
   *************** Start Comment Methods *******************
   *********************************************************/
 
   /* get comment list for a post */
   public function getPostCommentList($postID) {
      // first we check to see if this data is cached.
      // we send the get method a unique key that we
      // use to save this queries data
      $cacheResult = $this->myCache->get('postcomments:'.$postID);

      // if we found a valid cached result for this, we dont have 
      // to run our query, we can just return the result
      if ($cacheResult !== FALSE) {
         return $cacheResult;
      } 
      
      // we didnt find our comment in the cache, so now we will get 
      // it from the database, this example is using Propel ORM to run
      // our query, google PHP Propel for more info
      $commentList = tblPostCommentQuery::create()
         ->filterByPostID($postID)
         ->setFormatter('PropelArrayFormatter')
         ->find();
  
      // update the cache, from now on we wont have to look in the database
      // since we are saving a valid cache result.  The parameters here are 
      // first, a unique key, second, our actual data, third, false to tell 
      // memcache not to compress the data, and last our MCEXPIRE constant is 
      // set to the expiration time in seconds up to 2592000 (30 days).
      $this->myCache->set('postcomments:'.$postID, $commentList, false, MCEXPIRE);
  
      // return the result
      return $commentList; 
   }

   /********************************************************
   ************** End Comment Methods **********************
   *********************************************************/
}

As you can probably guess, since Memcached stores information in memory and uses a single key to grab your data, it will be much more efficient than your MySQL database. Using Memcached this way allows you to retain the advantages of long term storage in a relational database, while utilizing a NoSQL layer for short term performance gains.

In other words, you can have your cake and eat it to.

Monday, January 17, 2011

Using Smarty PHP Template Engine for Your Design Layer

Looking for a template engine for your latest web application? The good folks over at Smarty have got you covered.

I have been using Smarty for quite awhile now and it has been great. I won't go into all of the reasons I prefer it to some of the other options out there, but I will show you how to use it...

First, you need to download the source from the Smarty website: http://www.smarty.net/download

Now you are ready to get your hands dirty.

The PHP side will look something like this:

// first include the smarty library
include('Smarty.class.php');

// now we create the smarty object
$smarty = new Smarty;

// now we tell smarty where to look for template files
// and where to store compile/config/cache info
$smarty->template_dir = THEFULLPATH.'views/templates/';
$smarty->compile_dir  = THEFULLPATH.'views/templates_c/';
$smarty->config_dir   = THEFULLPATH.'views/configs/';
$smarty->cache_dir    = THEFULLPATH.'views/cache/';

// lets assign our data to template variables now
// in real life you would be getting this data
// from user input or a database, but here we
// are just using a static value
$smarty->assign('FullName', 'Jon Doe');

// display the template
$smarty->display('mytemplate.tpl');

Not bad so far ... now lets create the actual template:

<html>
   <head>
      <title>Hello World</title>
   </head>
   <body>
      Hello {$FullName}
   </body>
</html>

As you can see, Smarty is pretty simple to use. If you would like to become a Smarty expert, a good place to start is here: http://www.smarty.net/crash_course

Saturday, January 8, 2011

PHP Autoload

I fought it for a long time, but I think I am finally convinced that PHP autoload functionality is a good idea.

In case anyone out there needs an example, the following is a custom autoload function that allows for multiple directories to be checked for class files.

Just a quick note, the 'THEFULLPATH' constant should already be set to your server path, and the directories array should be updated to include the directories that your class files are in.

// global function for autoload functionality
function class_autoload($class_name)
{
   // directories where class files are located
   $directory_list = array(
      THEFULLPATH.'common/',
      THEFULLPATH.'models/',
   );

   // for consistency make sure the class name is lower case
   $class_name = strtolower($class_name);

   // for each directory in our directory list
   foreach ($directory_list as $directory)
   {
      // does the file exist? notice the naming convention used here
      // is classname.class.php, feel free to use your own naming 
      // structure and modify the following lines to fit, just 
      // be consistent
      if (file_exists($directory.$class_name.'.class.php'))
      {
         require($directory.$class_name . '.class.php');
         // only require the class once, we exit here to cut down on 
         // processing time
         return;
      } 
   }

   // if we are dealing with another class that had a different 
   // naming convention we add it here if you have many classes 
   // like this (and they should be common libraries, since if 
   // you are writing them they should follow your convention) 
   // you may want to change this to a switch statement
   if ($class_name == 'phpmailer') {
      require(THEFULLPATH."common/PHPMailer/class.phpmailer.php");
   }
}

Once you have created your function, you will need to register it with PHP

spl_autoload_register('class_autoload');

Congratulations, you now have a working autoload function!

For more information on PHP autoload, read the manual Here