Building an API for your Laravel Application with Lumen

Posted by Adam Engebretson on April 14, 2015

Lumen is a "micro-framework" built on top of Laravel's components, and is the official micro-framework of Laravel. Lumen is built for speed, and is one of the fastest PHP micro-frameworks available - even significantly faster than similar frameworks such as Silex.

For more information about how to get started with Lumen, check out the Lumen Documentation, as well as a blost post from Matt Stauffer!

While Lumen is exciting for many developers, it may pose some questions. In this blog post, I'd like to discuss how you can use Lumen to build an API for your Laravel Application. Obviously, Lumen will depend on your Laravel models. Instead of re-writing your models in both Laravel and Lumen, let's figure out how to use git submodules to bridge the gap!

The Laravel Side of Things

First thing's first - let's get a Laravel app up and running! We'll use laravel new application, and then follow that up with a php artisan app:name Application. Of course, you can swap out "application" with your own project name if you're following along. For the rest of this post, we'll refer to the Laravel application as being in the Application namespace.

In our Laravel application, we'll create a simple database migration.

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration {

  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('posts', function(Blueprint $table)
    {
      $table->increments('id');
      $table->string('title');
      $table->text('body');
      $table->timestamps();
    });
  }

  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::drop('posts');
  }

}

Next, we'll create a very simple model for our Post.

<?php namespace Application;

use Illuminate\Database\Eloquent\Model;

class Post extends Model {

    //

}

We'll now assume that you've gone ahead and built front-end and back-end views for reading and updating your posts on your blog website. Ta-da, you have a marvelous Laravel application! Now, since you're such a good developer and content writer, HackerNews has called you and asked to feature all of your blog posts on their home page! Good for you! :D So they'll need an API to access your posts. Since HackerNews has a lot of traffic (ignoring the fact that they'd actually cache your API responses), you'll need a strong API to back your integration. Let's set one up with Lumen!

The Lumen Side of Things

To get started, we'll run lumen new api. At the time of this blog post, Lumen does not come with a php artisan app:name command, so we'll have to move forward with using the App namespace. From here on, out our Lumen application is namespaced with App.

The first thing we'll need to do is to enable Eloquent. To do this, simply uncomment the $app->withEloquent(); line in bootstrap/app.php. For our case, we'll also want to uncomment the Dotenv::load(__DIR__.'/../'); line so that our .env configuration values will take effect in our Lumen application. Finally, let's make sure that our database configuration in .env of our Lumen application matches that of the Laravel application.

Next, let's create a route for getting a list of all of our blog posts. We'll worry about populating it later. In app/Http/routes.php, we'll define a route for /posts:

$app->get('posts', function() {
    return [];
});

Bridging The Gap

Now is where we get to the tricky part: pulling in your Laravel application so that Lumen can have access to your models. We'll be using git submodules to do this. What submodules do is allow you to include another git repository in your project's repository. You can specify the exact commit hash at which you'd like to require this. Let's get started.

To install a submodule, we use the git submodule add command. Here's what yours might look like:

git submodule add --force git@github.com:adamgoose/laravel laravel

I'm using the --force flag here, because git is smart enough to know that you already have the adamgoose/laravel repository installed on your machine. The flag tells git that you want to clone the repository into the laravel folder anyway.

Now, we'll need to tell Composer to autoload your project directory into Lumen's autoloader. Update your Lumen's composer.json file to look something like this:

{
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Application\\": "laravel/app/"
        },
        "classmap": [
            "tests/"
        ]
    }
}

Notice how we've added "Application\\": "laravel/app/" to the PSR-4 autoloader section. This tells composer to make sure and autoload the Application namespace from the laravel/app directory, which is where you Laravel application lives!

WARNING: Please be aware that your Laravel's composer.json is completely ignored by your Lumen's composer.json. This means that any dependencies you have for your Laravel application will not necessarily be available to Lumen, unless declared explicitely. This means that if your Post model requires Guzzle (for some strange reason), you'd need to define Guzzle as a dependency of your Lumen application, as well as your Laravel application.

Now that Lumen is operating with your Laravel application autoloaded, we can reference the Application\Post model from inside Lumen. Let's review that /posts route:

$app->get('posts', function() {
    return \Application\Post::all();
});

Notice how we reference the fully qualified class name (FQCN) to the Post model. You can also import this to the top of the routes file (or, more ideally, your controller) with use Application\Post;.

Not only will you have access to your models, but also your other classes, like Repositories, Services, and Commands. This makes it incredibly easy for you to queue jobs from your API that will be handeled by your Laravel application's Queue Worker.

For example, say your Laravel application had a ShouldBeQueued command called UpdatePubSubHubbub. This would theoretically be fired whenever your blog posts are created or updated. You would go about your day programming it into your Laravel application, then when you're ready to update your API, simply call $this->dispatch(new \Application\Commands\UpdatePubSubHubbub($post)); from your Lumen controller method. It would then be queued and processed by your Laravel Queue Worker.

Moving Forward

Once you have your initial API set up, you'll need to know how to update the submodule within your API. Every time you work on your Laravel application, you'll commit and push your changes to GitHub. Then, you'll switch over to your Lumen application.

First thing's first: update your underlying Laravel Application by running git submodule update --remote laravel. Or, you can simply cd laravel && git pull. Updating the currently checked-out revision inside your submodule directory will then tell your parent repository to update as well!

Now you can go about your business making changes to your Lumen application. Once all is said and done, git commit and deploy away!