LaravelVueWeb Development

Using Laravel and Vue.js for Fame and Glory

By March 13, 2016 No Comments

Last weekend I chose to develop an SPA (single-page application) written in Laravel and Vue.js in order to promote the launch of my band Stalko’s second album.

You can check out the final product, and follow along with the code.

The brief for this project is the following:

  • Allow users to listen to a new Stalko song
  • Share the song with friends in a fun way by typing in their name and a personalised message
  • Create a custom URL that users can send to their friends for them to read their message
  • Let the user choose what language to create their ‘share’ experience in (English or Maltese)

I also set myself some personal goals:

  • Test drive the application – a skill that I’ve been working on in PHP for the last year or so.
  • Use Vue’s router library to build my first SPA
  • Become more familiar with Vue in general

Planning It

It’s important to analyse the brief and translate it to technical terms that you can work with.

I want my users to be able to make a personalised experience for their friends, so that when visiting the website it would greet them with a message, and a Stalko song. Users would then be encouraged to create and share a personalised experience for one of their friends, and to buy tickets to our album launch. Hopefully this will create a viral loop where invited users will share to their friends.

Also – I decided to spice things up by allowing users to choose the language of their share.

I need to model this behaviour. To do so, I’ll  store the locale, name and message of each Share. To allow my SPA to preview and store each Share I’ll set up a couple of Api endpoints.

Setting up

Setting up is quick and easy when using Laravel’s installer with Homestead:

I set up my hosts file:

by adding one line to it:

Getting to work

I need to develop a simple API that my client side javascript can consume in order to create Shares.

The Laravel make:test command generates a boilerplate test class:

I can now put tests in my new ShareControllerTest file, and run them from terminal with a single line:

I want to be able to post to the /shares endpoint in order to create a new Share resource. I want to make sure that only valid requests will filter down to my ShareController. It’s often tempting to jump ahead when writing tests, because through experience we can sometimes predict how the eventual test should look:

But by doing that, you aren’t “driving” the development through the tests, since the code isn’t evolving naturally due to the test. A better approach is to remember Uncle Bob’s rule:

You are not allowed to write any more of a unit test than is sufficient to fail.

So an appropriate first test would be more like:

This fails.

The failing test drives my next piece of code, which is to fix the 404 error that I’m receiving. I don’t have any routes for my application to respond to – hence the 404:

Running the test again now will result in a 500 error – something to be expected since I haven’t created the ShareController yet. I can do that easily with Laravel:

For now I’ll create an empty store method in my new controller, and run the test again:

We’re not doing anything inside the method, and as a result Laravel automatically is returning a 200 response for us. Let’s change that by leveraging Laravel’s Form Request Validation:

We can add  validation rules inside this request object:

To instruct Laravel to validate using this object when trying to store a Share, we type hint the store method on our ShareController:

Our test passes now!

We can make it fail again by testing for the appropriate Json response:

We’ve returned to our initial prediction of how the first test might look, but we’ve test driven our production code to this point – great! We can fix our now failing test by simply adding the appropriate validation rules in our StoreShareRequest.

Great. It’s time to actually save the Share now.

By passing a a request that will pass validation, the control of the application now resides inside the ShareController::store method. This test will fail until we add the code to persist the Share.

Let’s start by creating the appropriate migration and model:

We’ll populate the migration file as follows:

And we can pop in the line that will save our Share to the database.

Don’t forget to enable database migrations when testing by adding the following use statement:

We’ll run the tests again.

A common mistake – we’ve forgotten to set up our fillables property on the Share model:

Now that we’re passing again, we can continue fleshing out our test.

It’s good to have a deep understanding of what we want to happen first: when a user creates a new Share we want to present them with a Url that they can then share with their friends.

Let’s translate that intent and add it to our test.

Running this test the first time will result in an error – the route shares.show isn’t defined, and so the test throws an error. This is a common scenario where you first need to work on getting your tests to fail instead of throwing an error before you can make them pass.

Let’s do just that.

Now the test fails. Let’s make it pass by adjusting the response:

Fast Forwarding

There’s some other functionality that needs to be added before we can move on to the front end. To avoid this post from getting too long, I’m going to highlight what was done and leave the source code up for your perusal:

  • Make the application respond to the shares.show route to display the customized share message
  • Make the application respond to a share-previews.store endpoint to allow my javascript Api consumer to generate a preview of what their share message will look like to their friend.
  • Make the homepage respond to a default Share

The Front End

I was really excited to jump into creating my first SPA with Vue. Even though I’ve used Vue for a number of projects – I’ve never invested the time to become really comfortable with it. My goal is to develop something that I can come back to a months from now and be able to quickly understand what’s going on.

I’ll start by pulling in Vue, Vue Resource, and Vue Router via npm.

I decided to use browserify for two reasons. First is the ability to use the latest features of Javascipt. Second, browserify allows you to require javascript files into others allowing me to organise my Javascript in a modular fashion.

I’d like to go over some of the concepts that I used, and the tricks that helped me level up my Vue game.

First, let’s set up the boilerplate to at least get a screen going where we can see the homepage!

I’ve setup my app.js to allow Vue’s router to take control of the homepage, and to pass that control to a Vue component.

The component is extremely basic, and simply renders the template defined:

We need to make a few adjustments to the Html too:

This in itself is already very satisfying to me. On page load, Vue’s router kicks in and takes control!

Allowing users to create a message to share with friends

The application needs to collect the following data from the user:

  • The language of the message that they’re writing
  • The name of the person this message is for
  • The actual message.

For aesthetic purposes I decided to split up these actions into three screens. This decision led me to discover a great pattern to keep a growing Javascript app from getting out of control.

The store pattern is explained on this excellent page on Vue’s documentation and recommends to create an object that acts as a single source of truth, and pass that object around to the different modules that you might have, allowing them to interact with it as you see fit. Without this pattern I might have been tempted to use events to communicate between different modules – from experience this can easily become messy and difficult to deal with.

I created my store object to allow me to handle the user’s Share:

I subsequently injected the store and router objects into my new components that needed to interact with them:

The locale, name and message components are very similar, so let’s use the locale component as a case study.

I’ve set up a simple Vue component that depends on the store and router objects, and exposes one method: setLocale. The setLocale method sets the locale that it is passed on the store object, and then instructs the app via the router to continue on to the name route.

The template that will be rendered is defined as follows:

Fast Forwarding

I’d like to cover interacting with the server before wrapping up, so I’ll skip setting up the name and message screens and jump straight to submitting the Share in the review screen.

The Vue component looks like this:

Once ready, the preview is created via the fetchPreview method. I’ve utilized the $http object made available to me by including the Vue Resource plugin.

The review template interacts with the component with a couple of simple bindings:

Wrapping Up

I skimmed over some of the work done setting up this mini website, but I hope that it conveys the thought process behind a test driven application.

Vue and Laravel make for a beautiful combination for web development, this was a fun project.

Check out the source on github, check out the final website and feel free to leave a comment below!

Michael Stivala

Michael Stivala

An inspired creative professional.