Abstract classes, abstract methods, interfaces, what?

If you've been developing with PHP for any length of time you've probably heard of concrete classes, abstract classes, abstract methods, and interfaces. Many of the popular frameworkd encourage you to "program to an interface", but what does that mean? And when should you program to an abstract class, or define an abstract method? Let's figure this out.

What's what?

I could give you definitions, but most people have a hard time wrapping their heads around these ideas without examples. I'd like for us to incrementally learn with a "real" life example. You won't find any car, animal, or whatever weird metaphors you have to figure out how to translate to real use cases here.

Starting small

First things first, let's define a small, achievable goal. Our application needs to be able to email its users. Let's accomadate that. We would probably write a class like this.

class BasicEmail 
{
    private $email;

    private $body;

    public function setEmail($email)
    {
        $this->email = $email;
    }

    public function setBody($body)
    {
        $this->body = $body;
    }

    protected function isValid()
    {
        return is_email($this->email) && strlen($this->body) > 0;
    }

    public function attempt()
    {
        if($this->isValid())
        {
            $this->send();
        }
    }

    public function send()
    {
        //use $email and $body to send email
    }
}

//elsewhere in your application

$email = new BasicEmail;
$email->setEmail('johnDoe@gmail.com');
$email->setBody('Thanks for joining CatLoverApp, the social media platform to show off your cat!');
$email->attempt();


Sweet. That looks good. We're using object oriented programming! Let's continue on.

Your users are really enjoying getting emails when their friends post pictures of their cats. Things are good, except many users are requesting SMS messages to be sent in addition to emails. A service like Twilio is perfect for this. Let's use it.

class SMS 
{
    private $phone;

    private $text;

    public function setPhone($phone)
    {
        $this->phone = $phone;
    }

    public function setText($text)
    {
        $this->text = $text;
    }

    protected function isValid()
    {
        return is_phone($this->phone) && strlen($this->text) > 0;
    }

    public function attempt()
    {
        if($this->isValid())
        {
            $this->send();
        }
    }

    public function send()
    {
        //use Twilio to send SMS
    }
}

//elsewhere in your application

$sms = new SMS;
$sms->setPhone('123-456-7890');
$sms->setText('Bob, just posted a pic of his cat!');
$sms->attempt();


Abstract classes and methods

Cool, now we can send emails and SMS messages to our users...but our classes look very similar. That doesn't feel quite right. They both have a destination, text body, isValid(), attempt(), and send() methods. This is the perfect scenario for an abstract class. That could look like this.

abstract class Message 
{
    private $destination;

    private $content;

    public function setDestination($destination)
    {
        $this->destination = $destination;
    }

    public function setContent($content)
    {
        $this->content = $content;
    }

    public function attempt()
    {
        if($this->isValid()) {
            $this->send();
        }
    }

    abstract protected function isValid();

    abstract public function send();
}

class BasicEmail extends Message 
{
    protected function isValid()
    {
        return is_email($this->destination) && strlen($this->content) > 0;
    }

    public function send()
    {
        //use $this->destination and $this->content to send email
    }
}

class SMS extends Message 
{   
    protected function isValid()
    {
        return is_phone($this->destination) && strlen($this->content) > 0;
    }

    public function send()
    {
        //use $this->destination and $this->content to send SMS
    }
}

//

$message = new Message; //Invalid, won't work because it's abstract!

$message1 = new BasicEmail;
$message1->setDestination('johnDoe@gmail.com');
$message1->setContent('Sorry, Susan just de-friended you!');
$message1->attempt();

$message2 = new SMS;
$message2->setDestination('123-456-7890');
$message2->setContent('Sorry, Susan just de-friended you!');
$message2->attempt();


We can use abstract classes when we have similar objects that share some functionality but do things a bit differently. In our Message class we've defined a couple abstract methods. We are forcing a requirement on all classes that extend Message. We require them to implement send() and isValid() methods. The Message class doesn't care how exactly it sends the message or how it gets validated, just that it has the ability to do so.

It's also important to note that abstract classes and interfaces(which we'll get to later) can define methods with any type of visibility, public, protected, or private. In these classes, the isValid() should probably be public. I'm merely illustrating a point.

Warning! You can not instantiate an abstract class. They're too vague. They're meant to be extended.
Note! If a class has an abstract method defined, it must be an abstract class. However, it is still valid to define an abstract class that has zero abstract methods. It's uncommon, but valid.

Message queue

We can't predict the future and can't know what our users will want next. Maybe an actual phone call, who knows? We do know that they like notification options and want lots of them. Let's put together some kind of message queue. Our first pass might look like this.

$messages = array();

$messages[] = $message1;
$messages[] = $message2;

/** other application code **/

foreach ($messages as $message) {
    $message->attempt();    
}


Hmm...this works, but it could be a lot better. What happens if our coworker, Norm, sees $messages and adds $messages[] = "You've been awarded a badge!"? Things break. He might not have seen the portion of code that sends all of the messages and expects them to have an attempt() method. For our and our coworkers sake, let's refactor. Let's create an actual MessageQueue.

class MessageQueue 
{
    private $messages = array();

    public function add(Message $message)
    {
        $this->messages[] = $message;
    }

    public function sendAll()
    {
        foreach ($this->messages as $message) {
            $message->attempt();
        }
    }
}


This looks a lot better. We're even type-hinting the add() method! Our coworkers will know that the add() method requires only Message objects(which BasicEmail and SMS are).

Extending functionality

I'm liking this MessageQueue idea. It doesn't care what kind of Message it's sending, just that it needs to send them. This is great.

Now, let's say we want to really encourage our users to use our service. Let's reward them 5¢ for every cat photo they post.

class PhotoReward 
{
    private $amount;

    private $recipient;

    public function setAmount($amount)
    {
        $this->amount = $amount;
    }

    public function setRecipient($recipient)
    {
        $this->recipient = $recipient;
    }

    public function reward()
    {
        //use paypal to send reward to recipient
    }
}


This doesn't qualify as a Message but it would be great if we could use it in a queue. Time for an interface! An interface imposes requirements on our classes in the form of methods, just like abstract methods, only there's zero implementation code.

One advantage to using interfaces is that you can bolt them on to your existing classes. A class can only extend a single other class. It can only have one parent. When it comes to interfaces, however, classes can implement an unlimited number of interfaces.

Fun Fact! Interfaces can be extended by other interfaces. I don't think I've seen it done out in the wild, but it can be. Usually it's clearer to just have your classes implement multiple interfaces.

Let's define an Event interface.

interface Event 
{
    public function fire();
}


As you can see, the interface does nothing but define a fire() method. Any class that uses/implements this interface will be required to define a fire() method.

Time to refactor our queue class. Let's genericize it a bit by using the Event interface.

class EventQueue 
{
    private $events = array();

    public function add(Event $event)
    {
        $this->events[] = $event;
    }

    public function fireAll()
    {
        foreach ($this->events as $event) {
            $event->fire();
        }
    }
}


Now, let's refactor our other Message and PhotoReward classes to use the interface.

abstract class Message implements Event 
{
    private $destination;

    private $content;

    public function setDestination($destination)
    {
        $this->destination = $destination;
    }

    public function setContent($content)
    {
        $this->content = $content;
    }

    public function attempt()
    {
        if($this->isValid()) {
            $this->send();
        }
    }

    public function fire()
    {
        $this->attempt();
    }

    abstract protected function isValid();

    abstract public function send();
}

class PhotoReward implements Event 
{
    private $amount;

    private $recipient;

    public function setAmount($amount)
    {
        $this->amount = $amount;
    }

    public function setRecipient($recipient)
    {
        $this->recipient = $recipient;
    }

    public function fire()
    {
        $this->reward();
    }

    public function reward()
    {
        //use paypal to send reward to user
    }
}


Lookin good. There are few things to note.

You'll notice that we didn't need to touch the BasicEmail and SMS classes. We set the interface on their parent abstract Message class. The new fire() method just wraps our attempt() method. This may seem redundant, but we are now able to call these classes Events.

We could have kept the interface on Message and left off the fire() method because Message is abstract. As long as the implementations, BasicEmail and SMS, implemented their own fire() methods, they would adhere to the interface. All abstract requirements are eventually funnelled down to their concrete implementations.

We've implemented an interface on an abstract and a concrete class. Both are valid.

Let's see what we can do now.

$queue = new EventQueue;

$event1 = new BasicEmail;
$event1->setDestination('johnDoe@gmail.com');
$event1->setContent('Sorry, Susan just de-friended you!');

$queue->add($event1);

$event2 = new SMS;
$event2->setDestination('123-456-7890');
$event2->setContent('Sorry, Susan just de-friended you!');

$queue->add($event2);

$event3 = new PhotoReward;
$event3->setRecipient($bob);
$event3->setAmount(5);

$queue->add($event3);

$queue->fireAll();


Because each object adheres to the Event interface, we can add them to the queue and the queue can count on all of its objects to have a fire() method. Sweet.

Inception

Prepare yourselves. We're about to get crazy.

Let's add some dimension to our EventQueue. You'll notice we have a fireAll() method. This class would also make sense to be an Event. It's time to really take advantage of some object oriented programming.

Our new and improved EventQueue could look like this.

class EventQueue implements Event 
{
    private $events = array();

    public function add(Event $event)
    {
        $this->events[] = $event;
    }

    public function fire()
    {
        foreach ($this->events as $event) {
            $event->fire();
        }
    }
}


What does this buy us? Organization and options.

$messageQueue = new EventQueue;
$rewardQueue  = new EventQueue;

$email = new BasicEmail;
$email->setDestination('johnDoe@gmail.com');
$email->setContent('Congrats, you\'re the cat lover of the month!');

$messageQueue->add($email);

$sms = new SMS;
$sms->setDestination('123-456-7890');
$sms->setContent('Congrats, you\'re the cat lover of the month!');

$messageQueue->add($sms);

$photoReward = new PhotoReward;
$photoReward->setRecipient($bob);
$photoReward->setAmount(5);

$rewardQueue->add($photoReward);

$badgeReward = new BadgeReward;
$badgeReward->setRecipient($spencer);

$rewardQueue->add($badgeReward);

$masterQueue = new EventQueue;
$masterQueue->add($messageQueue);
$masterQueue->add($rewardQueue);

//fire events in both queues
$masterQueue->fire();

//or only fire events in $messageQueue
$messageQueue->fire();

//or only fire events in $rewardQueue
$rewardQueue->fire();


We can now treat and handle each queue separately or all at once. It's now possible to put queues inside of queues inside of queues. Dominic Cobb would be proud.

A side effect of using abstract classes and interfaces is having very modulized and extendable code. To create a new Message we just need to extend the Message class and implement send() and isValid() methods.

Need another example?

Let's pretend we have some documents we need to save to a database. We could have the following abstract class.

abstract class Document 
{
    protected $datasource;

    public function __construct(DataSource $datasource)
    {
        $this->datasource = $datasource
    }

    public function save()
    {
        if($this->isNew())
        {
            return $this->datasource->insert($this);
        }

        return $this->datasource->update($this);        
    }

    public function delete()
    {
        return $this->datasource->delete($this);
    }

    public function set(array $attr)
    {
        //set attributes on the document
    }

    public function isNew()
    {
        //return true or false
    }

    public function getTable()
    {
        return static::TABLE;
    }
}

class Person extends Document 
{    
    const TABLE = "people";
}

class Company extends Document 
{    
    const TABLE = "companies";
}
Gripe! One feature I find lacking from php is the concept of final variables. Let me pick on Laravel a bit to illustrate this point.

In the previous code snippet, we refer to a DataSource. We should definitely define a DataSource interface and code implementations to that.

interface DataSource 
{
    public function insert(Document $document);

    public function update(Document $document);

    public function delete(Document $document);

    public function read($id, Document $document);
}

class MySQLDataSource implements DataSource 
{    
    public function insert(Document $document)
    {
        //use mysql specific code to insert a document
    }

    public function update(Document $document)
    {
        //use mysql specific code to update a document
    }

    public function delete(Document $document)
    {
        //use mysql specific code to delete a document
    }

    public function read($id, Document $document)
    {
        //use mysql specific code to read a document
    }
}

class FileSystemDataSource implements DataSource 
{
    //implement DataSource for file system
}

class RedisDataSource implements DataSource 
{
    //implement DataSource for Redis
}

class MongoDBDataSource implements DataSource 
{
    //implement DataSource for MongoDB
}

By programming to an interface, we can extremely easily swap out components. Consider the following example.

$john = new Person(new MySQLDataSource);
$john->set(["name" => "John Doe"]);
$john->save();

$bob = new Person(new RedisDataSource);
$bob->set(["name" => "Bob Smith"]);
$bob->save();

Because we've defined an interface and created different implementations, we've decoupled our Documents. Swapping things out is a breeze and we've future proofed our application a bit. If a new data source becomes available, we can implement a DataSource for the new data source and swap that in without touching our Document class. Our MySQLDataSource could use the getTable() method to determine where to save/delete the document while our RedisDataSource could use the document's class name. The document isn't concerned with how the DataSource operates, just that it does.

Make sense?

These are difficult concepts to grasp. I hope I've illustrated their usefullness clearly and in a way you can apply to your own codebase. Abstraction is a powerful thing. Learn how to harness its flexibility.

Good luck!

Tags: PHP, Intermediate

Zero to Jenkins - PHP Continuous Integration

Jenkins is an incredibly powerful continuous integration server. It allows us to automate all sorts of things through "Jobs". When using Jenkins with a php project we can automate cloning our project, using Composer to grab vendor packages, generating API documentation, running PHPUnit tests and code coverage reports, and all sorts of other tasks. This is all to make sure your project stays healthy. This post will walk you through how to set up Jenkins to use with a Laravel project.

More of a visual learner? Go straight to the video

Let's get started

The first thing we need to do is obtain a suitable server/virtual machine to install Jenkins. I went to PuPHPet and set up a VM using its default selection as a base but with the following modifications:

  • Ubuntu Precise 12.04 x64
  • Nginx
  • The php5-xsl php module

Jenkins does not need any of the above to operate(besides an OS). These are just my preferences. However, this guide does assume you are running Ubuntu Precise 12.04 x64. Our Laravel project and the tools we'll be using require Composer and the php5-xsl php module.

Note! Later in this guide I will set up a hook in BitBucket, where I host my code. When I push up changes BitBucket will automatically fire off a request to my Jenkins server to start a new build. For this to work your VM needs to be publically accessible. I use DigitalOcean to host my Jenkins server. Need help with that?

Install Jenkins and plugins

Once you have a VM booted, SSH into it and let's first run sudo apt-get update to make our box aware of the new/latest packages it can install.

nstall Jenkins, simply issue the following, apt-get install jenkins. It will prompt you to continue, press y and hit Enter. This will install Jenkins and get it running on port 8080. Visit http://your-ip-address:8080 and you should see Jenkins.

Next, we need to use a Jenkins command line tool to install some plugins.

#move the command line tool to our root directory
wget http://localhost:8080/jnlpJars/jenkins-cli.jar

#install plugins to use with our php project
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin checkstyle cloverphp dry htmlpublisher jdepend plot pmd violations xunit

#restart Jenkins for the plugins to take effect
java -jar jenkins-cli.jar -s http://localhost:8080 safe-restart
Tip! You can restart Jenkins by visiting the following url in your browser: http://your-ip-address:8080/restart
Argh! If you have trouble installing the plugins go into Jenkins and go to Manage Jenkins -> Manage Plugins -> Advanced -> Check Now. This will update Jenkin's list of available plugins. After doing that, go back to your terminal and try to install the plugins again.

Install the php job template

Sebastian Bergmann, the creator of PHPUnit, has put together a Jenkins job template for php projects. We can use this as a starting point to create a job. Install it by doing the following.

#get the php job template
curl https://raw.github.com/sebastianbergmann/php-jenkins-template/master/config.xml | java -jar jenkins-cli.jar -s http://localhost:8080 create-job php-template

#restart Jenkins for the template to be recognized
java -jar jenkins-cli.jar -s http://localhost:8080 safe-restart


Once we have the template we need to change its file permissions. Go into the jobs directory with cd /var/libs/jenkins/jobs and then change the permissions with chown -R jenkins:jenkins php-template.

Update Jenkins

We need to update Jenkins now. If you click the Manage Jenkins link in the left sidebar you will most likely see some yellow text, telling you a newer version is available. Update to the latest version by doing the following.

#stop Jenkins
/etc/init.d/jenkins stop

#download the latest war file to the /usr/share/jenkins/ directory
wget -P /usr/share/jenkins/ http://mirrors.jenkins-ci.org/war/latest/jenkins.war

#restart Jenkins
java -jar jenkins-cli.jar -s http://localhost:8080 safe-restart
Note! Once restarted, Jenkins may tell you that it discovered a security vulnerability. Click the Re-key in background now and Dismiss this message buttons.

Update existing plugins and install the Git Plugin

Since we udated Jenkins, we need to update some plugins. Go to Manage Jenkins -> Manage Plugins**. Check all of the boxes and select the Download now and install after restart button.

Configuring Jenkins Security


For our builds, we're going to use Git to clone our project to always start with a clean slate. For this to occur we need to install the Git Plugin. Grab the Git Plugin by clicking on the Available tab and checking the box next to Git Plugin. Click on the Download now and install after restart button. Restart Jenkins again for those plugins to be installed.

Secure Jenkins

As of now Jenkins is completeley insecure. Anyone can visit it in their browser and start messing around. We should fix this.

Go to Manage Jenkins -> Configure Global Security. Check the Enable security box. Select the Jenkin's own user database with the Allow users to sign up box checked in the Access Control -> Security Realm section. This will allow you and others to create user accounts.

Next, in the Authorization section, select Matrix-based security. In the User/group to add: field enter the username you want to use to access Jenkins for yourself. Click the Add button and select all of the boxes next to the newly added username. Leave the Anonymous boxes unchecked. Click Save.


Configuring Jenkins Security


You should be immediately taken to a login screen now that security is enabled. Click the Create an account link. Fill out the sign up form using the same username you enabled all access for. Click Sign up and you should now be logged in.

Crap! I locked myself out! Whoa...take a breath. We can fix this. Stop Jenkins with /etc/init.d/jenkins stop. Use Vim to edit the Jenkins config file, sudo vim /var/lib/jenkins/config.xml. Locate the <useSecurity>true</useSecurity> line and changed it to <useSecurity>false</useSecurity>. Save it and restart Jenkins, /etc/init.d/jenkins start. Now Jenkins will be started in an insecure mode and you can go back and configure the global security correctly.

Prepare a php project

I've created a build-ready Laravel project on BitBucket. Clone or fork that into your own git repository to use.

Create an SSH key pair

Next, we need to set up an SSH key pair for Jenkins to communicate with our repo. Change to the Jenkins user, sudo su jenkins, and navigate into the directory where we're going to store our key pair, cd /var/lib/jenkins/.ssh.

Create a key pair with the following command, ssh-keygen -t rsa -C "your.email@website.com". Press Enter to save the pair as id_rsa. Press Enter again when prompted to enter a passphrase. The passphrase needs to be blank. Confirm the blank passphrase again by pressing Enter. This will create two files, id_rsa and id_rsa.pub, the private and public key, respectively.

Now that we've created a key pair, we need to add the public key to the repository. View your public key with cat id_rsa.pub. Copy the key to your clipboard.

d your public key to BitBucket, click on the user icon at the top right of the page and select Manage account -> SSH keys. Click the Add key button, paste your key into the Key field, and Label it however you like.


BitBucket SSH


Back in the command line, we need to establish that connection. Enter ssh -T git@bitbucket.org, type yes when prompted and push Enter. It should now tell you that git can now be used to connect to BitBucket.

Create a new Jenkins job

We can now create a new job. Go to Manage Jenkins -> New Job. Enter a title for this new job in the Job name field. Don't use any spaces in your Job name though. We're going to use this in a url later. Select the Copy existing Job option and enter php-template in the Copy from field. Click OK.

s make sure our new job has the correct permissions. Change into the jobs directory with cd /var/libs/jenkins/jobs and then change the permissions with chown -R jenkins:jenkins your-project-name.

Configure the job

Now we need to tell Jenkins what this job is suppose to do.

In the Source Code Management section(provided by the Git Plugin), choose Git. Copy your git url into the Repository URL and type develop in the Branches to build field. At the beginning of each build, Jenkins will now clone the develop git branch and perform the build.


Jenkins git configuration


In the next section, Build Triggers, select the Trigger builds remotely box and enter an Authentication Token. This will allow us to queue a build by hitting a url. The Authentication Token should remain secret. Because it will be used in a url, I recommend using only letters, numbers, and/or dashes.

It's time to specify the build steps now.

In the Build section, Delete the default Invoke Ant step.

Add a build step by selecting Add build step -> Execute shell. After the cloning of the project we want to use Composer to get our vendor packages. Type composer update in the Command text area.

After installing our dependencies with Composer, we want to use Phing to handle the rest of the build. Add another build step and in this build step's Command field enter vendor/bin/phing -logger phing.listener.NoBannerLogger. Phing uses the .xml files at the root of our project to determine what to do. Some of the tasks include: creating a build directory to store reports, running PHPUnit, generating API documentation, and more. Explore the build.xml file a bit to learn more about what all phing is doing.


Jenkins build steps


Scroll down to the Publish HTML reports section. We need to correct a path. Our build is generating API documentation and Jenkins is providing a link to those docs on the Jenkins project's homepage. Because we're using the php-template and I've modified the project structure a bit, we need to change the HTML directory to archive to build/api/html. This will set the correct path to access our generated documentation.

Finish by clicking Save

Configure Git

Because we're using git to clone our project, it needs to know who it's acting on behalf of. To inform git, first, run git config --global user.email "your.email@website.com" and git config --global user.name "jenkins".

Is it time to build yet?

Yes. Yes it is. In the left sidebar of Jenkins click the Build Now link. It will eventually fail because it's trying to download too many packages from GitHub while being unauthenticated. We can fix this by changing into the job directory, cd /var/lib/jenkins/jobs/your-project-name and manually running Composer with composer update. After a few successful package downloads, you will be prompted to enter your GitHub credentials. When you do, the packages will continue to be downloaded.

Tip! You can watch the output of the build in real time by clicking on the current build link in the Build History section and selecting Console Output.

Click Build Now again and the build should finally successfully complete!

Create a Jenkins hook

The beautiful thing about Jenkins is that we can automate builds. We can trigger a build to be queued up when we push code to our repository.

To do this we need to get our Jenkins user API Token. Go to Manage Jenkins -> Manage Users. Click on your user account and click the Configure link in the left sidebar. Click Show API Token... and copy the token to your clipboard.

Back in BitBucket, click the cog icon in the upper right corner. Select Hooks. Choose Jenkins in the dropdown and press Add hook.

Specify your endpoint with the following pattern: http://jenkins-username:jenkins-api-token@your-ip-address:8080/

It should look something like this: http://dadams:234asdg7f1f1jea4f9ad37ds5dbc724eecda9a510@192.243.157.38:8080/

We can leave the Module name blank. Specify the your Jenkins project in the Project name field. Put the same build token specified in the Build Triggers section in Jenkins in the Token field. Click Save. Now, every time we push code to the repo a build will get triggered.


Jenkins build steps


Tip! This hook will be triggered for every push. This probably isn't what you'd want in a real project. You probably only want to trigger builds on certain branches, like the develop branch for instance. To accomplish this, use a POST hook in BitBucket instead of a Jenkins hook. You'll need to write an endpoint script that will process the POST and determine which branch was committed to and then based on that, trigger a build by requesting JENKINS_URL/job/PROJECT_NAME/build?token=TOKEN_NAME. More information can be found here.

Enjoy the awesome

If you go back to the project's homepage, you can now view all of the results in reports, charts, graphs, API docs, and an interactive code browser. Sweet! We've just automated a whole lot of extremely useful tasks.




Zero to Jenkins | Full Length Video





The benefit of Jenkins


Tags: PHP, Jenkins, CI, Intermediate

Getting Laravel Set Up

I've recorded a series to illustrate how to get a Laravel project set up on your development machine. I cover creating a virtual machine, installing Laravel, using Git for version control, and setting up our project in PHPStorm.

Part 1.

Topics covered

  • Using PuPHPet to get a VM created and provisioned




Part 2.

Topics covered

  • Adding a line to your hosts file
  • Using Vim
  • Creating a Laravel project using Composer
  • Changing folder/file permissions for Laravel




Part 3.

Topics covered

  • Adding the project in PHPStorm
  • Using Composer to install a helper package for PHPStorm
  • Setting up PHPUnit in PHPStorm




Part 4.

Topics covered

  • Configuring the database connection
  • Creating and running a Laravel migration
  • Using Git and BitBucket to track our project
  • Configuring Sequel Pro to connect to our database
  • Setting up Git in PHPStorm

Tags: Vagrant, Puppet, PuPHPet, Laravel, Beginner