A day-to-day log of the questions we've asked & the answers we've found.

William

Creating a Ratchet Web Socket Server with Laravel

TL;DR: Check out the package.

I've been building an api for the past couple months and we've come to the point where the frontend needs to do some status checks. Status checks currently ping the crap out of the current api and are pretty darn slow.

The solution for us is a Socket based status check, the frontend connects, validates and performs checks as it sees fit. 

There are many other reasons to use sockets in your web application, the most common example is a Chat server, but you can do almost anything with a Web Socket.

Ratchet?

"Ratchet is a loosely coupled PHP library providing developers with tools to create real time, bi-directionalapplications between clients and servers over WebSockets. This is not your Grandfather's Internet."

Basically in a few lines we get a full socket server with a lot of options, it's really easy to get going.

Google around for Laravel Ratchet and you'll land on this example. It's pretty basic and is a great start for including Ratchet in Laravel but I wanted a bit more, a package, some options, an easy way to add my own server.

 

Introducing Laravel Ratchet

Laravel Ratchet is a simple package I made that allows you to create a Ratchet Socket Server with minimal effort. Simply create a custom MessageComponentInterface or one that extends mine and you'll be up and running in no time.

Here is an example of a server we can telnet to that responds to us, everyone, then kicks us off:

<?php

namespace App;

use Ratchet\ConnectionInterface;

class RatchetServer extends \Askedio\LaravelRatchet\RatchetServer
{
    public function onMessage(ConnectionInterface $conn, $input)
    {
        parent::onMessage($conn, $input);

        $this->send($conn, 'Hello you.'.PHP_EOL);

        $this->sendAll('Hello everyone.'.PHP_EOL);

        $this->send($conn, 'Wait, I don\'t know you! Bye bye!'.PHP_EOL);

        $this->abort($conn);
    }
}

Read over the github page to learn how to configure it with your own class.

 

Conclusion

Ratchet is pretty cool. It was really easy to get setup and added to laravel. With this package I can focus on building the actions in the server instead of the server itself. If others find it useful and actually contribute that'd make it even better.

 


William

Cascading SoftDeletes with Laravel 5

Laravels Soft Deleting allows you to retain deleted records in your database so they can be used or restored at a later point. Restoring deleted records is great if a mistake is made and you need to revert and retaining deleted data can often be useful in the event you need to pull up some old records.

TL:DR: Take me to the package!

 

Traditionally Deleting Relations

 

I've always used MySQL foreign key constraints to cascade delete related records. Laravel makes it easy to use foreign keys in migrations, set `onDelete` to cascade and walla, your relations will be deleted automatically.

But what happens when you enable SoftDeletes? Your database is never told to actually 'delete' a record, instead the `deleted_at` field is updated. So what happens to your cascading deletes? Nothing, your related records are left alone.

Cascading Soft Deletes

Since soft deletes don't actually delete any records we need some way to cascade, or iterate over each, related model.

If you google "laravel 5 cascade soft delete" you'll find a lot of different options.

While each option may be different they all pretty much work the same way, you define the relations when deleting.

You do it in a model like this example:

public static function boot()
{
    parent::boot();    

    // cause a delete of a product to cascade to children so they are also deleted
    static::deleted(function($product)
    {
        $product->images()->delete();
        $product->descriptions()->delete();
    });
}  

Or even better, as an Event like here:

Offers::deleted(function($offer) {
    $offer->services()->delete();
});

Offers::restored(function($offer) {
    $offer->services()->withTrashed()->restore();
});

There is another way

Both options require us to duplicate a lot of code. Option 1 even requires us to override the boot function.

They both require us to define these settings for each Model, that's quite a bit of code - and almost all of it will be duplicated minus the actual relations.

My solution was to use Events and an array in the Model to tell it what to cascade, this allows us to simply add 2 lines to a Model to enable cascade deleting and restoring:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use \Illuminate\Database\Eloquent\SoftDeletes;
    use \Askedio\SoftCascade\Traits\SoftCascadeTrait;

    protected $fillable = ['name', 'email', 'password'];

    protected $softCascade = ['profiles'];

    public function profiles()
    {
        return $this->hasMany('App\Profiles');
    }
}

We needed to add the trait to enable the ability to read the `protected $softCascade` variable.

use \Askedio\SoftCascade\Traits\SoftCascadeTrait;

Then we we define `$softCascade` with the array of relations we want to cascade delete.

protected $softCascade = ['profiles'];

Each model gets its own array, if the array is empty or doesn't exist that models relations wont be deleted.


  2
William

Laravel Validaton: All Your Base Are Belong To Us

We all use Laravels Validation feature to ensure we have the required input and it matches some sort of rule. The available rules cover plenty of situations but they fail to cover one of the most important rules, input Sanitization.

TL;DR

A typical validator

Laravels Auth system comes with a simple User model that provides validation of the users details before it's inserted into your database. We see it like:

return Validator::make($data, [
    'name' => 'required|max:255',
    'email' => 'required|email|max:255|unique:users',
    'password' => 'required|min:6|confirmed',
]);

These rules will ensure the data we need is there and of the desired length and type. 

That's it, we're done! Nothing else to check, required and max made sure our data is safe, right?

But wait, there's more

Don't go yet, come back and clam your prize. A dirty database.

That's a really cool user name there isn't it?

Since you only required the name and made sure it was 255 chars or less the "user" was allowed to input anything they wanted, in this case a pretty 'hello world' alert loop that crashes Firefox.

Buy now and we'll double your order

Double up your dirty database with any type of unescaped output of the users name and let the magic begin.

If as in magic you mean things users will exploit.

The User Auth example escapes all of the strings with {{ }} before displaying to the user so there wont be much magic going on with that example.

If you defined a variable, even escaped, within a <script> or html <=""> tag your ticket to the magic show is valid, so watch out. Even escaped outputs can trigger XSS and other attacks when used improperly.

It's 2016, you probably have an API

Did you do any validation on the output from the API? Most APIs for Laravel allow you to transform your data, if you didn't sanitize your output in the transformation then what the user provided is sent to your frontend. 

Did you sanitize the output in your frontend? Well if you didn't, congrats, your entrance to the magic show has been granted. Be prepared to be amused.

Hurry, while supplies last

You can easily close the door on exploits and dirty databases by properly validating and sanitizing your users input.

Whitelisting, mmmm.

If you validate user input against a whitelist you ensure you get only the data you want. A simple alpha_num or regexp can often do the trick.

This works great when you need to allow HTML or need a very specific type of value.

It's not very practical for all of your fields.

For those generic fields that can accept almost anything (like utf8 and unicode) another solution may work better for you. Sanitizing

Sanitizing the users input will help prevent the user from inserting possible exploits and mucking up your database.

It's not as fool proof as a whitelist but it is the most recommended method I've seen over the years.

Many people sanitize their inputs with htmlspecialchars, some like strip_tags but I prefer HTMLPurifier.

Note: 'mews/purifier' does allow some HTML in the inputs by default, you can adjust this in its config.

Your order has shipped

Unbox it and start putting it together. The inputs are yours so you'll need to decide what method to choose.

composer require daylerees/sanitizer
composer require mews/purifier

app/Http/routes.php

<?php
Route::get('/', function () {

    $validator = app('validator')->make(request()->all(), [
               'title' => 'filter:clean|required|max:255',
               'body' => 'required',
    ]);
    
    return $validator->fails() ? $validator->errors() : 'pass';
});

app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{

    public function boot()
    {
        app('validator')->extend('filter', function ($attribute, $value, $parameters, $validator) {
            $data = [$attribute => $value];
            app('sanitizer')->sanitize([$attribute => $parameters], $data);
            $replace = array_merge($validator->getData(), [$attribute => $data[$attribute]]);
            request()->replace($replace);
            $validator->setData($replace);
            return true;
        });
    }

    public function register()
    {
        app()->register('Rees\Sanitizer\SanitizerServiceProvider');
        app()->register('Mews\Purifier\PurifierServiceProvider');
    }
}

Don't return this item to the store, we can help

If you can't tell what's going on, no worries. 

The ServiceProvider is extending the validator class with a 'filter' option that can be accessed in your validation rules:

'title' => 'filter:clean|required|max:255',

You can use multiple filters:

'title' => 'filter:clean,htmlspecialchars|required|max:255',

You can create custom filters:

app('sanitizer')->register('sanitize_string', function ($field) {
    return htmlspecialchars($field);
});

$validator = app('validator')->make(request()->all(), [
           'title' => 'filter:sanitize_string|required|max:255',
           'body' => 'required',
]);

You can use it any way Dayle intended with his Sanitizer package.

Conclusion

Sanitizing inputs in Laravel is far from a new topic. It's been talked about recently and at one point even had some code started. 

found plenty of articles talking about it, new and old, but they all had some extra steps or classes, nothing short and to the point.

I don't want to define more rules. I want to sanitize when I validate and in the same manner as validation.

The ideas from #42 lead me to using the Sanitizer package with Validator, a simple combination that allows me to do pretty much anything I want with my inputs.

 

 

 

 



William

Laravel 5 Artisan and Composer Autocomplete

I was tweetering and came across...

Ding! The bulb lights up and I say - let's get this for artisan - life will be easier. Less things to remember, faster access to the commands, why not?

Searching for Artisan Autocomplete

I found Eric Barnes had already written an article on using Oh My Zsh to auto complete artisan commands, neat! 

So I went over to the Oh My Zsh site, took a quick look, and found some nice plugins and themes. It was easy to get everything setup and customized to my taste.

Install Oh My Zsh

In your terminal window (iTerm 2 in my case or your remote ssh terminal) run the following command:

sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

Once installed you'll want to register the laravel5 and composer plugins.

Register the Autocomplete plugins for Artisan and Composer

Edit ~/.zshrc and modify your plugins to include laravel5 and composer:

plugins=(git laravel5 composer)

Once edited, restart your terminal or start a new shell:

zsh

Now you should get access to the short-hand commands and auto complete.

Test on a Laravel 5 project

Browse to one of your Laravel 5 projects and give the commands a try, type 'la5 ' then tab or 'composer ' then tab, you'll now get all the commands listed neatly.

Walla! Autocompletion, fancy stuff! 

Conclusion

I'm happy to not need to type 'php artisan' along with a dozen other commands already aliased. I'll spend the next day or so looking for more commands to alias and eventually wont be typing much in a terminal.

 

Homestead

sudo apt-get install zsh
sudo chsh -s $(which zsh) vagrant
sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

Handy Aliases

alias homestead="cd ~/Homestead ; vagrant ssh"
alias sql="mysql -uhomestead -psecret"

 


  0
William

Using Bootstrap 3 Less or SCSS with Elixir

I recently wrote an article about How-to setup Laravel 5, VueJs, and Bootstrap 3 and was asked:

My how-to didn't cover anything about that so here I will discuss how-to enable and modify Bootstrap 3 variables with Laravel 5 and Elixir.

Step 1: Create a project

In your terminal:

composer create-project --prefer-dist laravel/laravel .


Step 2: Install Gulp

Don't have npm? Install node.
In your terminal:

npm install --global gulp
npm install


Step 3: Less or SCSS?

The choice is yours. Bootstrap 3 is compiled with Less, not SCSS, but SCSS is included by default in Laravel 5s gulpfile.js - I prefer Less over SCSS.

Bootstrap 3 SCSS

Edit: resources/assets/sass/app.scss
Make it read:

@import "_variables.scss"
@import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap

Create: resources/assets/sass/_variables.scss
Define what variables you would like to adjust, ie:

$brand-primary: #000;

 

Bootstrap 3 Less

Install bootstrap:
In your terminal:

npm install bootstrap


Create: resources/assets/less/app.less
Make it read:

@import "node_modules/bootstrap/less/bootstrap.less";
@import "variables.less";

Create: resources/assets/less/variables.less
Define what variables you would like to adjust, ie:

@brand-primary: #000;

Edit: gulpfile.js
Change:

elixir(function(mix) {
    mix.sass('app.scss');
});

To:

elixir(function(mix) {
    mix.less('app.less');
});


Step 4: Compile


Now that you've enabled the less or scss versions you need to compile everything into app.css.
In your terminal:

gulp

 

Step 5: Link to your stylesheet

Edit your template and in the head tag add:

<link rel="stylesheet" href="{{ asset('css/app.css') }}">

Make some changes to check if your variables worked, like adding a class="text-primary" somewhere.

 

Step 6: Test

Make some changes to check if your variables worked, like adding a class="text-primary" somewhere.
I edited resources/views/weclome.blade.php and changed the title tag for a quick test:

<div class="title bg-primary">Laravel 5</div>

Load up your test server and see if it works.
 

php artisan serv

Load up your browser and you'll see:

Making Changes

I suggest looking at the less source and searching for the features you want to adjust.

Editing a navbar? You'll want to adjust colors and maybe the navbar.

If we look at navbar.less we'll see what it takes to build a Bootstrap 3 nav. Find what you want to edit - and make the changes.
For example making changes to the navbar-default:

.navbar-default {
  background-color: #fff;
  border-color: #ccc;
}

Ideally you'd define #fff and #ccc as @brand-white and @brand-grey in your variables.css but this is just a quick example.

Follow the same nesting, folders and file names and @import your own classes to adjust how Bootstrap is rendered. 

When using Less your @includes are after the Bootstrap include, when using SCSS they go before.

These steps work for SCSS as well, just adapt .less to .scss and the way you define variables.

Don't forget to compile your changes with gulp, you can use gulp watch and browserify to help as well.


Conclusion


Trying to modify Bootstrap 3 CSS is a huge pain. Trying to modify it with Less, plain and simple. Find what you want, copy/paste/edit/save, bam - you've made it look like what you want.

I cut my Bootstrap 3 template development time in half by switching to Less and compiling in my changes. I also was able to create highly optimized versions of Bootstrap that only utilized exactly what I needed with little effort.

I am not certain why Laravel 5 ships with Bootstrap 3 SCSS, it's a port - and not how Bootstrap is compiled. I would suggest using what Bootstrap 3 uses and that's Less. 

 


William

Laravel 5: Social Authentication with Socialite

The next step in todays project is to integrate Social Authentication. I don't need any user details, rather not deal with lost passwords, forms and the likes so Social Authenticaton is the best bet for me, it's fast and easy.

 

Using Laravels Socialite

I went over to the github page for socialite and copied its directions for installation, pretty simple. Of course I did have issues, copy/pasting their example didn't yeild a working authentication system, sure I authed with the Social Network but not Laravel, so gg.

 

Migrate Laravels Users table

If you dont have the Users table already migrated go ahead and do it now.

php artisan migrate


Install Socliate

composer require laravel/socialite

 

Add to config/app.php 

Register the provider

'providers' => [
    ...

    Laravel\Socialite\SocialiteServiceProvider::class,

],

And alias

'aliases' => [
   ...

   'Socialite' => Laravel\Socialite\Facades\Socialite::class,
],

 

Add to config/services.php

For each Social Network you want to auth with add its configuration, be sure to replace client_id and client_secret with your information:

'github' => [
    'client_id' => 'your-github-app-id',
    'client_secret' => 'your-github-app-secret',
    'redirect' => 'http://localhost:8000/auth/github/callback',
],

Replace the redirect with your url, unless you're like me and just testing locally.
Replace the github parts with the name of the driver.

 

Edit Http/Controllers/Auth/AuthController.php

We're replacing Laravels Auth system here, so if you want to keep local accounts, lost password and all that extra crap I suggest making a new controller. I don't want any of it, so it gets replaced with:

<?php

namespace App\Http\Controllers\Auth;

use Socialite;
use App\Http\Controllers\Controller;
use App\User;
use Auth;

class AuthController extends Controller
{
    /**
     * Redirect the user to the providers authentication page.
     *
     * @return Response
     */
    public function redirectToProvider($driver)
    {
        if($driverDoesntExist = $this->checkIfDriverExists($driver)){
          return $driverDoesntExist;
        }

        return Socialite::driver($driver)->redirect();

    }

    /**
     * Handle the providers call back.
     *
     * @return Response
     */
    public function handleProviderCallback($driver)
    {

        if($driverDoesntExist = $this->checkIfDriverExists($driver)){
          return $driverDoesntExist;
        }

        try {
            $user = Socialite::driver($driver)->user();
        } catch (Exception $e) {
            return redirect('/')->withErrors($e->getMessage());
        }

        Auth::login(User::firstOrCreate([
            'name'      => $user->name,
            'email'     => $user->email,
        ]), true);

        return redirect('/');
    }

    /**
     * Check if a driver exists, if it doesnt return a redirect, if it does return false.
     * 
     * @param  string $driver 
     * 
     * @return mixed
     */
    private function checkIfDriverExists($driver)
    {
      if(!config('services.'.$driver)){
        return redirect('/');
      }
      
      return false;
    }
}

 

Edit app/Http/routes.php

Add the routes to your controller:

Route::group(['middleware' => ['web']], function () {

  Route::get('auth/{driver}', 'Auth\[email protected]');
  Route::get('auth/{driver}/callback', 'Auth\[email protected]');

});

 

Test it!

If you've configured your Social Network to allow your url, and provided the right client_id and client_secret you should be all ready to test (or at least find out if you messed up), so boot up your test server and give it a shot.

php artisan serv

Browse to http://localhost:8000/auth/github and you should be redirected to login.

 

Conclusion

It's not hard to get Socialite setup with Laravel for Social Network Authenticate but if you actually wanted Authenticate you needed to do a few more steps then outlined in the Scoalite github pages, it's not hard - but not noted.

 



William

Quick Start Guide: Laravel 5, vue.js & Bootstrap 3

Vue.js has been getting a lot of attention lately so I've decided to give it another look in a new application I'm building. Vue.js is fast, small and easy to use, so why not give it a shot!

Since I'm a Laravel kinda guy I needed to configure vue with L5 and I always use Bootstrap, so that was needed as well. 

 

Did I say Laravel?

I did! So if you don't have a project, make one!

composer create-project --prefer-dist laravel/laravel .

 

Configure: package.json

Edit the package.json file in your projects folder and make it read:

{
  "private": true,
  "devDependencies": {
    "gulp": "^3.8.8"
  },
  "dependencies": {
    "bootstrap-sass": "^3.0.0",
    "laravel-elixir": "^4.0.0",
    "vue": "^1.0.18",
    "vue-resource": "^0.7.0"
  }
}

 

Install

Don't have npm? Install node.

npm install --global gulp
npm install

 

Edit: resources/assets/sass/app.scss

Uncomment the @import.

@import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap

 

Create: resources/assets/js/app.js

You'll be storing your vue.js, or any other js, here.

import Vue from 'vue'

new Vue({
  el: 'body',
  data: {
  message: 'Hello Vue World!'
  }
})

 

Append: gulpfile.js

Add the mix for scripts and set versioning up.

elixir(function(mix) {
    mix.sass('app.scss');
});

elixir(function(mix) {
    mix.browserify('app.js');
});

elixir(function(mix) {
    mix.version(['css/app.css', 'js/app.js']);
});

Gulp it

Compile all your crap into one css and one js file :D

gulp

 

Edit: resources/views/welcome.blade.php

Add the css in the <head></head> tag.

<link rel="stylesheet" href="{{ elixir('css/app.css') }}">

Add the js before the </body> tag

<script src="{{ elixir('js/app.js') }}"></script>

After the .title div add the div for your message.

<div class="title">Laravel 5</div>
<div id="app">
  @{{ message }}
</div>

 

Test it

php artisan serv

Load http://localhost:8000 and you'll see `Hello Vue World!`

Conclusion

5mins later you now have vue.js, bootstrap and laravel all configured. This guide won't go into any details because that's up to you to figure out. You now have a working base to develop as you desire, so enjoy!

 

 


William

Using Google Calendar as a Bill Reminder App

I've been using Google Calendar for years and some of the importat bills I want to be reminded about have their own monthly event. I get anice little notification before the bill is due ( a few days) and the day of. I just have one or two so managing so few reminders is quite easy - but these days I want to keep track of more of my bills.

Google Calendar Bill Reminder App

So I created the BillReminder app. The app connects to your Google Calendar and creates events with a bit of code to help the system track what they're for, when they're due, for how much and if you've paid.

You also get a break down of payments still owed and what type of payments, Credit Card, money orders, or however you define.

The app is simple to use, is totally free and we don't store much of your info, just enough to get you logged in and authenticated to edit a calendar created just for the app.

So if you have bills you need to remember with Google Calender give it a try.


  0