How to implement In-browser Database for offline use

If you are familiar with Laravel Eloquent, this is going to look familiar.

We are going to use a JS library very similar to Eloquent called collect.js. With this little beast in place, all you have to do is use it to transform your data into Eloquent collection in JavaScript, and use all Eloquent magic on the frontend:


// Fake db (aka fake news)

import collect from 'collect.js'

const collection = collect({
    users: [
        { id: 1, firstname: 'Jane', lastname: 'Doe', gender: 'F' },
        { id: 2, firstname: 'John', lastname: 'Doe', gender: 'M' },
        { id: 3, firstname: 'Penelope', lastname: 'Cruz', gender: 'F' },
        { id: 4, firstname: 'Eva', lastname: 'Longoria', gender: 'F' },
        { id: 5, firstname: 'Cristiano', lastname: 'Penaldo', gender: 'M' }

    cities: [
        { id: 1, name: 'Sydney', country: 'Australia', humans: 4873217, kangaroos: 9321893, snakes: 22432645},
        { id: 2, name: 'Douala', country: 'Cameroon', humans: 5221943, kangaroos: 0, snakes: 2981023},
        { id: 3, name: 'Villetaneuse', country: 'France', humans: 32987, kangaroos: 0, snakes: 876432}

    friends: [],
    todos: [], // duh
    andSoOn: []

// Important bit...
localStorage.setItem('fake_db', JSON.stringify(collection))

And there, my friend, you have persisted your entire fake database to the localStorage. If and when you reload the page, or quit and reopen the browser, your data is not lost and you can query if offline like this

// Read and query fake_db
let fakeDB
const data = localStorage.getItem('fake_db')
if (data) {
    fakeDB = collect(JSON.parse(data))

const females = fakeDB.get('users').where('gender', 'F').all()
console.log(females) // (3) [{...}, {...}, {...}]
//The above array will contain users 1, 3 & 4

As you can see, it looks and behaves like helpers function from Laravel Collection. You could wrap this as a service or use with one of the cool kids like Redux or vuex .

Keep in mind though, localStorage is limited in size (MB).  How big? I have no clue. I wanted to Google it and put it here, but man, I’ll leave it for another day. And yeah, Ronaldo moved to Juve. But all good. We’ll sort it out. As long as we don’t get relegated, we’ll sort it out.

Disclaimer: If your code does not work, I have no idea why. If your code works, I have no idea why.

Get user timezone with Javascript

In 2017 it’s relatively easy to get the user timezone with countless of packages available. Nonetheless, there are easier, shorter, faster way to get the user timezone using just vanilla JavaScript, which takes it from the user’s browser if set properly.

var split = new Date().toString().split(" ");
var timeZoneFormatted = split[split.length - 2] + " " + split[split.length - 1]; 

//outputs "GMT+1100 (AEDT)"

Manchester is red! So is my bank account.

Laravel multilingual application

When working with multilingual applications, I like to have clear URls without the language displayed. Therefore I use session to manage my localization. I have the following setup:


public function handle($request, Closure $next)
    if( !Session::has('locale' )){
        $browserLanguage = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); //read browser language

        if ( array_key_exists($browserLanguage, Config::get('languages')) ) {
            Session::set('locale', $browserLanguage);
        } else {
            Session::set('locale', 'en');

    //Simply set language from session 

    return $next($request);

What happens is, first I check if there is already a locale saved in the session. If not, I get the browser language, and check if that language in my languages array from ‘/config/language.php’, which simply returns an array of languages. If the browser language is not in my languages array, I default back to English. Now that the language is set in the session, we need to set it to the app as well `App::setlocale()`.

Next, add your middleware to the Kernel, then wrap all your routes that need localization in a group and pass this middleware to the group

// app/Http/Kernel.php
protected $routeMiddleware = [
    'translate' => \App\Http\Middleware\TranslateMiddleware::class

// routes/web.php 
Route::group(['middleware' => 'translate'], function() {
    Route::get('home', 'HomeController@index');

Note: Don’t forget ‘use App;’, ‘use Config;’ and ‘use Session;’ on top of your middleware

What if the user decides to manually change the language?

Simple. Define a get route that takes one parameter. That parameter is going to be the language (2 letters). Then define a function in a controller, and call App::setlocale() again, passing it the URL parameter. But first, check if the language in parameter is in the languages array.

// route/web.php
Route::get('language/{language}', 'HomeController@setLanguage');

// HomeController
public function setLanguage($language)
    if ( array_key_exists($language, Config::get('languages')) ) {
        Session::set('locale', $language);

    return redirect()->back();

And voila!

At least Man U won and is getting closer to 4th position. If we defeat City this week, I think that would almost guarantee a 4th place.

Vue 2 SPA restricting components for logged-in users only

Who doesn’t need authentication middleware to secure their app? Not me. In SPAs (Single Page Applications), this could seem tricky according to your development background. Having a Laravel background, it makes more sense to me to apply authentication middleware to routes. Fortunately, VueJS official router facilitates that thanks to its ‘beforeEnter’, to which you may apply guards. This is how I do it.

First, let’s create a middleware service in ‘src/services/middleware.js’. Not that I use vue-cli to generate the project.

import user from './auth'

export default {
    guest (to, from, next) {

    auth (to, from, next) {
        next(user.check() ? true : {
            path: '/login',
            query: {

You can see most of the vocabulary is borrowed from Laravel, though the query looks more like Express. The guest() method only allows guest users for pages like Login and Sign Up. Conversely, the auth() function only allows authenticated users, else redirect to login with the intended route as a URL parameter like http://localhost/login?redirect=dashboard.

Now, let’s define /src/services/auth.js

import Vue from 'vue'

export default {
    user () {
        return this.$store.state.user

    check () {
        return localStorage.getItem('token') //get token from localStorage 

At last, in our router, we can check for user authentication on a per route basis.


import Vue from 'vue'
import Router from 'vue-router'
import Guard from '../services/middleware'

import NotFoundComponent '@/components/notfound'
import LoginComponent from '@/components/login'
import DashboardComponentfrom '@/components/dashboard'


export default new Router({
    mode: 'history',
    routes: [
        { path: '/login', name: 'login', component: LoginComponent, beforeEnter: Guard.guest },
        { path: '/dashboard', name: 'dashboard', component: DashboardComponent, beforeEnter: Guard.auth }
        { path: '*', component: NotFoundComponent }

From the above routes, ‘login’ will only be available to guests, whereas ‘dashboard’ will require authentication. Then the ‘catch-all-routes’ will be displayed to both guests and authenticated users if they enter random URLs.

I can’t get over Madrid loosing to Barcelona at home. Such is life.

Laravel running multiple operations with a single DB instance

It sometimes occur that you have a lot of queries to run a single function. Let’s say you have a loop in which you keep querying the database. Although it’s recommended to optimize your code, if you are more efficient (not lazy) like me, you could run all queries in a single DB Instance.

public function doLotsOfStruff()
    DB::transaction(function () {
        $users = DB::table('users')->get();
        $bills = DB::table('bills')->lists('id');

The code above will run a single instance of DB instead of 2. You could also run the same like this

public function doLotsOfStruff()

   $users = DB::table('users')->get();
   $bills = DB::table('bills')->lists('id');


The second method is the more flexible one as midway you may decide to cancel everything and literally rollback

public function doLotsOfStruff()

   $users = DB::table('users')->get();

   // if we don't have users, we stop everything
   if ( !$users ) DB::rollBack(); 

   $bills = DB::table('bills')->lists('id');


Did I say Madrid lost 2-3 in today’s El Classico? Bummer! Hala Madrid!

VueJS Live search

Implementing live search is quite fun and easy with AngularJS thanks to the ng-model-options, to which you may apply a debounce (delay). Implementing something similar in VueJS however cannot be done out of box.

First, you need to import lodash (if not done yet). Don’t forget to run ‘npm install lodash’

// import lodash 
import _ from 'lodash'

Create your input

    <div class="form-group">
        <input type="text" v-model="keywords"  
            class="form-control input-lg" />

Now you can debounce the s**t out of it!

import _ from 'lodash'
import axios from 'axios'

export default {
    data () {
        return {
            keywords: "",
            results: []

    methods: {
        searchAfterDebounce: _.debounce(
            function () {
            }, 500 // 500 milliseconds

        search () {
            if (keywords.length > 1) {
                axio.get('/api/v1/url').then(response => {
                   this.results =

    watch: {
        keywords: function (val) {

All we are doing is waiting for the user to take half-a-second break when typing, then we check if there more than 1 characters typed. If true, we call the API and pass the results to the results variable.

Yeah and Madrid lost to Barcelona tonight 2-3. We are now 2nd. Ramos, again, took a red card; Messi (the extraterrestrial) scored a brace, including his late winner at the 92″. Hala Madrid!

Hello world!

Welcome to WordPress. This is your first post. Edit or delete it, then start writing!

Reminder to delete this… like in 2030. If you scrolled all the way down here, you deserve to see this;

For your tenacity, here is a little fact: You are now older than when you open this page. Feeling old yet?