Showing posts with label array. Show all posts
Showing posts with label array. 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.

Tuesday, January 18, 2011

PHP array_map

One very useful function in PHP is array_map.

Today I am going to show you an example of how you can use this function to quickly filter possibly dangerous data in an array to prevent XSS attacks.

First you will need to create a function that will be used to clean the data:

// heres function that escapes html data to prevent xss attacks
function map_entities($str) {
    return htmlspecialchars($str, ENT_QUOTES);
} 

Next you need to apply that data to an array containing user input (in real life this could be from a $_POST or $_GET or even from a database:

// here $suspect_data is an array containing data needing to be cleaned
$safe_data = array_map('map_entities',$suspect_data);

And now our array is ready for use ... obviously there is more to filtering data then just stripping html characters, but hopefully this little tutorial is helpful in showing you how you can use array_map to solve some real life problems.