Beginning cloud development with cloudControl - Part 2 - MySQL

In part one of the series we got a birds eye view of a great cloud development solution for PHP - cloudControl. We looked at the concept of what it is, what you can do with it and ran through a basic deployment with a rather basic application. If you missed the first part, I strongly encourage you to read it before continuing on with part two. When you’re done, come on back and work through it here.

In this, part two of the series, things start to get more serious. In this part, we’re going to start to flesh out the application started in part one, adding in MySQL support - showing just how simple cloudControl makes this for us.


In part one of the series we got a birds eye view of a great cloud development solution for PHP - cloudControl. We looked at the concept of what it is, what you can do with it and ran through a basic deployment with a rather basic application. If you missed the first part, I strongly encourage you to read it before continuing on with part two. When you’re done, come on back and work through it here.

In this, part two of the series, things start to get more serious. In this part, we’re going to start to flesh out the application started in part one, adding in MySQL support - showing just how simple cloudControl makes this for us.

The application will be a simple CRUD application that will allow us to mange a set of users. We’ll be able to do the following operations by the time we’re done:

  • Add
  • Edit
  • Delete
  • List (or view)

Now initially I thought I’d write a pretty plain vanilla application. But as the work progressed, it appeared that that approach wouldn’t work well across multiple environments - which is one of the key benefits of cloudControl. So given that yet in the spirit of keeping things as simple as possible and professional, I decided to use a set of third party libraries to make it easier. These include:

  • [Zend Framework (1.11)][1]
  • [HTML 5 Boilerplate][2]

There’s more code in there than I’d really planned to put in it, but it really helps to show you a good, if basic, application that will work across multiple environments. If you want, grab a copy of the code, available at https://github.com/maltblue/cloudcontrol-project and follow along in your local development environment.

Branches and Deployments

The application will have 4 branches: production, staging, testing and development. Production is a branch of the default, or master. For the 3 main branches there will be an accompanying cloudControl deployment.

Let’s create the application

Change to the project directory you created in part one and then run the following command:

[bash] # create (and checkout) a development branch from the master branch git checkout -b development [/bash]

Following this, you’ll need to do the following:

  1. Grab yourself a copy of the [HTML 5 Boilerplate][2] and [Zend Framework][1] libraries
  2. Extract the HTML 5 Boilerplate in to your project directory
  3. Create a directory, library, under the root of your project directory and extract the Zend Framework library in to it
  4. Under the root of the project create a new directory, config, and in there, create a file application.ini
  5. Also under the root of the project create a new directory, data/db, and in there, create a file called: dbload.sql
  6. In the css directory (created by the HTML 5 Boilerplate), create a new file main.css
  7. Create a file config.php in the root directory
  8. Create a new directory called includes and in there create two new files: template.footer.php and template.header.php

Adding MySQL Support

As we’re going to be using MySQL, then we’re going to be needing the cloudControl [MySQL add-on][3]. The MySQL add-on comes in a variety of flavours, from free, which we’ll be  using as well as in the following space options:

  • 512 MB
  • 20 GB
  • 250 GB
  • 1 TB
As you can see, there's ample available options to suit your needs. You can read more about them on the add on page.

To add support for MySQL run the following command to add it to our development deployment:

[bash] cctrlapp maltbluedev/development addon.add mysql.free [/bash]

To work with it, we’re going to need the configuration options for it. To get these, run the following command:

[bash] cctrlapp maltbluedev/default addon mysql.free [/bash]

This will list all of the essential information as shown in the screenshot below:

cloudControl MySQL add on configuration optionsNow, in the application.ini file, add in the code below and adjust the details, where necessary, to match the values when you ran the above command.

[bash] [production] ; Database database.adapter = PDO_MYSQL database.params.host = 127.0.0.1 database.params.username = depe2yjxwjz database.params.password = 2gVSZRDv5HReX3E database.params.dbname = depe2yjxwjz [/bash]

The Database Data

Ok, we’re going to need some real data to get us started. In data/db/dbload.sql, add the following which will load a default table, complete with 10 records for us:

[sql] — database table DROP TABLE IF EXISTS staff;

— the staff table CREATE TABLE staff ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, firstName VARCHAR(100) NOT NULL, lastName VARCHAR(100), emailAddress VARCHAR(150) NOT NULL, occupation VARCHAR(50), CONSTRAINT UNIQUE INDEX uniq_email(emailAddress) ) ENGINE = InnoDB, COMMENT = “Store list of staff members”;

INSERT INTO staff (firstName, lastName, emailAddress, occupation) VALUES (“Muhammad”,“Ali”,“mali@gmail.com”,“Boxer”), (“Lou”,“Ambers”,“lambers@gmail.com”,“Boxer”), (“Vito”,“Antuofermo”,“vantuofermo@gmail.com”,“Boxer”), (“Jorge”,“Arce”,“j.arce@gmail.com”,“Boxer”), (“Alexis”,“Arguello”,“a.arguello@gmail.com”,“Boxer”), (“Henry”,“Armstrong”,“h.armstrong@gmail.com”,“Boxer”), (“Abe”,“Attell”,“a.attell@gmail.com”,“Boxer”), (“Monte”,“Attell”,“m.attell@gmail.com”,“Boxer”), (“Yuri”,“Arbachakov”,“y.arbachakov@gmail.com”,“Boxer”), (“Satoshi”,“Aragaki”,"s.aragaki@gmail.com",“Boxer”); [/sql]

Loading the Data in to the cloudControl Database

This is where it gets a bit interesting. In the interests of security, cloudControl provide a secure connection to your database available via an stunnel server. So to access it you’re going to need a copy of the [stunnel client][4] and create an encrypted connection from your development environment to the cloudControl servers. Grab and install a copy of stunnel from the stunnel website.

If you're not familiar with stunnel, what it does is to create a secure connection between a local and a remote port. Through doing this, you can make a connection with an application to a local port which is then transparently redirected to a remote ip and port securely.

In the case of our application, we’re going to create a secure tunnel to the cloudControl mysql servers on the standard port or 3307 via the local port 4711. To do this, we run the command below:

[bash] stunnel -c -d 4711 -r mysql.cloudcontrolled.com:3307 -P /tmp/stunnel4.pid [/bash]

Following this, we can use the MySQL clients as normal, but specifying port 4711 instead of the default 3307. Given that we’ve setup the tunnel, let’s import the data:

[bash] mysql -u depe2yjxwjz -p -h 127.0.0.1 -P 4711 depe2yjxwjz < data/db/dbload.sql [/bash]

Following this, you’ll be prompted for the password as normal, so enter it and the database table will now be created and loaded up with our ten records.

The Templates

Now we need to lay the ground work for the user interface. In includes/template.footer.php, add the following code:

[php] <!- JavaScript at the bottom for fast page loading -> <!- Grab Google CDN’s jQuery, with a protocol relative URL; fall back to local if offline -> <!- scripts concatenated and minified via ant build script->

<!- end scripts-> <!- Prompt IE 6 users to install Chrome Frame. Remove this if you want to support IE 6. chromium.org/developers/how-tos/chrome-frame-getting-started -> <!-[if lt IE 7 ]>

<![endif]->

[/php]

In includes/template.header.php, add the following code:

[php] <!doctype html> <!- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -> <!-[if lt IE 7]> <![endif]-> <!-[if IE 7]> <![endif]-> <!-[if IE 8]> <![endif]-> <!- Consider adding an manifest.appcache: h5bp.com/d/Offline -> <!-[if gt IE 8]><!-> <!-<![endif]->

IE=edge,chrome=1″> Malt Blue / cloudControl :: Staff Manager

<!- Mobile viewport optimized: j.mp/bplateviewport ->

CSS concatenated and minified via ant build script->

CSS->

<!- More ideas for your here: h5bp.com/d/head-Tips ->

<!- All JavaScript at the bottom, except for Modernizr / Respond. Modernizr enables HTML5 elements & feature detects; Respond is a polyfill for min/max-width CSS3 Media Queries For optimal performance, use a custom Modernizr build: www.modernizr.com/download/ ->

[/php]

The core configuration

Now we’re starting to build up nicely. In config.php, add the following code, which I’ll step through and explain.

[php]

However, whereas Zend takes the APPLICATION_ENV setting from an environment variable set by the web server, I wasn't able to find out how to replicate that for cloudControl. Given that, I've determined it by looking at the hostname up until the first period, i.e., the third-level domain. Now, I'm not saying that this is the best approach, but for the purposes of our application, it will work. But given that, we have to name our branches and deployments to match our configuration.
[php] define(&'TABLE_STAFF', &'staff'); set\_include\_path(implode(PATH_SEPARATOR, array( realpath(APPLICATION_PATH . &'/library'), get\_include\_path(), ))); require_once(&'Zend/Loader/Autoloader.php'); $autoloader = Zend\_Loader\_Autoloader::getInstance(); [/php] Here, we ensure that the Zend libraries are on our include path and for convenience, set a constant for the users table, to avoid remembering it in our CRUD pages. [php] // database configuration $config = new Zend\_Config\_Ini( APPLICATION_PATH . &'/config/application.ini', APPLICATION_ENV ); $db = Zend_Db::factory($config->database); $db->getConnection(); $db->setFetchMode(Zend_[Db::FETCH_OBJ][5]); $view = new Zend_View(); [/php] Here, we load up a connection to our database through a Zend\_Config\_Ini object and our configuration file and create a view object, required to render forms later. [php] function getManageForm() { $firstName = new Zend\_Form\_Element_Text(&'firstName', array(&'label' => &'first name: &', &'required' => true) ); $lastName = new Zend\_Form\_Element_Text(&'lastName', array(&'label' => &'last name: &')); $emailAddress = new Zend\_Form\_Element_Text('emailAddress', array(&'label' => 'email address: &', &'required' => true) ); $occupation = new Zend\_Form\_Element_Text(&'occupation', array(&'label' => &'occupation: &')); $id = new Zend\_Form\_Element_Hidden(&'id', array(&'required' => true)); $submit = new Zend\_Form\_Element_Submit(&'submit', array(&'label' => &'Create User', &'ignore' => true) ); $form = new Zend_Form; $form->setMethod(&'post') ->setAttrib(&'id', &'manage_user') ->addElement($firstName) ->addElement($lastName) ->addElement($emailAddress) ->addElement($occupation) ->addElement($submit) ->addElement($id); return $form; } function getDeleteForm() { $id = new Zend\_Form\_Element_Text(&'id', array(&'required' => true, &'readonly' => true, &'label' => &'user id: &') ); $submit = new Zend\_Form\_Element_Submit(&'submit', array(&'label' => &'Delete User', &'ignore' => true) ); $form = new Zend_Form; $form->setMethod(&'post') ->setAttrib(&'id', &'delete_user') ->addElement($id) ->addElement($submit); return $form; } [/php] Here are two convenience methods for working with our forms. The first one will give us a form for adding and editing records, the second for deleting them. ### The CRUD Forms #### Add

The add user form

Grab a copy of the add form from [the github repository][6] and save it as add.php. In it you'll see that we've included config.php and the header and footer templates. After that, we instantiate an add form, set the action and ensure that the id field is not required. After that, we've put in a basic html shell to ensure the user knows the page that we're on and a simple if/else that validates the form. If the page is not the result of a POST operation, then we just show the form. If the page is the result of a POST, then we attempt to validate it. If it is valid, then we attempt to insert a new staff member. If successful, we tell the user and provide them a link to the view all staff page. If it wasn't, we let them know and again provide them a link to the view all staff page. If the form wasn't successful, then we render it again and the form class will take care of repopulating it from the POST information and displaying the appropriate errors. #### Edit

populated edit form

Grab a copy of the edit form from [the github repository][7] and save it as add.php. In it you'll see that, as with the add form, we've included config.php and the header and footer templates. The code also retrieves the user, based on the GET id value and populates the form with the information retrieved from the database. With this information, we pre-populate the form data so it's ready to update by the user. After that, we've put in a basic html shell to ensure the user knows the page that we're on and a simple if/else that validates the form. If the page is not the result of a POST operation, then we just show the form. If the page is the result of a POST, then we attempt to validate it. If it is valid, then we attempt to update the details of the staff member. If successful, we tell the user and provide them a link to the view all staff page. If it wasn't, we let them know and again provide them a link to the view all staff page. If the form wasn't successful, then we render it again and the form class will take care of repopulating it from the POST information and displaying the appropriate errors. #### Delete

populated delete form

Grab a copy of the delete form from [the github repository][8] and save it as add.php. In it you'll see that we've included config.php and the header and footer templates. After that, we instantiate an add form, set the form action and id value to use the id retrieved from the GET data. After that, we've put in a basic html shell to ensure the user knows the page that we're on and a simple if/else that validates the form. If the page is not the result of a POST operation, then we just show the form. If the page is the result of a POST, then we attempt to validate it. If it is valid, then we attempt to delete the staff member. If successful, we tell the user and provide them a link to the view all staff page. If it wasn't, we let them know and again provide them a link to the view all staff page. If the form wasn't successful, then we render it again and the form class will take care of repopulating it from the POST information and displaying the appropriate errors. #### List

list users

Grab a copy of the list form from [the github repository][9] and save it as add.php. In it you'll see that we've included config.php and the header and footer templates. After that, we retrieved the top 10 user records and in a simple table, have rendered them for the user to see. The table contains the first & last name, email address and their occupation along with links to edit and delete the user. Above the form, we also have a link to add a new staff member. Now I've not focused too much on the structure of the application as this is a tutorial about cloudControl instead of creating an application in PHP. So if you have any questions, add a comment or email me – I'm more than happy to clarify anything here. Now that the code's in, workign and ready, we need to commit it to our local repository and deploy the changes out to our branch. So let's do that with the following commands: [bash] git add . git commit -m “adding project content” cctrlapp maltbluedev/development push cctrlapp maltbluedev/development deploy [/bash] In under a minute, the code will be deployed to the development environment ready to test. So, in your browser, open up [http://development.maltbluedev.cloudcontrolled.com/list.php][10]. ### Winding Up Let's stop a moment and consider just how easy that was. Let's look at what we did and how simple it was to deploy. We just did the following: * Create an application * Commit it to a repository (which can be stored in multiple locations, including github) * Create a deployment that transparently works with the branch of the same name * Integrate MySQL in to our deployment and push out a database load script * Run through the application Here's what we didn't have to know: * How to be a Systems Administration ninja (though I know a few) * How to be a MySQL Database Administration guru * Configure servers, setup and manage a VPS or dedicated box * Worry about how much load we need right now or later * Write complicated deployment management scripts All we needed to do was to focus on the fundamental aspects that are important to us as developers: designing, building and testing our application**. ** ****And that's really how it should be for us as developers. It's important for us to know how the components work, how our work impacts on and is impacted by the various components in N-tier application architectures. But we should be focused on the application itself – the systems administration is for either others, or other times. ### Is cloudControl worthwhile? I'm proud to say a big hell yes. Through the experience I've gained so far, developing the application for this tutorial, by using cloudControl, I've been able to get back in touch with the aspect of my craft that I love the most - **software application design and development**. Whilst I'm an avid Linux lover and part-time systems administrator, far and away my greater passion is for software. The way that the [cloudControl][11] service has been constructed, from the *simple command line interface*, to the components that they offer, to *how* *reliable* it is - gives me the confidence to proudly tout their service to you as one that you should include either in your personal arsenal or in that of the company or organisation that you work for. It really becomes quickly apparent that they were and are web developers and know what it takes to build a reliable hosting platform that *just works*. On top of that, whenever I've needed any assistance, the staff there have been all too willing to offer quality support. A big shout out to *Henning*. ### Coming Up Next In the next part of this tutorial, we branch away from MySQL and look at just how easy it is to use MongoDB as well – and just how easy it is to deploy it with cloudControl. If you want more *tips*, *ideas*, *hints* and *suggestions*, [jump on the mailing list][12]. I'm keen to hear how you go with building the application, or a different application and deploying it with cloudControl. Let me know your thoughts in a comment or a tweet. ### Links / Further Reading: * * * * * [1]: http://framework.zend.com/ [2]: http://html5boilerplate.com/ [3]: http://cloudcontrol.com/add-ons/mysql/ "The cloudControl MySQL addon" [4]: http://www.stunnel.org/examples/mysql.html [5]: db::FETCH_OBJ [6]: https://github.com/maltblue/cloudcontrol-project/blob/master/add.php [7]: https://github.com/maltblue/cloudcontrol-project/blob/master/edit.php [8]: https://github.com/maltblue/cloudcontrol-project/blob/master/delete.php [9]: https://github.com/maltblue/cloudcontrol-project/blob/master/list.php [10]: http://development.maltbluedev.cloudcontrolled.com/list.php "The running Malt Blue app on cloudControl" [11]: http://cloudcontrol.com/?utm_source=maltblue&utm_medium=Banner&utm_campaign=MaltBlue [12]: http://eepurl.com/dWhRf "Sign up to the Malt Blue mailing list"

You might also be interested in these tutorials too...

Mon, Jan 9, 2012

Beginning cloud development with cloudControl – Part 4 – Memcache

Here we are at part four of the Beginning Cloud Development with cloudControl series and in this part, we’re adding Memcached support. In part one of the series, we laid the foundation for the application and got up to speed with what cloudControl is, why it works and how to get started using it.

Then in part two, we started to flesh out the application that we started building in part one and added MySQL support to it. We showed how to work with cloudControl to manage the key requirements, such as enabling MySQL support, connecting to the MySQL database and keeping the database up to date from a maintenance perspective (creating the database schema and loading data in to the database).

Then in the third part of the series, we replaced MySQL with mongoDB support. Now, in this, the third part of the series, we’re going to finish up with adding Memcached support. As the core of the work’s already been done in the application, this tutorial will be shorter and simpler than the previous three. So, get out the code that you worked through from part 2, or download a copy of it from the github repository and let’s get started.

Thu, Dec 8, 2011

Beginning cloud development with cloudControl

##.

Don’t forget to grab the other parts as well:


So you’ve heard all about the cloud. In the current day and age, you’d have to be living under a rock to have not encountered it by now. Whether it’s the ads from Amazon, Rackspace or Microsoft, the extensions to your favourite framework, such as SimpleCloud in Zend Framework or iCloud from Apple – The Cloud is Everywhere!

But these aren’t the only options available to us as developers. In this series I want to introduce you to and help you get started with another cloud service - cloudControl.

Mon, Jan 2, 2012

Beginning cloud development with cloudControl – Part 3 – MongoDB

Here we are at part three of the beginning cloud development with cloudControl series and in this part, we’re adding mongoDB support. In part one of the series, we laid the foundation for the application and got up to speed with what cloudControl is, why it works and how to get started using it.

Then in part two, we started to flesh out the application that we started building in part one and added MySQL support to it. We showed how to work with cloudControl to manage the key requirements, such as enabling MySQL support, connecting to the MySQL database and keeping the database up to date from a maintenance perspective (creating the database schema and loading data in to the database).

In this, the third part of the series, we’re replacing MySQL that we introduced in part two with mongoDB support.

Tue, May 22, 2012

Zend Form Mastery with Zend Config – Part 3 Standard Form &amp; Element Options

– Part 3 Standard Form & Element Options This is a Multi Part Series. Check out the other parts: Part 1 - Custom Filter Paths Part 2 - Core Form Configuration Part 4 - Configuring Zend Validators Options We’ve looked at custom form filters and we’ve looked at the core form configuration. But what about the other form properties? What about: setting an element as readonly an element as required ignoring an element and love them or hate them, what about decorators Element Options Outside of the options that we’ve looked at previously, there are a number of other options that we can consider implementing when configuring a Zend Form.


Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.

Join the discussion

comments powered by Disqus