Community

Getting Started with Laravel on BlueMix

Share this post:

**Updated 4/10/15 for Laravel 5 **
Few web developers like to spend a lot of time configuring systems and servers, and any PHP developer knows how much of a pain this can be. Luckily, there are services out there that take all this grunt work out of creating web applications, such as IBM Bluemix. In this tutorial, we’ll create a basic Laravel app, deploy it on Bluemix, and bind it to a database. By the end of our tutorial, our web app will provide a very basic way to write or delete public notes. You can view a running demo here.

Prerequisites

You should have Composer and PHP 5.5 (although PHP 5.4 should be fine) installed globally on your local machine. You should also have basic command line knowledge. It will help to have at least a minimal understanding of PHP and the Laravel framework, but even if you don’t, you’ll still be able to follow this tutorial.

Creating, Configuring, and Deploying a Laravel App to Bluemix

Open up a command-line prompt and navigate to the directory that you want your project’s root directory to reside in. Run this command to have Composer grab most of the base files you’ll need:

[code]composer create-project laravel/laravel laravel-demo –prefer-dist[/code]

Creating a manifest

Move to the newly created root directory of your Laravel project and create a new file called manifest.yml. This stores the config options that the Bluemix command line program uses when we upload our file to Bluemix. Your file should look similar to this:

[code]—
applications:
– name: your-app-name-here
memory: 128M
buildpack: https://github.com/cloudfoundry/php-buildpack#v3.2.2
env:
CF_STAGING_TIMEOUT: 15
CF_STARTUP_TIMEOUT: 15[/code]

A quick explanation of our settings:

  • name: this sets our app name on Bluemix. You should choose a unique name that hasn’t been used by anyone else.
  • memory: our demo app will be quite simple, so we’ll only request 128MB of memory.
  • buildpack: this one is important! Since Bluemix doesn’t have an automatic system to handle PHP or Laravel apps, we have to specify what should happen when we upload one of these kinds of projects. Luckily, there’s already a good buildpack built, so we don’t have to make our own.
  • env: We want to make sure our app has plenty of time to deploy and start, so we’ll set two environment variables to (arbitrarily) give it a max of 15 minutes. This should be way more than enough for our simple app. If you have a complex application with many Composer dependencies, deploying will probably take a little, so we’ll just make sure we don’t have to worry about timeouts. We could also set other environment variables here if needed.

You can see more detailed documentation on the manifest.yml as well.

Setting up your project file structure

Change directories into the laravel-demo (application root) folder. Create a htdocs folder.
Move all generated project files into this newly created htdocs folder with the exception of these four files:

  • .gitignore
  • composer.json
  • composer.lock
  • manifest.yml

Your file structure should now look similar to this:
File_structure

Choosing which Files get Sent to Bluemix

Create a new file in your project root called .cfignore.
Edit .cfignore by entering in the following:

[code]composer.lock
htdocs/vendor/[/code]

when we push to Bluemix, .cfignore is used to determine what files and folders should NOT be uploaded. For example, we ignore any composer-installed libraries in htdocs/vendor/ because they’ll be installed automatically in Bluemix by the php buildpack when we deploy.

Next, we must update the composer.json file to reflect the new htdocs file paths. Take note of the htdocs modifications shown below. Your updated composer.json should look similar to this:

cf appscomposer_json_mods

Finally, we must provide some customized entries for the cloud foundry php buildpack to understand things like where our vendor folder is being generated, what the document root url folder should be and what PHP extensions are useful for Laravel – to name a few.

Create a new folder in the root of our application named .bp-config. Change directories into this folder and create a new filed named options.json. Within this file, include the following json snippet:

[code]{<br /> "PHP_VERSION": "{PHP_55_LATEST}",<br /> "COMPOSER_VENDOR_DIR": "htdocs/vendor",<br /> "WEBDIR": "htdocs/public",<br /> "PHP_EXTENSIONS": [ "bz2", "zlib", "openssl", "fpm", "tokenizer", "curl", "mcrypt", "mbstring", "pdo"]<br />}[/code]

In summary, we’ve …

  • Added two new files to the root folder of our application: manifest.yml and .cfignore.
  • Added one new folder to the root folder of our application: .bp-config and inserted within it a new file named options.json
  • Moved most of our project files into a directory named htdocs
  • Modified the composer.json to reflect the modified file structure

Deploying to Bluemix

We’re ready to deploy to Bluemix! If you haven’t deployed anything to Bluemix before, create a Bluemix account and follow the first three steps here to install the command line tool, connect to Bluemix, and log in. Finally, just run this command from your application root to push and deploy your app on Bluemix!

[code]cf push[/code]

Once you see the message that your app has started (don’t worry if some of the actions take a little while to run during the first deploy) navigate to yourappname.mybluemix.net. Your app is now running! You’ll see something like this:


Working with a Database

It’s been easy so far to get our site up and running – basically just a few configuration tweaks and changes are all we’ve done. However, without some sort of a datastore, we’ll have severely limited capabilities – including no way to permanently store notes like we want to. On a more classical sever setup, we could perhaps write data to a file on disk. However, this approach leads to scalability issues. Also, Bluemix VM instances, to make scaling as easy as possible, use an ephemeral filesystem which isn’t appropriate for storing permanent data. Instead let’s setup a MySQL database, which will work well with Bluemix and integrate nicely with Laravel. We’ll create a single table called notes to store our messages in. In a future tutorial we might look at setting up an alternative datastore, such as Redis.

Binding the MySQL Service

Navigate to bluemix.net, go to your dashboard, and select your new project. In the overview screen for the app, click ‘Add a Service’. We’ll use the ClearDB MySQL service. After a moment of processing, it should appear as a service in your app overview.

LaravelDemoClearDB

When we bind a service to our app, the service typically adds configuration values to a JSON-formatted environment variable named VCAP_SERVICES. If you click the ‘Quick Docs’ button on the ClearDB service on Bluemix, you can see the relevant part of the JSON value. We need to configure Laravel to read these values and use them to connect to the database. At the top of app/config/database.php let’s add a few lines to grab the values pertaining to our database:

[code language=”php”]
<!–?php <!–mep-nl—->
$services = json_decode(getenv(‘VCAP_SERVICES’), true);
$sqlCreds = $services[‘cleardb’][0][‘credentials’];

return array(
…[/code]

Then we have to use them in the configuration settings below:

[code language=”php” firstline=”49″]

‘connections’ => array(

‘sqlite’ => array(
‘driver’ => ‘sqlite’,
‘database’ => __DIR__.’/../database/production.sqlite’,
‘prefix’ => ”,
),

‘mysql’ => array(
‘driver’ => ‘mysql’,
‘host’ => $sqlCreds[‘hostname’],
‘database’ => $sqlCreds[‘name’],
‘username’ => $sqlCreds[‘username’],
‘password’ => $sqlCreds[‘password’],
‘charset’ => ‘utf8’,
‘collation’ => ‘utf8_unicode_ci’,
‘prefix’ => ”,
),

‘pgsql’ => array(
‘driver’ => ‘pgsql’,
‘host’ => ‘localhost’,
…[/code]

Creating the Notes Table

[code][/code]

After configuring Laravel to connect to our database, we’ll generate a database migration to create a new database table. Run from the command line:

[code][/code]

[code]php htdocs/artisan migrate:make create_notes_table[/code]

[code][/code]

Open up the newly created migration file and add a few lines of code to create a database table:

[code][/code]

[code language=”php”]
<!–?php <!–mep-nl—->
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateNotesTable extends Migration {

/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(‘notes’, function($table)
{
$table->increments(‘id’);
$table->text(‘content’);
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists(‘notes’);
}

}
[/code]

Basic Note Functionality

[code][/code]

This isn’t a Laravel tutorial, so we’ll quite quickly run through the steps to set up some basic operations on our data. Create a app/models/Note.php with the following contents:

[code][/code]

[code language=”php”]
<!–?php <!–mep-nl—->
class Note extends Eloquent {
public $timestamps = false;
}

?>
[/code]

[code][/code]

Generate a controller with the following command:

[code][/code]

[code]php htdocs/artisan controller:make NoteController –only=store,index,destroy[/code]

[code][/code]

Then add some basic code to the new file found at app/controllers/NoteController to let us view, create, and delete notes:

[code][/code]

[code language=”php”]
<!–?php <!–mep-nl—->
class NoteController extends \BaseController {
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
return View::make(‘notes.index’)->with(‘notes’, Note::all());
}

/**
* Store a newly created resource in storage.
*
* @return Response
*/
public function store()
{
$note = new Note;
$note->content = Input::get(‘content’);
$note->save();
return Redirect::action(‘NoteController@index’);
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @return Response
*/
public function destroy($id)
{
Note::destroy($id);
return Redirect::action(‘NoteController@index’);
}

}
[/code]

Add routes for these actions in app/routes.php:

[code language=”php”]
<!–?php<!–mep-nl—->
/*
|————————————————————————–
| Application Routes
|————————————————————————–
|
| Here is where you can register all of the routes for an application.
| It’s a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/

Route::get(‘/’, function()
{
return View::make(‘hello’);
});

Route::resource(‘/notes’, ‘NoteController’, [‘only’ => [‘index’, ‘store’, ‘destroy’]]);
[/code]

And make a view for our page at app/views/notes/index.php:

[code language=”html”]

Notes

[/code]



# Note Delete
id ?> content ?>


[code]

[/code]

[code]<br />
[/code]

Making Bluemix Run Database Migrations

[code][/code]

We have one final challenge: getting Bluemix to migrate our database. Unfortunately, there’s no current way to access a shell prompt on Bluemix and run the database migration. We could connect directly to our database, but then we’d have to craft our SQL by hand and would lose all the advantages of having database migrations. Instead, let’s set it up so that on a push to Bluemix, any new migrations are run automatically. Luckily, with our buildpack and Composer, this is easy. In composer.json, there’s a configuration option with commands that Composer will run after it installs dependencies. Since Composer installs dependencies on every deploy, we can just tack on a command to migrate the database afterwards:

[code][/code]

[code language=”javascript” firstline=”18″]

"scripts": {
"post-install-cmd": [
"php htdocs/artisan clear-compiled",
"php htdocs/artisan optimize",
"php htdocs/artisan migrate –force"
],
"post-update-cmd": [
"php htdocs/artisan clear-compiled",
"php htdocs/artisan optimize"
],
"post-create-project-cmd": [
"php htdocs/artisan key:generate"
]
},

[/code]

[code][/code]

Run cf push again, and your application will be pushed to Bluemix, the proper database tables generated, and your application deployed! Go to yourappname.mybluemix.net/notes and you should see something like this:

[code]<a href="/blogs/bluemix/wp-content/uploads/2014/06/LaravelFinishedNewScreenshot.png"><img src="/blogs/bluemix/wp-content/uploads/2014/06/LaravelFinishedNewScreenshot.png" alt="LaravelFinishedNewScreenshot" width="497" height="316" class="aligncenter size-full wp-image-2667" /></a>
[/code]

And we’re finished! Overall, a pretty easy process to get a Laravel app up and running on Bluemix and connect to a database. It’s a little bit of a pain that we don’t have any direct command line access on Bluemix to run database migrations by hand, but as this article illustrates, we have an easy workaround. Just be careful not to push any destructive migrations by accident. Still, that small issue is easily outweighed by all the other tedious work we can skip by using Bluemix.

[code][/code]

IBM jStart Team, IBM Emerging Technologies

More stories
December 7, 2018

Highly Available Applications with IBM Cloud Foundry

To properly deploy an application in a cloud environment and ensure maximum responsiveness, your app needs to be deployed in a certain (and easy) way that maximizes the chance of an instance always being ready to respond to a user request. This article will explain how to deploy your Cloud Foundry applications in the IBM Cloud such that you reach your target application availability.

Continue reading

December 5, 2018

Cloud Foundry Container-to-Container Networking

If you're like many developers who are deploying applications to Cloud Foundry, you probably don't think about networking too often. After all, as a PaaS, Cloud Foundry takes care of all the routing and connectivity for you. There is one feature, however, you might consider before writing your next app: container-to-container networking.

Continue reading

November 30, 2018

Bringing It All Together: A Single Account and Billing Management Experience

We're pleased to announce that the IBM Cloud platform has integrated all SoftLayer customer portal functionality. And as a result, we've significantly improved the way you navigate and manage your account.

Continue reading