19
May
3

Symfony Parallel Content Delivery – UPDATE

UPDATED – 05-19-2011

I updated the script to make sure that it serves the same image from the same domain on each request. It’s counter productive to send the same image from different url’s as this increases the download time. This fix does not hash or internally check the image to see if it is identical to another image with a different name. This also does not store anything in a file or database, so it’s possible that the image will be served from a different url on a different page / request.

This is a drop in replacement for the original script. The interface for cdn_image_url and cdn_image_tag methods did not change.

Original Information

In order to reduce page latency, I’ve been implementing a parallel content delivery network on a large symfony project. This code should work on symfony and most any other php based site. What it does is allow a developer to specify a number of subdomains / domains for content delivery, such as content1.mydomain, content2.mydomain, etc… When serving images in this manner, one can greatly reduce page loading time by using multiple domains for images even if the domains are on the same server.

This script uses a singleton hack to keep a cursor of the current domain that the image is being served from. It then delivers the image in sequential order from the list of domains that the developer has pre-specified. A developer can specify as many domains as they want, and if the page is being served over a secure connection, the script will automatically include secure versions of the images. NOTE: make sure the domains have ssl installed correctly or errors will occur.

Add this script to a file in /myproject/lib/.

<?php
 
class Cdn {
 
    private $current_cdn;
    private $is_secure = 'http://';
    private $prefix_match = array();
    private static $instance;
    private static $domain = 'mydomain.com';
    private static $cdn = array('www.', 'cd1.', 'cd2.');
 
    private function __construct() {
 
        $this->current_cdn = 0;
 
        if ($_SERVER['SERVER_PORT'] == '443') {
 
            $this->is_secure = 'https://';
        }
    }
 
    public function cdn_image_url($image_path) {
 
        $cdn = $this->get_cdn($image_path);
 
        return $this->is_secure . $cdn . self::$domain . '/' . $image_path;
    }
 
    public function cdn_image_tag($image_path, $option_array=array()) {
 
        $options = null;
 
        $cdn = $this->get_cdn($image_path);
 
        if (count($option_array) > 0) {
            foreach ($option_array as $key => $attribute) {
                $options .= $key . '="' . $attribute . '" ';
            }
        }
 
        return '<img src="' . $this->is_secure . $cdn . self::$domain . '/' . $image_path . '" ' . $options . ' />';
    }
 
    private function get_cdn($image_path) {
 
        if (!isset(self::$cdn[$this->current_cdn])) {
            $this->current_cdn = 0;
        }
 
        if (array_key_exists($image_path, $this->prefix_match)) {
 
            $cdn = $this->prefix_match[$image_path];
        } else {
 
            $cdn = self::$cdn[$this->current_cdn];
        }
 
        $this->prefix_match[$image_path] = $cdn;
 
        $this->current_cdn++;
 
        return $cdn;
    }
 
    public static function getInstance() {
        if(self::$instance == NULL) self::$instance = new Cdn;
        return self::$instance;
    }
 
}

Then you can call your images using 1 of 2 methods throughout the project and they will be delivered sequentially through all of the domains in your CDN.

If you would just like the image url:

 $my_url = Cdn::getInstance()->cdn_image_url('images/my_image.jpg');

If you want the entire tag:

 echo Cdn::getInstance()->cdn_image_tag('images/swiped-box-b.jpg');

You can also add attributes to the tag:

 echo Cdn::getInstance()->cdn_image_tag('images/swiped-box-b.jpg', array('alt' => 'My Image'));

If your images are hosted on completely different domains, simply edit the $cdn property to include the full domain, and take out the self::$domain property from the appropriate method: cdn_image_url or cdn_image_tag.

This is a very basic class for delivering images from different domains. It does not take things into account like serving the same image from the same domain every time to take advantage of caching, or checking to see if the image actually exists. However, it should provide a basis for a more complete content delivery script.

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.
3 Comments:
  1. Massimiliano Arione 7 Oct, 2010

    DIRECTORY_SEPARATOR is pretty useless for urls.
    Urls use always normal slashes (thanks gods)

  2. Jerome 27 Oct, 2010

    Hello!

    I made a plugin based on your article :
    http://www.symfony-project.org/plugins/euzeoCDNPlugin

    Hope this will help 🙂

    Cheerz

  3. Neha 24 Jan, 2012

    How to implement Content Delivery Network in symfony2?any bundle for Content Delivery Network

Copyright © 2024 SayNoToFlash, Jamie Estep, All Rights Reserved · Theme design by Themes Boutique