Saturday 1 December 2012

sticky footer

Here I'm going to show you a super simple way of making sure that your footer stays at the bottom of your page without hard-coding your height or setting position as absolute


There are three main elements

  • pageContent
  • offSet
  • footer

The CSS
* {
 margin: 0;
}
html, body {
 height: 100%;
}
.pageContent {
 min-height: 100%;
 height: auto !important;
 height: 100%;
 margin: 0 auto -25px;
}
.offSet{ /* the offset is used to stop the footer from over laping with the page content */
height: 25px; 
}

.footer {
 background-color:#000;
 color:#fff;
 height: 25px;
}

The HTML


 

Boy desirous families prepared gay reserved add ecstatic say

Comfort reached gay perhaps chamber his six detract besides add. Moonlight newspaper up he it enjoyment agreeable depending. Timed voice share led his widen noisy young. On weddings believed laughing although material do exercise of. Up attempt offered ye civilly so sitting to. She new course get living within elinor joy. She her rapturous suffering concealed. Started earnest brother believe an exposed so. Me he believing daughters if forfeited at furniture. Age again and stuff downs spoke. Late hour new nay able fat each sell. Nor themselves age introduced frequently use unsatiable devonshire get. They why quit gay cold rose deal park. One same they four did ask busy. Reserved opinions fat him nay position. Breakfast as zealously incommode do agreeable furniture. One too nay led fanny allow plate.


Once done you should end up with something like the following:

... continue reading!

Monday 5 November 2012

Moving sub-domian on Wordpress

Wordpress has a nasty habit of keeling over and dying when it is moved from one directory, or server, from another. This is because it is not just static html and css pages and it has quite a lot of relevant links to where it was originally based. For example it requires a database which contains links to the site url and config files which link to the database. The use case for this was changing the theme of a codemeasandwich.com wordpress blog. Another test site was set up so themes and layout changes could be made without affecting the live site. From researching there seems to be plugins and services that help facilitate this better but these are more for server migration and also don't seem to be much simpler than this was for switching directories and such. Also there is more initial steps in this method but after this is done there will constantly be a test environment available for future wordpress development.
These are the steps taken to set up new.codemeasandwich.com:

  1. Add new sub-domain to gandi.net under codemeasandwich.com called "new"

  2. On DEV VM: Create new git repo called codemeasandwich_site using the create_repo.sh script

  3. On sites vm:

    sudo mkdir /var/www/testing.codemeasandwich.com

  4. Clone repo you made into the directory you created:

    git clone
    ssh://git@dev.codemeasandwich.com:2222/home/git/codemeasandwich_site.git testing.codemeasandwich

  5. Copy files from codemeasandwich directory into the testing.codemeasandwich directory:

    cd /var/www/codemeasandwich
    sudo cp -R * ../testing.codemeasandwich

  6. From within the testing/codemeasandwich directory push to master:

    sudo git add *
    sudo git commit
    sudo git push origin master

  7. Add a reference in /etc/apache2/sites-available/sites for the new sub-domain and restart apache:
    
            Use VHostSetup new.codemeasandwich.com testing.codemeasandwich
            ServerAlias www.new.codemeasandwich.com
    
    
    sudo service apache2 restart

  8. I also needed to chown -R the new testing.codemeasandwich directory to www-data, I will explain this in depth later:

    sudo chown www-data -R *

The remaining changes are to do with the database:

  1. Log into dev.codemeasandwich.com/phpmyadmin
  2. Export database codemeasandwich_wordpress to your local machine
  3. Create new empty database, in this case called newcodemeasandwich_wordpress
  4. Import the old database you downloaded to your local machine
  5. Add user "sandwich" and grant the user all privileges
  6. From inside the database click on wp-options on the list on the left
  7. From this table find the entries for siteurl and home, change them to point to your new sub-domain
  8. Lastly from the sites vm change the database being used for the wordpress:
    cd /var/www/testing.codemeasandwich
    sudo vim wp-config.php
The line:
/** The name of the database for WordPress */
define('DB_NAME', 'codemeasandwich_wordpress');
Should be changed to:
/** The name of the database for WordPress */
define('DB_NAME', 'newcodemeasandwich_wordpress');
The site should now be fully functioning from your new sub-domain.

Common errors with Wordpress

Uploaded file could not be moved to...
This happened after we finished moving the site and realised that images and such weren't able to be uploaded. The error that would appear is Uploaded file could not be moved to:/some/directory/uploads. From researching the problem online it seems to occur quite often and the reason it happens is that Wordpress does not have permission to place the file in the directory mentioned.

The top fix online was to  chmod 777  the directories but this is dangerous as someone could hack in and place their own images and we don't want that now do we?(Do we?)!? I noticed, by using  ls -la  on the directory that all the folders belonged to root but the original codemeasandwich directory had belonged to www-data. This was the problem and a simple  sudo chown www-data -R *  fixed the problem. I still don't know how the copying of the files changed the ownership but it did, so deal with it!
... continue reading!

Sunday 21 October 2012

SimpleTest CheatSheet

PHP Unit Testing with SimpleTest

Following on from my getting up & running with SimpleTest I thought it would be good to give you guys a list of the assertions you will become all too familiar with.. very soon :D

So, There are a variety of different assertions

All of these functions are contained in unit_tester.php

assertTrue(x)
Fail if x is false
assertFalse(x)
Fail if x is true
assertNull(x)
Fail if x is set
assertNotNull(x)
Fail if x not set
assertIsA(x, t)
Fail if x is not the class or type t
assertEqual(x, y)
Fail if x y is false
assertNotEqual(x, y)
Fail if x y is true
assertIdentical(x, y)
Fail if x === y is false
assertNotIdentical(x, y)
Fail if x === y is true
assertReference(x, y)
Fail unless x and y are the same variable
assertCopy(x, y)
Fail if x and y are the same variable
assertWantedPattern(p, x)
Fail unless the regex p matches x
assertNoUnwantedPattern(p, x)
Fail if the regex p matches x
assertNoErrors()
Fail if any PHP error occoured
assertError(x)
Fail if no PHP error or incorrect message

Encapsulating Tests

When needing to do some work before and after every test, SimpleTest has setUp() and tearDown() methods which are run before and after every test respectively.
Convenience methods for debugging code or Extending the suite

pass()
Sends a test pass
fail()
Sends a test failure
error()
Sends an exception event
signal($type, $payload)
Sends a user defined message to the test reporter
dump($var)
Does a formatted print_r() for quick and dirty debugging

To get you started. Here is a standard unit test class called UnitTestCase. That can be used as a super class also.

Mocks as actors

set return values simulate connection

Mocks as critics

expect results
expect($method, $args)
Arguments must match if called
expectAt($timing, $method, $args)
Arguments must match when called on the $timing'th time
expectCallCount($method, $count)
The method must be called exactly this many times
expectMaximumCallCount($method, $count)
Call this method no more than $count times
expectMinimumCallCount($method, $count)
Must be called at least $count times
expectNever($method)
Must never be called
expectOnce($method, $args)
Must be called once and with the expected arguments if supplied
expectAtLeastOnce($method, $args)
Must be called at least once, and always with any expected arguments

And that it. Have fun! :)
... continue reading!

Tuesday 9 October 2012

Getting up & running with SimpleTest (2 of 2)

4.Reusing The Test Case

We can not only use the library assert functions ,but also can create our own assert functions. Also we can reuse test cases that we have defined. Next I would like to talk about how to define new assert functions and reuse test cases.

Firstly, take a look at our testClockTellsTime function which is defined in the clock_test.php. Assume we need to run the clock test hundred times, the test may be out by one second and would cause a failure. Therefore, I add the one second into our acceptable range. Create a new class called TimeTestCase into clock_test.php to fix that. And then, reusing the TimeTestCase.
class TimeTestCase extends UnitTestCase {
    function __construct($test_name=false) {                  
    //If leave it as blank, it will display the subclass's name   
        parent::__construct($test_name);
    }
    
    function assertSameTime($time1, $time2, $message=false) {
        if ( ! $message) {//If there is no message send in, it means that the test fail, show the message below.
           $message = "Time [$time1] should match time [$time2]"; 
        }
        
        $result = ($time1 == $time2) OR ($time1 + 1 == $time2);
        
        $this->assertTrue($result , $message);
                //add one second into our acceptable range 
        }
    }
}

class TestOfClock extends TimeTestCase {
    function TestOfClock() {
        $this->TimeTestCase('Clock class test');
    }
    function testClockTellsTime() {
        $clock = new Clock();
        $this->assertSameTime($clock->now(), time(), 'Now is the right time');
    }
    function testClockAdvance() {
        $clock = new Clock();
        $clock->advance(10);
        $this->assertSameTime($clock->now(), time() + 10, 'Advancement');
    }
}

Now, we can reuse the TimeTestCase.
There is a situation, if we combine this with other tests into our all_test.php. The system will recognize our reused test case as a individual case and test it. In order to prevent it, we could simply add abstract keyword to make the reused class as an abstract class that the system will not go into it. Another way is add "SimpleTestOptions::ignore('classname');" before the reused class, where the classname is reused class's name. In our case, we should add "SimpleTestOptions::ignore('TimeTestCase ');" before TimeTestCase class.

5.Using Mock Objects

Mock is a very powerful and useful technique in Unit Test. You can use a mock object to simulate the original class and can set arbitrary return values to test your function.
Firstly, I would like to use a simple example to explain how to use a mock object.
As you can see, we have set a log file that should be able to record some log information. Next, I will add a time stamp after the each log message.
Change the log.php as following
_file_path=$file_path;
   }

   function message($message){           

           $clock = new Clock();
           $file=fopen($this->_file_path,'a');
        fwrite($file,"[".$clock->now()."]$message.\n"); //add the time stamp to the log file
        fclose($file);    
   }
}


Then, if we test our log file by using log_test.php, the result will be failed. The reason is that we added the the stamp at the end of each log message, but we did not change our test program to match the new log message format. So we modify our log_test.php as following.
assertFalse(file_exists('temp/test.log'),'No file created before first message');
        $log->message('Should write this to a file');
        $this->assertTrue(file_exists('temp/test.log'),'File created');

    }
    function testAppendingToFile(){    
        $log=new Log('temp/test.log');
        $log->message('Test line 1');
        $message=file('temp/test.log');
        $this->assertPattern('/Test line 1/', $this->getFileLine('temp/test.log',0));
        $log->message('Test line 2');
        $message=file('temp/test.log');
        $this->assertPattern('/Test line 2/', $this->getFileLine('temp/test.log',1));    
    }

// new function to test time stamps    
    function testTimestamps(){
        $log = new Log('temp/test.log');  // create log file
        $log->message('Test line');       // add a log message

        $this->assertTrue(
            preg_match('/(\d+)/',$this->getFileLine('temp/test.log',0),$matches),'Found timestamp'  
            // test whether the digits are in the log message or not
        );
        $clock = new Clock();  
        $this->assertSameTime((integer)$matches[1],$clock->now(),'Correct time'); 
        //test whether the time stamp are as same as the current time  

    }
}
OK, now we run our test again. We should pass all tests now. And you should be able to see the time stamps matched in the pass message.
The time stamps are always changing, however, we do not want to test them every time if we knew they have no problems. Is there an easy way to bypass testing every second? Yes, we can use a mock object to solve this problem.
By using the mock object, we can set the return value to a constant, such as a string. Then, we only need to match the string rather than match the time stamps.
To use a mock object, we need add following code
<-- log_test.php -->
require_once ('simpletest/mock_objects.php');
Mock::generate('Clock');  // using Mock::generate('Class name') to create a mock object, where "Class name" is the class you want to mock it.  
Add these two lines before the class definition.
If you would like to check what Mock::generate() does, you could using print (Mock::generate()) to print it out.
Change the log_test.php again.
assertFalse(file_exists('temp/test.log'),'No file created before first message');
        $log->message('Should write this to a file');
        $this->assertTrue(file_exists('temp/test.log'),'File created');

    }
    function testAppendingToFile(){    
        $log=new Log('temp/test.log');
        $log->message('Test line 1');
        $message=file('temp/test.log');
        $this->assertPattern('/Test line 1/', $this->getFileLine('temp/test.log',0));
        $log->message('Test line 2');
        $message=file('temp/test.log');
        $this->assertPattern('/Test line 2/', $this->getFileLine('temp/test.log',1));

    }

    // Mock object

    function testTimestamps(){ 
        $clock = new MockClock($this);                       // mock object
        $clock->setReturnValue('now','Timestamp');           
        // mock object, set the return value to take place of the actual time stamp
         // The setReturnValue function is one of mock functions
         // There are also many other useful functions, 
         // you can print mock object out and check them 
        $log = new Log('temp/test.log');
        $log->message('Test line', $clock);
        $this->assertPattern('/Timestamp/',$this->getFileLine('temp/test.log',0), 'Found timestamp');  // only need to mathch the string 

        // we do not need those stuff anymore
        //$this->assertTrue(
        //    preg_match('/(\d+)/',$this->getFileLine('temp/test.log',0),$matches),'Found timestamp'
        //);
        //$clock = new Clock();
        //$this->assertSameTime((integer)$matches[1],$clock->now(),'Correct time');

    }
}
Now, run log_test.php again. You should be able to see, we did not exactly match the time stamps, but the results passed.
I just introduce one simplest way to use mock objects. When you generate a mock object to a class, the mock object actually creates a subclass for that class. All the functions of the original class are simulated by the mock object. You can set any return values for each function of the original class by using mock object in order to test what results you will get. You can also simulate the database connection rather than really connect database in your each testing.
For more details of using mock objects, please check simpletest's mock objects documentation.

Reference

This tutorial refer to the original tutorial at lastcraft.com ~ first test tutorial. All the code and ideas are come from the original tutorial. I just made that more clear and added some comments. If you are confused, please check the original tutorial.
The code in original tutorial worked on the old version. If you cannot follow the original tutorial, please check mine.


hope this will be helpful.
... continue reading!

Friday 5 October 2012

Getting up & running with SimpleTest (1 of 2)

Today we are going to work on something that I know every developer loves.
Unit-Tests! Well, you will once you get a handle on them. For this we are going to use the test framework SimpleTest from simpletest.org

Download and install SimpleTest

Download the current release version SimpleTest 1.1.0 *as of this writing. Then extract it into the directory that your web server can see. I unzipped it into C:/xampp/htdocs/tests/simpletest.

You can also install it a Eclipse Plugin.
Choose Help->Install New Software.. and type in "http://simpletest.org/eclipse/".


1.Creating A Test Case

I'd like to use an example to explain how to create a test case and how to use it to test a php file. The test target file named log.php which is used to create a log file.
Firstly, I create a empty directory as the root directory. Then I move the simpletest(the library folder) into the root directory. After that, I create two folders. One is named classes which contains the test target php file. Another one is temp where the log files will be created.
Next is the code in log.php.
<-- log.php --> 
<?php
class Log{
   var $_file_path;
   function Log($file_path){
      $this->_file_path = $file_path;
   }
   function message($message){
      $file=fopen($this->_file_path,'a');
      fwrite($file,$message."\n");
      fclose($file);
   }
}

The log_test.php is the test case which is used to test log.php. I put this file in the same folder with simpletest library.
The autorun.php is used to automatically run the test process. And you need to include the target test file in order to test each function of it. 
<-- log_test.php -->
require_once ('simpletest/autorun.php');
require_once ('classes/log.php'); 
In this part, there are four functions. The constructor sets the test name. The setUp and tearDown functions are used to create and delete the log file respectively. The getFileLine function is used to read the message in the file. 
<-- log_test.php Continue... -->
class TestOfLogging extends UnitTestCase{    
    function __construct(){
        parent::__construct('Log class test');
    } 
    function setUp(){
        @unlink('temp/test.log'); 
     //if setUp at the function beginning, then the test.log will be written in temp/ floder.
    }
    function tearDown(){
        @unlink('temp/test.log'); 
     // if call tearDown on the bottom of the function again, the test.log will be deleted.
    }
    function getFileLine($filename,$index){
        $messages=file($filename);
        return $messages[$index];    
    }
The next two functions are the actual testing functions.
The testCreatingNewFile function is used to test whether the test.log file created or not. The assertTrue() and assertFalse() are the library functions that are defined in the unit_tester.php. There are also many other assert functions in the simpletest library. They are listed below. Those assert functions are used to report the assertion and display a message. The messages should be set as the last parameter for every assert function.
<-- log_test.php Continue...  -->
    function testCreatingNewFile(){
        $log=new Log('temp/test.log');
        $this->assertFalse(file_exists('temp/test.log'),'No file created'); 
       // if the file exists, the assertion will be fail. Otherwise, it will be true.
        $log->message('Should write this to a file');                    
       // create the test.log and write message into it.
        $this->assertTrue(file_exists('temp/test.log'),'File created');  
        // if the file exists, the assertion will be true. Otherwise, it will be fail.
    }
The testAppendingToFile function is testing the contents of test.log.
<-- log_test.php Continue... -->
    function testAppendingToFile(){    
        $log=new Log('temp/test.log');
        $log->message('Test line 1');   // write the message into test.log
        $this->assertPattern('/Test line 1/', $this->getFileLine('temp/test.log',0)); //Using getFileLine() to read first message in test.log. 
                                                                                              //If the pattern in first parameter match with the second,
                                                                                              //the assertion will be true.  
        $log->message('Test line 2');        
        $this->assertPattern('/Test line 2/', $this->getFileLine('temp/test.log',1));    
    }
}
Next is to execute the test.
<-- log_test.php Continue... -->
} //end the class

$test = new TestOfLogging(); //instance
$test->run(new HtmlReporter()); // HtmlReporter is used to show out the result.
?>
If the test succeed, you should see the test name, the green bar with test results.

2.Creating A Test Suite

The first example showed how to create a single test case. Although you can define multiple test functions in one test php file, it is not enough. Next I would like to introduce how to make a test suite that can run multiple test php files one by one.
Firstly, I create a target test file named clock.php. It can return a timestamp. And I put it into the classes folder. Code is on below.
<-- clock.php -->
<?php 
class Clock{
    var $_offset;    
    function __construct(){
        $this->_offset=0;    
    }
    function now(){             // return a timestamp
        return time()+$this->_offset;
    }

    function advance($offset){  // change the timestamp;    
       $this->_offset+=$offset;
    }
}
Next, I would like to do some tests to the clock.php. Create the test case in the new file clock_test.php and leave it in the root directory.
<-- clock_test.php -->
<?php
    require_once('simpletest/autorun.php');
    require_once('classes/clock.php');

    class TestOfClock extends UnitTestCase {
        function TestOfClock() {
            parent::__construct('Clock test');
        }
        function testClockTellsTime() {
            $clock = new Clock();
            $this->assertEqual($clock->now(), time(), 'Now is the right time'); //test return time
        }
        function testClockAdvance() {
        }
    }
I have created the second test case now. Next I would like to make a test suite to run log_test.php and clock_test.php.
Create a new file named all_test.php. And put it in the root directory. Write code below into all_test.php
<-- all_test.php -->
<?php 
require_once('simpletest/autorun.php');

class AllTests extends TestSuite{
    function AllTests(){                          //you can also write as function __construct()
        $this->TestSuite('All tests here');   // and parent::__construct('All tests here');

        // if you have multiple test files, use addFile() function to add them.
        $this->addFile('log_test.php');
        $this->addFile('clock_test.php');
    }
}
Then, I can remove the "require_once('simpletest/autorun.php')" from log_test.php and clock_test.php. Also remove "$test = new TestOfLogging();" and "$test->run(new HtmlReporter());" from log_test.php.
Now, I can only run the all_test.php to run all the test files.

3.Show pass message

According the first two examples, we can see if the test succeed, we only get the numbers of test cases, passes, fails and exceptions. Next code is used to print out the details of passes information. I write it into the file named show_passes.php, and leave it in the root directory. 
<-- show_passes.php -->
<?php
require_once ('simpletest/reporter.php');

class ShowPasses extends HtmlReporter{
    function __construct(){
        parent::__construct();        
    }
    function paintPass($message){
        parent::paintPass($message);
        print "<span class=\"pass\">Pass</span>:";
        $breadcrumb = $this->getTestList();
        array_shift($breadcrumb);
        print implode("-&gt;", $breadcrumb);
        print "-&gt;$message<br />\n";
    }
}

Then go back to the all_test.php, and add "require_once('show_passes.php');" at the beginning, and add "$this->run(new ShowPasses());" at the bottom of function AllTests(). After that, if you run the test again, the passes information should be shown.

Want more? Part 2
... continue reading!

Monday 30 July 2012

PHP Simple Singleton

Here's a nice little trait(the new type of construct in PHP 5.4) to allow you to take a class and turn it into a singleton

Here we go: 
1) Include the trait 
2) Change the constructor to protected 
.. and that's it. Happy days

Example

namespace test;

class boosh
{ use \system\mixin\_Singleton;
 
 protected function __construct() 
 { }
}

$mighty = boosh::getInstance();


The Singleton Source

namespace system\mixin;

trait _Singleton
{
 private static $obj;
 
 /** 
  * @brief  Using a singleton pattern to return a reference of the base class 
  * @return a reference to a shared instance
  */
 final public static function getInstance()
 {
  $lastClass = get_called_class();
  
  if(false == isset(self::$obj))
  {
   self::$obj = new static();
  }
  return self::$obj;
 }
}
So what's the key? The secret is in static. Using "new static();we are getting a reference to the class that the developer is invoking this against. 
Not the class that the function is defined in. :D

Short and Sweet!
... continue reading!

Wednesday 11 July 2012

Virtual Machines using Vagrant and Chef

Vagrant
VirtualBox
Chef

Vagrant + VirtualBox + Chef

With the use of Vagrant and Chef we can fully automate our Virtual Server deployment. Using Vagrant we can setup our VM by using a "base box" and using Chef "recipes" and "cookbooks" we can set what gets installed on the VM as it starts up so your virtual environment is already setup for use.

Some links that will be helpful:
for Chef
Opscode Documentation
Opscode Wiki
Opscode-Cookbooks *git You will need Virtual Box before we start anything else so download and install it:
Download Vagrant and install according to your machine and download Chef and install as well.

Setting up Vagrant

After you install Vagrant it will add the `vagrant` command to your terminal/command prompt. Type `vagrant -h` to get a list of all the commands associated with it, also read the documentation on the website as it's very thorough and precise.
To set up your Debian box follow these commands:
mkdir vagrantDeb cd vagrantDeb vagrant box add localDebian http://dl.dropbox.com/u/937870/VMs/squeeze64.box vagrant init localDebian
Your VM is now ready to build, but first we must configure our vagrantfile. Edit the vagrant file in the directory you made using the editor of your choice and make these changes:
  • Uncomment the line stating `config.vm.network :hostonly, "192.168.33.10"`. The IP address is arbitrary, just make sure it doesn't clash with other VM's.
  • Add:
    config.vm.customize do |vm|
            vm.memory_size = 512
        end
    

    This will set the RAM size, you can still change this in the virtualbox settings later so it doesn't matter too much.
  • Change share folder to: config.vm.share_folder "htdoc", "/var/www", "/htdoc". You can add more folders if you want, the syntax is `config.vm.share_folder "name", "guest/dir", "host/dir"
Now you are ready to run your VM. Enter the command `vagrant up` and your VM will boot. You must ssh into it so if you are using windows you will need to download a ssh program such as PuTTY. Use the IP 127.0.0.1 and port 2222.

Configuring VM

Now that your VM is setup we need to update it. Run `sudo apt-get update` and `sudo apt-get upgrade` to get everything up to date. Remember we won't be downloading any applications or tools manually, chef will be doing that for us.
You may have noticed after your `vagrant up` command that vagrant complained the VirtualBox guest additions were not the same version as your VirtualBox program. Comments on this report varying problems from not working at all to nothing happening, if you receive any problems here are the commands to update:
NOTE: VBoxGuestAdditions_4.X.Y relates to the version of Virtual Box you have.
wget -c http://download.virtualbox.org/virtualbox/4.0.8/VBoxGuestAdditions_4.X.Y.iso -O VBoxGuestAdditions_4.X.Y.iso sudo apt-get install build-essential module-assistant sudo m-a prepare sudo mount VBoxGuestAdditions_4.X.Y.iso -o loop /mnt sudo sh /mnt/VBoxLinuxAdditions.run --nox11 sudo /etc/init.d/vboxadd setup rm *.iso
That should be it for the guest additions. Now we need to upgrade our chef application on the VM with the following command:
sudo gem install chef --no-ri --no-doc
It's important to note that the version on your host and guest machine should be matching, so if you ever upgrade on make sure to upgrade the other.
Ta-da! Our VM is on like Donkey Kong!

Cooking up some Recipes

Chef is a configuration management tool that is written in Ruby. They come in recipes and recipes are grouped into cookbooks. There are many chef recipes and cookbooks already available online and we can write our own if we want. We include these recipes in our vagrant file so when we load our VM it will read these recipes and install the according applications and tools. First we create a directory for our recipes within our directory which contains our vagrantfile and then we will download the ones we need. If you are using Windows download the Git Bash tool:
mkdir cookbooks
cd cookbooks
git clone git://github.com/opscode-cookbooks/apache2.git
git clone git://github.com/opscode-cookbooks/apt.git
git clone git://github.com/opscode-cookbooks/build-essential.git
git clone git://github.com/opscode-cookbooks/git.git
git clone git://github.com/opscode-cookbooks/vim.git
git clone git://github.com/opscode-cookbooks/php.git
git clone git://github.com/opscode-cookbooks/mysql.git
git clone git://github.com/homemade/chef-dotdeb.git
The opscode-cookbooks page has a list of common application recipes that were made by opscode themselves. The last one is to upgrade php to 5.3 as the default Debian repo only has 5.3 (at time of writing!).
Now open up your vagrantfile and lets add these recipes. At line 70 or so in your vagrantfile it should start mentioning chef and all these commands will be commented out. Uncomment the ones you need and add your recipes as such:
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "cookbooks"
chef.provisioning_path = "/tmp/vagrant-chef"
# chef.roles_path = "../my-recipes/roles"
# chef.data_bags_path = "../my-recipes/data_bags"
chef.add_recipe ("dotdeb")
chef.add_recipe ("dotdeb::php54")
chef.add_recipe ("apt")
chef.add_recipe ("apache2")
chef.add_recipe ("apache2::mod_php5")
chef.add_recipe ("apache2::mod_rewrite")
chef.add_recipe ("php")
chef.add_recipe ("build-essential")
chef.add_recipe ("git")
chef.add_recipe ("vim")

# # You may also specify custom JSON attributes:
# chef.json = { :mysql_password => "foo" }
end
Now we are ready to rebuild our VM. First lets go through some vagrant commands:
 vagrant up  start VM, whether new or halted
 vagrant halt  halts and stops VM, what you should be doing to shut it down
 vagrant reload  rebuilds the VM if changes have been made to the vagrantfile while it has been running
 vagrant destroy  deletes VM, but not the vagrant file. Don't do this unless absolutely necessary
Now just run  vagrant reload   and it will apply your changes made in the vagrantfile. Wait until the loading finishes and you VM is complete. If you wish to create multiple VM's for testing new configurations just make a new directory and use the command  vagrant init localDebian  . This will create a new vagrant file and a new vm, then just run  vagrant up   in this directory. Vagrant can do this as localDebian is saved in a .box format that vagrant uses. It builds your VM on top of this "base box" so you can build multiple VM's of the same box without effecting the other ones.
... continue reading!

Tuesday 17 April 2012

PHP Easy Enums

So what do we have on the table today... ENUM. 
Coming from a Java background I really like the ideas of Enumerated types and when moving to PHP had a hard time accepting define(a global constant) OR constant within a class that you have to statically reference :p

So here is my enum behaviour class that was designed to be inherited into standard class is to allow for more intuitive enum coding

! This is a different way of defining enum as compared to php's SplEnum !

Let's look at how you would use it.. and then will take a look inside.

Example that represents HTTP status codes 

First lets create are enum collection.


! If the code looks a bit strange with all the slashes, it's because I'm use PHP autoloader.. which I love :D !

namespace enum\message;

final class Http extends \_Enumerat
{
 const OK = 200;
 const NO_CONTENT = 204;
 const BAD_REQUEST = 400;
 const UNAUTHORIZED = 401;
 const FORBIDDEN = 403;
 const NOT_FOUND = 404;
 const NOT_ACCEPTABLE = 406;
 const INTERNAL_ERROR = 500;
 const TEMPORARILY_OVERLOADED = 502;
}

and here's the filler

use \enum\message\Http;

//get the enum value directly
echo Http::OK; //int(200)

//get the value wrapped in an enum object
$serverProblem = Http::INTERNAL_ERROR();

//lets print the object
echo $serverProblem; //"500"

//let's check variables to see if there valid against the enums
$outSideRequest = '-1';

$status = 'invalid';

if(Http::check($outSideRequest))
{
 $status = 'valid';
}

echo 'the Request code is '.$status; //the Request code is invalid


//here we can enforce that functions must only accept a specific enum type
function setStatusCode(Http $_code){

}


If you want a bit more and have a good understanding of magic methods keep reading.



/**
* @note To help identify classes that cannot be instantiated we prefix them with a single underscore at the beginning
@note In order to help distinguish between variables passed into the function as against variables created inside it. We prefix the start of the variable name with an underscore.
*/
 abstract class _Enumerat
 {
  private $value;
  
There the interesting stuff of how you create your enum object.
As in the example above, all you need to do is call the value within the enum and add the function braces.

  /**
  * To help in force a standardisation on enum(as distinct from other objects) developer must invoke the enum constant value
  @see _Enumerat::__callStatic(a,b)
  */
  private function __construct($_value)
  {   
   $this->value = $_value;
  } 
  
  /**
  * This is invoked when the you want to create an enum. it will acts like a constructor
  */
  public static function __callStatic($_name, $_asString = FALSE)
  {
   $class = get_called_class();
   $oClass = new \ReflectionClass($class);
   $value = $oClass->getConstant($_name);
   
   if(NULL  === $value 
   OR FALSE === $value)//I'm raising an error as I consider this to be a compile time problem
   { trigger_error('invalid enum value',E_USER_ERROR); }
   else
   { return new $class($value); }
  }
  
The functions to accessing the value with in
  /**
   * This will convert this object instance into a string representing the enum if you try and use this object like a string
   * @return string
   */
  public function __toString()
  {
   return ''.$this();
  }

  
 /**
  * This allows you to quickly and easily access the value of the enum while keeping the enum object intact
  * @return mixed 
  */
  public function __invoke()
  {
   return $this->value;
  }
 }
  
Quick way to pull a list of all of the value the enum supports
  /**
   * This will return an array of all the predefined constants for this type of enum. The enum name will be the key and the enum's value... well, in value
   * @return array
   */
  public static function listValues()
  {
   $oClass = new \ReflectionClass(get_called_class());
   return $oClass->getConstants();
  }
Allows the resolving of the position of a value relative to wear it was declared.
 /**
 * Gets the position of this enum in the list as ordered in the source code.
 * @return int
 */
 public function index()
 {
  return $self::indexOf($this->value);
 }
 
 /**
 * Gets the position of the request enum as ordered in the source code.
 * @param int $_num the index you want to check for
 * @return int
 */
 public static function indexOf($_enum)
 {
  //if its an object of enum, then pull the value out of it
  if($_enum instanceof static)
  { $enum = $_enum(); }
  else
  { $enum = $_enum;  }
  
  $list = self::listValues();
  
  $count = 0;
  foreach($list as $val)
  {
   if($val === $enum)
   {
    return $count;
   }
   $count++;
  }
  return -1;
 }
Check if a value is valid
  /**
  * Will check if the input is compatible/valid with this instance of enum
  *
  * @param mixed $_enum you can pass in the enum object or the value of the enum
  * @return boolean
   */
  
  final public static function check($_enum){
  
   if($_enum instanceof static)
   { 
    return TRUE; 
   }
   else
   {
    return in_array($_enum, self::listValues() , TRUE);
   }
   return FALSE;
  }
  
  /**
  * Will let you know if an enum value exists in the list at the requested index
  *
  * @param int $_num the index you want to check for
  * @throws InvalidArgumentException if the input is not an int
  * @return boolean true if exists false if not
  */
  public static function checkIndex($_num)
  {
   if( ! is_int($_num))
   { 
    throw new \InvalidArgumentException('input is not an integer'); 
   }
   
   $count = count(self::listValues());
   if(0 <= $_num AND $_num < $count)
   { 
    return TRUE; 
   }
   return FALSE;
  }
  
And that it, easy peasy.
... continue reading!