Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
View Maarten Balliauw's MVP profile

Search

Latest Twitter

    Follow me on Twitter...

    My projects

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    Extension methods for PHP

    PHP Extension Methods The concept of “extension” methods will be nothing new to this blog’s .NET-related audience. For the PHP-related audience, this is probably something new. Let’s start with the official definition for extension methods: Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.

    Let’s visualize this. Imagine having the following class:

    class HelloWorld
    {
        public function sayHello($to = 'World', $from = null)
        {
            $helloString = "Hello, " . $to . "!";
            if (!is_null($from)) {
                $helloString .= " From " . $from;
            }

            echo $helloString . "\r\n";
        }
    }

    Not too difficult. There’s a sayHello() method that allows you to optionally pass who should be greeted and who the greeting is from. Imagine you would like to have a sayHelloTo() method as well, a shortcut to sayHello($to). And some other helper methods that use sayHello() under the hood. Wouldn’t it be nice to have the HelloWorld class concentrating on the real logic and defining the helper/utility functions somewhere else? How about a class named HelloExtensions:

    class HelloWorldExtensions
    {
        public static function sayHelloTo(HelloWorld $subject, $name = '')
        {
            $subject->sayHello($name);
        }

        public static function sayHelloFrom(HelloWorld $subject, $name = '')
        {
            $subject->sayHello('World', $name);
        }
    }

    Ok, nice. But this means I should call HelloWorldExtensions::sayHelloTo(‘Maarten’); to use the utility functions, right? Well: no! Not if we implement the concept of extension methods. Let’s see what we can do to HelloWorld in order to make our life easier.

    class HelloWorld
    {
        public function sayHello($to = 'World', $from = null)
        {
            $helloString = "Hello, " . $to . "!";
            if (!is_null($from)) {
                $helloString .= " From " . $from;
            }

            echo $helloString . "\r\n";
        }

        public function __call($functionName, $arguments = array())
        {
            // Add an extra parameter
            array_unshift($arguments, $this);

            // Current reflected class
            $reflectedClass = new reflectionObject($this);

            // Find suitable class and function
            $availableClasses = get_declared_classes();
            foreach ($availableClasses as $class) {
                $classDefinition = new ReflectionClass($class);
                $availableMethods = $classDefinition->getMethods();
                foreach ($availableMethods as $method) {
                    if ($method->isStatic() && $method->getName() == $functionName) {
                        $availableParameters = $method->getParameters();
                        if ($availableParameters[0]->getClass()->getName() == $reflectedClass->getName()) {
                            $method->invokeArgs(null, $arguments);
                        }
                    }
                }
            }
        }
    }

    The magic method __call() is used to look for a class that defines a static method with the first parameter of our type, HelloWorld. This now allows us to write very clean calls to code, as well as simplify our HelloWorld class:

    $helloWorld = new HelloWorld();
    $helloWorld->sayHello();
    $helloWorld->sayHelloTo('Maarten');
    $helloWorld->sayHelloFrom('Maarten');

    Sweet, no? Can someone get this into the PHP core? I would greatly appreciate it: my classes can focus on functionality and all utility functions that just pass around variables can be defined in a separate class.


    Book review: PHP 5 E-commerce Development

    9645_MockupCoverOnce again, Packt Publishing has asked me to do a book review on one of their latest books, "PHP 5 E-commerce Development” by Michael Peacock. The book promises the following:

    • Build a flexible e-commerce framework using PHP, which can be extended and modified for the purposes of any e-commerce site
    • Enable customer retention and more business by creating rich user experiences
    • Develop a suitable structure for your framework and create a registry to store core objects
    • Promote your e-commerce site using techniques with APIs such as Google Products or Amazon web services, SEO, marketing, and customer satisfaction

    All of this is true, but…

    1. The book does not make use of an existing framework. There are tons of them out there, so why re-invent the wheel to do specific tasks if someone already did that and tested and fine-tuned it.
    2. The book does make use of a custom, application-specific framework. However, the design of the framework is not clean enough in my opinion. It is based on MVC, yet it does have some portions of code that are sitting in the wrong place… SQL code in the controllers, no real abstraction of the data layer, …
    3. Inexperienced PHP developers will not learn the best-practices from this book.

    Not all is negative of course! The writing style is good and provides an easy read. Next to that, all concepts and pitfalls that go with building an online commerce site are well explained. Still, my advise on this book would not be “buy it”.


    Categories: Book review | General | PHP

    Linuxwochen Austria

    As part of my global domination plans, I this week visited Vienna, Austria for a session at Linuxwochen around PHP on Windows.

    PHP on Windows

    Abstract: “Ever wanted to get started with PHP development on Windows? This session covers the basics of running PHP on the Windows platform and will help getting your development environment ready.”

    Thanks for being in this session! I know it is a controversial one on a Linux event :-)


    TechDays 2010 Portugal slides and demo code

    First of all: thank you for attending the sessions Kevin Dockx and I gave at TechDays 2010 Portugal! A wonder we made it there with all the ash clouds and volcanic interference based in Iceland.

    Just Another Wordpress Weblog, But More Cloudy

    Abstract: “While working together with Microsoft on the Windows Azure SDK for PHP, we found that we needed an popular example application hosted on Microsoft’s Windows Azure. Wordpress was an obvious choice, but not an obvious task. Learn more about Windows Azure, the PHP SDK that we developed, SQL Azure and about the problems we faced porting an existing PHP application to Windows Azure.”

    I can not disclose demo code at this time, sorry. Here’s a list of good resources to get you started though:

    PHP and Silverlight

    Abstract: “So you have an existing PHP application and would like to spice it up with a rich and attractive front-end. Next to Adobe Flex, you can also choose Silverlight as a solution. This session shows you around in Silverlight and shows that PHP and Silverlight can go together easily.”

    Demo code: PHP and Silverlight - DevDays.zip (1.00 mb) (based on Silverlight 2, bug Kevin for a recent version :-))


    Using Windows Azure Drive in PHP (or Ruby)

    At the JumpIn Camp in Zürich this week, we are trying to get some of the more popular PHP applications running on Windows Azure. As you may know, Windows Azure has different storage options like blobs, tables, queues and drives. There’s the Windows Azure SDK for PHP for most of this, except for drives. Which is normal: drives are at the operating system level and have nothing to do with the REST calls that are used for the other storage types. By the way: I did a post on using Windows Azure Drive (or “XDrive”) a while ago if you want more info.

    Unfortunately, .NET code is currently the only way to create and mount these virtual hard drives from Windows Azure. But luckily, IIS7 has this integrated pipeline model which Windows Azure is also using. Among other things, this means that services provided by managed modules (written in .NET) can now be applied to all requests to the server, not just ones handled by ASP.NET! In even other words: you can have some .NET code running in the same request pipeline as the FastCGI process running PHP (or Ruby). Which made me think: it should be possible to create and mount a Windows Azure Drive in a .NET HTTP module and pass the drive letter of this thing to PHP through a server variable. And here’s how...

    Note: I’ll start with the implementation part first, the usage part comes after that. If you don’t care about the implementation, scroll down...

    Download source code and binaries at http://phpazurecontrib.codeplex.com.

    kick it on DotNetKicks.com

    Building the Windows Azure Drive HTTP module

    Building HTTP modules in .NET is easy! Simply reference the System.Web assembly and create a class implementing IHttpModule:

    public class AzureDriveModule : IHttpModule
    {
        void IHttpModule.Dispose()
        {
            throw new NotImplementedException();
        }

        void IHttpModule.Init(HttpApplication context)
        {
            throw new NotImplementedException();
        }
    }

    There’s our skeleton! Now for the implementation… (Note: insane amount of code coming!)

    public class AzureDriveModule : IHttpModule
    {
        #region IHttpModule Members

        public void Init(HttpApplication context)
        {
            // Initialize config environment
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
            });

            // Initialize local cache
            CloudDrive.InitializeCache(
                RoleEnvironment.GetLocalResource("cloudDriveCache").RootPath,
                RoleEnvironment.GetLocalResource("cloudDriveCache").MaximumSizeInMegabytes);

            // Determine drives to map
            for (int i = 0; i < 10; i++)
            {
                string driveConnectionString = null;
                try
                {
                    driveConnectionString = RoleEnvironment.GetConfigurationSettingValue("CloudDrive" + i);
                }
                catch (RoleEnvironmentException) { }

                if (string.IsNullOrEmpty(driveConnectionString))
                {
                    continue;
                }

                string[] driveConnection = driveConnectionString.Split(new char[] { ';' });

                // Create storage account
                CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting(driveConnection[0]);
                CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

                // Mount requested drive
                blobClient.GetContainerReference(driveConnection[1]).CreateIfNotExist();

                var drive = storageAccount.CreateCloudDrive(
                    blobClient
                        .GetContainerReference(driveConnection[1])
                        .GetPageBlobReference(driveConnection[2])
                        .Uri.ToString()
                );

                try
                {
                    drive.Create(int.Parse(driveConnection[3]));
                }
                catch (CloudDriveException ex)
                {
                    // handle exception here
                    // exception is also thrown if all is well but the drive already exists
                }

                string driveLetter = drive.Mount(
                    RoleEnvironment.GetLocalResource("cloudDriveCache").MaximumSizeInMegabytes, DriveMountOptions.None);

                // Add the drive letter to the environment
                Environment.SetEnvironmentVariable("CloudDrive" + i, driveLetter);
            }
        }

        public void Dispose()
        {
        }

        #endregion
    }

    Configuring and using Windows Azure Drive

    There are 4 steps involved in using the Windows Azure Drive HTTP module:

    1. Copy the .NET assemblies into your project
    2. Edit ServiceConfiguration.cscfg (and ServiceDefinition.csdef)
    3. Edit Web.config
    4. Use the thing!

    The Windows Azure tooling for Eclipse will be used in the following example.

    Copy the .NET assemblies into your project

    Create a /bin folder in your web role project and copy in all .DLL files provided. Here’s a screenshot of how this looks:

    .NET assemblies for XDrive in PHP on Azure

    Edit ServiceConfiguration.cscfg (and ServiceDefinition.csdef)

    In order to be able to mount, some modifications to ServiceConfiguration.cscfg (and ServiceDefinition.csdef) are required. The ServiceDefinition.csdef file should contain the following additional entries:

    <?xml version="1.0" encoding="utf-8"?>
    <ServiceDefinition name="TestCustomModules" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
      <WebRole name="WebRole" enableNativeCodeExecution="true">
        <ConfigurationSettings>
          <Setting name="CloudDriveConnectionString" />  
          <Setting name="CloudDrive0" />   
        </ConfigurationSettings>
        <InputEndpoints>
          <!-- Must use port 80 for http and port 443 for https when running in the cloud -->
          <InputEndpoint name="HttpIn" protocol="http" port="80" />
        </InputEndpoints>
        <LocalStorage name="cloudDriveCache" sizeInMB="128"/>
      </WebRole>
    </ServiceDefinition>

    Things to note are the cloudDriveCache local storage entry, which is needed for caching access to the virtual drive. The configuration settings are defined for use in ServiceConfiguration.csdef:

    <?xml version="1.0"?>
    <ServiceConfiguration serviceName="TestCustomModules" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
      <Role name="WebRole">
        <Instances count="1"/>
        <ConfigurationSettings>
          <Setting name="CloudDriveConnectionString" value="UseDevelopmentStorage=true" />
          <Setting name="CloudDrive0" value="CloudDriveConnectionString;drives;sampledrive.vhd;64" />
        </ConfigurationSettings>
      </Role>
    </ServiceConfiguration>

    The configuration specifies that a cloud drive “CloudDrive0” (up to “CloudDrive9”) should be mounted using the storage account in “CloudDriveConnectionString”, a storage container named “drives” and a virtual hard disk file named “sampledrive.vhd”. Oh, and the drive should be 64 MB in size.

    Edit Web.config

    Before the HTTP module is used by IIS7 or Windows Azure, the following should be added to Web.config:

    <modules>
      <add name="AzureDriveModule" type="PhpAzureExtensions.AzureDriveModule, PhpAzureExtensions"/>
    </modules>

    Here’s my complete Web.config:

    <?xml version="1.0"?>
    <configuration>
      <system.webServer>
        <!-- DO NOT REMOVE: PHP FastCGI Module Handler -->
        <handlers>
          <clear />
          <add name="PHP via FastCGI"
               path="*.php"
               verb="*"
               modules="FastCgiModule"
               scriptProcessor="%RoleRoot%\approot\php\php-cgi.exe"
               resourceType="Unspecified" />
          <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
        </handlers>
        <!-- Example WebRole IIS 7 Configation -->
        <defaultDocument>
          <files>
            <clear />
            <add value="index.php" />
          </files>
        </defaultDocument>

        <modules>
          <add name="AzureDriveModule" type="PhpAzureExtensions.AzureDriveModule, PhpAzureExtensions"/>
        </modules>
      </system.webServer>
    </configuration>

    Use the thing!

    Next thing to do is use your virtual Windows Azure Drive. The HTTP module adds an entry in the $_SERVER variable, named after the CloudDrive0-9 settings defined earlier. The following code example stores a file on a virtual Windows Azure Drive and reads it back afterwards:

    <?php
    file_put_contents($_SERVER['CloudDrive0'] . '\sample.txt', 'Hello World!');

    echo file_get_contents($_SERVER['CloudDrive0'] . '\sample.txt');

    Source code in PHPAzureContrib (CodePlex)

    Since there already is a project for PHP and Azure contributions, I decided to add this module to that project. The binaries and source code can be found on http://phpazurecontrib.codeplex.com.

    Other possible usages

    The approach I demonstrated above may be used for other scenarios as well:

    • Modifying php.ini before PHP runs. The module you can access would run before FastCGI runs, an ideal moment to modigy php.ini settings and such.
    • Using .NET authentication modules in PHP, check this site for an example.
    • Download updates to PHP automatically if a new version is available and deploy it into your application at runtime. Probably needs some performance tuning but this trick may work. The same goes for static content and script updates by the way. Imagine pulling a website dynamically from blob storage and deploy it onto your web role without any hassle…

    In short: endless possibilities!

    kick it on DotNetKicks.com


    Categories: ASP.NET | Azure | C# | General | PHP | Projects

    Running PHP on Windows Azure

    Yesterday I did some talks on PHP and Windows Azure at JumpIn Camp in Zürich together with Josh Holmes. Here are the slide decks and samples we used.

    Scaling Big while Sleeping Well

    Josh talked on what Windows Azure is, what components are available and how you can get started with PHP and Windows Azure.

    Running PHP in the Cloud

    I did not do the entire deck, but showed some slides and concepts. This is mainly the same content as Josh’s session with some additions.

    Windows Azure Storage & SQL Azure

    This deck talks about the different storage concepts and how to use them in PHP.

    Sample code

    As a demo, I had ImageCloud, a web application similar to Flickr. Here’s the sample code: ImageCloud.rar (5.00 mb)


    Running PHP in the Cloud slides and sample code

    Just got back from London where I did a fun talk on PHP and Windows Azure yesterday evening. It was the first time I did a presentation after three beers, but I think it went allright. As promised, here's the slide deck and sample code (ImageCloud.rar (5.00 mb)).

    Abstract: "This session covers the basics of Microsoft’s Windows Azure cloud platform. Learn how you can develop and deploy a PHP application in Windows Azure, using the tools and libraries Microsoft provides. Creating a photo upload application, the different aspects of the Windows Azure platform are leveraged for creating a performant and scalable PHP application."

    Thanks for joining the conference and my session! Also, Robert Castelo, your talk on Drupal and its community was interesting. Did not know the active developer base and security teams were that big.


    Jump in! camp - Call for participants

    Jump In! Camp I just got the following invitation from Microsoft, and would like to encourage  you to participate as well if you are interested in bot PHP and the Microsoft worlds.

    Jump In! and be a part of it!

    Open source programming and Microsoft: two incompatible worlds? Microsoft is partnering with renowned actors of the open-source community to organise the Jump In! Developers' Camp in an effort to combat this misperception. Twenty-five knowledge-hungry open source application developers from all over Europe will be invited to spend four unforgettable days of dialogue, networking and workshops at the beautiful Panorama Resort & Spa Feusisberg in Switzerland.

    The Jump In! Developers' Camp is designed primarily for open-source application developers who are interested in increasing their skills in a range of specific areas. Here they will be able to experiment with ways of combining open-source technologies with Microsoft products to optimize applications. But don’t worry: no one is out to ‘convert’ anybody! The aim instead is to promote interoperability, problem-solving and enhance programming skills. Software experts will be on hand to provide tips and advice, and a range of workshops will be held on topics including Azure, IIS, Silverlight and more in combination with open-source applications. Plenty of time for actual coding will be available.

    Potential participants are invited to file an application at www.jumpincamp.com, outlining their profile. The 25 developers who are creating the most “buzz” for themselves and their programming abilities will then be selected. Attendees of the JumpIn! Developers' Camp will then record their impressions and experiences in a live blog for their community of ‘followers’. The Camp will be held between 6 - 9 April 2010.

    Register now and apply for taking part on www.jumpincamp.com.


    Categories: Events | General | PHP

    Just Another Wordpress Weblog, But More Cloudy

    4322759659_6cab114506_b Slides of my talk at the PHPBenelux conference last weekend are online. Bit of a pity my live demo went wrong due to my www.azure.com trial account going into read-only mode while doing the demo.

    Abstract: "While working together with Microsoft on the Windows Azure SDK for PHP, we found that we needed an popular example application hosted on Microsoft’s Windows Azure. Wordpress was an obvious choice, but not an obvious task. Learn more about Windows Azure, the PHP SDK that we developed, SQL Azure and about the problems we faced porting an existing PHP application to Windows Azure."

    Thanks for joining the conference and my session! And thanks to the PHPBenelux crew for organizing their first conference ever, it rocked!


    PHPMEF 0.1.0 released!

    PHP MEF A while ago, I did a conceptual blog post on PHP Managed Extensibility Framework – PHPMEF. Today, I’m proud to announce the first public release of PHPMEF! After PHPExcel, PHPLinq, PHPPowerPoint and the Windows Azure SDK for PHP, PHPMEF is the 5th open-source project I started on interoperability (or conceptual interoperability) between the Microsoft world and the PHP world. Noble price for peace upcoming :-)

    What is this thing?

    PHPMEF is a PHP port of the .NET Managed Extensibility Framework, allowing easy composition and extensibility in an application using the Inversion of Control principle and 2 easy keywords: @export and @import.

    PHPMEF is based on a .NET library, MEF, targeting extensibility of projects. It allows you to declaratively extend your application instead of requiring you to do a lot of plumbing. All this is done with three concepts in mind: export, import and compose. “PHPMEF” uses the same concepts in order to provide this extensibility features.

    Show me an example!

    Ok, I will. But not here. Head over to http://phpmef.codeplex.com and have a look at the principles and features behind PHPMEF.

    Enjoy!


    Categories: C# | General | MEF | PHP | Projects