Ajaxify Your Laravel Application Automatically

You have a “nice little” Laravel app. You return views from your controllers, you redirect with a flash message when you’re done with something or when something goes wrong.

But sometimes you need to send Ajax requests to the server. And this time those views and redirects don’t make sense. You need JSON response. You create two different methods in your controller, one returns JSON and one returns View, because you also want the page to be loaded from server when user(or search engines) hit the url directly. And now things start to get messy.

What if you can write an HTTP Middleware which detects Ajax requests and converts responses to Ajax compatible responses? For example turn the response of this:

$user = ['name' => 'Usman', 'email' => '[email protected]'];
return View::make('user.show', $user);

into this
{"name": "Usman", "email": "[email protected]"}

or response of this

return Redirect::to('/')->with('error', 'User not found');

to this

{"error": "User not found"}
// with a 301 header

That’d be great, right? All this can be automated, I will show you how.

Let’s Code

We’ll create an HTTP middleware by running php artisan make:middleware Ajaxify
Or just create the class manually in (app/Http/Middleware/).

It’ll look like this:

<?php

namespace App\Http\Middleware;

use Closure;

class Ajaxify
{
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
}

Handle Method

Here we basically use couple of helper methods, which we’ll create next.
We check if we really need to alter the original response or not. Then we check if the response is successful (it has 20* status code) or not. If yes, we get all the the data passed to our view and then return the data as JSON response. It’s the key thing here.

If the response is not successful, we get all the flash data. If we have them then we return the flash data as a JSON response.

public function handle($request, Closure $next, $guard = null)
{
    // Get the original response
    $response = $next($request);

    if (! $this->shouldAjaxify($request, $response)) {
        return $response;
    }

    // A 20* response
    if ($response->isSuccessful()) {
        $originalContent = $response->getOriginalContent();
        // Get the data we passed to our view
        $data = $originalContent->getData();
        // Return the data passed to view as JSON response
        return response()->json($data);
    }

    // We don't have a successful response,
    //  we rather have a redirect like response

    $flashData = $this->getFlashData($request);
    if (! count($flashData)) {
        return $response;
    }
    // Return all the flash data as JSON
    return response()->json($flashData, $response->getStatusCode());
}

Helper Methods

Now we’ll add couple of protected methods in the class. First one is to help us determine if we should convert the response to JSON response or not.

protected function shouldAjaxify($request, $response)
{
    // If we already have a JSON response we don't need to do anything
    if ($response instanceof JsonResponse) {
        return false;
    }

    // If there is a server (status 50*) error, we won't do anything
    if ($response->isServerError()) {
        return false;
    }

    // It's not a View response
    if ($response->isSuccessful() && ! method_exists($response->getOriginalContent(), 'getData')) {
        return false;
    }

    // Now if it's an Ajax request or the clients wants a JSON response or we've
    //  a query string param 'ajaxify' then we'll Ajaxify, else we won't.
    return $request->ajax() || $request->wantsJson() || $request->exists('ajaxify');
}

So this method basically determines if we need to alter the response or just ignore it.

Now another helper method to get all flash data from the session:

protected function getFlashData($request)
{
    // Get all session data and convert the array to a Collection object
    $sessionData = collect($request->session()->all());
    // Filter only flash data from session data
    $flashedKeys = $request->session()->get('flash.new');
    $flashData = $sessionData->only($flashedKeys);
  
    // Delete flash data, as we've already used them
    $request->session()->forget($flashedKeys);
    return $flashData;
}

Finally

Register our middleware as a global middleware, by going to this file app/Http/Kernel.php.
in the web section we will add this:

protected $middlewareGroups = [
        'web' => [
            ...
            \App\Http\Middleware\Ajaxify::class,
        ],
        ...
    ];

Now you can try sending an Ajax request to your existing route or just try this in your browser: http://yourapp.dev?ajaxify

Caution:
Do not pass sensitive data to your view or to flash session. It will expose all data. Be careful when passing full model, use $hidden and $visible properties in your models to secure sensitive database fields.

Charisma – free, responsive, multiple skin admin template

Charisma is a full featured, free, premium quality, responsive, HTML5 admin template (or backend template) based on Bootstrap 3 from Twitter, it comes with 9 different themes to suit your style and application type.

Charisma helps you minimize the repeat work you have to do on you projects. You can re-use Charisma as a base or as a package for your admin panel. It’s free for personal and commercial use and you can use it in multiple sites.

I have put a lot of effort on this, I just expect a share on Twitter or Facebook from you as a “Thank you!”.

Charisma free, premium quality, responsive, multiple skin admin template.

View Live Demo

View on GitHub

Download

If you’re a PHP dev then you may like my projects Pixie Database Query Builder and Strana Pagination Library.

An alternative Download Link (if the Download button doesn’t work).

It is featured with many plugins and UI elements to ease your work. It works on all major browsers and optimizes itself for tablets and mobile phones. Above all it’s 100% FREE and open source. It is licensed under Apache License v2.0, respective licenses apply to all resources used. Issues and pull requests on GitHub are always welcome.

Features

  • 9 different themes
  • Fully responsive, optimized UI for tablets and mobile phones, see how it looks on different devices.
  • Based on Bootstrap 3.
  • Grandmother friendly, works on IE9+.
  • Commented code.
  • Custom product tour, see example.
  • Grid system, see example.
  • Charts, including, pie, stack, flot, realtime etc.
  • Data tables.
  • Widget boxes, collapsible, sortable, closable, see example.
  • Photo gallery, see example
  • Ajaxified menus.
  • Full calendar, monthly weekly, daily, with todo list.
  • Custom error page.
  • Auto active link detection and much more.

UI Elements

  • Custom Tooltip
  • Popover
  • Star Rating
  • Toggle Switch
  • Tag Boxes
  • Multiple File Upload
  • Dialog Box
  • Auto Growing Textarea
  • Ajax Loaders
  • Progress Bars
  • Alerts
  • Pop Notifications
  • Animations

Enjoy 🙂

Strana – Smart Pagination Library for PHP

A framework agnostic, smart pagination library for PHP. Just a few lines of code and fully functional pagination is ready.

Paginate your records with Strana. Strana will slice(limit and offset) these records, generate pagination links for you and reads page number from them, all automatically.

Features:

  • Built-in adapters for Doctrine, Eloquent (Laravel), Pixie, PHP Array and you can do it manually.
  • Readable syntax
  • Add Infinite Scroll with one line
  • It automatically detects which DBAL you are using.
  • Styles automatically with Twitter Bootstrap, Zurb Foundation and most of other CSS frameworks.

Check out the installation instructions and documentation on GitHub.

Install or View on GitHub

Screenshot:

Screenshot

Example

Basically Strana makes it very easy, like the code below:

$paginator = $strana->perPage(10)->make($records);

That’s basically it.

Full Usage Example

// Make sure you have Composer's autoload file included
require 'vendor/autoload.php';

$strana = new \Strana\Paginator();
$records = array(1, 2, 3, .... 100);
$paginator = $strana->perPage(10)->make($records);

// Loop paginated items
foreach ($paginator as $item) {
    echo $item['field_name'] . '<br>';
}

// Print pagination links
echo '<br><br>;' . $paginator;

There are some advanced options which are documented below. Sold? Lets install.

Pixie – A Database Query Builder for PHP

It took me few weeks to build Pixie, a lightweight, expressive, framework agnostic query builder for PHP, it can also be referred as a Database Abstraction Layer. Pixie supports MySQL, SQLite and PostgreSQL and it takes care of query sanitization, table prefixing and many other things with a unified API. At least PHP 5.3 is required.

It has some advanced features like:

  • Query Events
  • Nested Criteria
  • Sub Queries
  • Nested Queries
  • Multiple Database Connections.

Check out the installation instructions and documentation on GitHub.

Install or View on GitHub

Example

// Make sure you have Composer's autoload file included
require 'vendor/autoload.php';

// Create a connection, once only.
$config = array(
            'driver'    => 'mysql', // Db driver
            'host'      => 'localhost',
            'database'  => 'your-database',
            'username'  => 'root',
            'password'  => 'your-password',
            'charset'   => 'utf8', // Optional
            'collation' => 'utf8_unicode_ci', // Optional
            'prefix'    => 'cb_', // Table prefix, optional
        );

new \Pixie\Connection('mysql', $config, 'QB');

Simple Query:

The query below returns the row where id = 3, null if no rows.

$row = QB::table('my_table')->find(3);

Full Queries:

$query = QB::table('my_table')->where('name', '=', 'Sana');

// Get result
$query->get();

Query Events:

After the code below, every time a select query occurs on users table, it will add this where criteria, so banned users don’t get access.

QB::registerEvent('before-select', 'users', function($qb)
{
    $qb->where('status', '!=', 'banned');
});

There are many advanced features which are documented on GitHub project page. Sold? Lets install.

PHP Router in 140 Characters

This is a dimple(damn simple) URL routing script for PHP which is written in just 140 characters of code, so it fits within a tweet.

Its NOT a good router at all, don’t use it in a real application, its not exception handled either. I did it just for fun and to demonstrate the simplicity

So here’s the router code, and that’s all (seriously).

class R{
function a($r,callable $c){$this->r[$r]=$c;}
function e(){$s=$_SERVER;$i='PATH_INFO';$p=isset($s[$i])?$s[$i]:'/';$this->r[$p]();}
}

Fork on GitHub.

Usage

Create a file index.php in your server root and try this code

<?php
// The router code
class R{
function a($r,callable $c){$this->r[$r]=$c;}
function e(){$s=$_SERVER;$i='PATH_INFO';$p=isset($s[$i])?$s[$i]:'/';$this->r[$p]();}
}
//


// Create 
$router = new R();

// Add a route with a callback function
$router->a('/a', 'callbackFunction');

// Add a route with a closure
$router->a('/b', function(){
    echo 'Hello B';
});

// Add homepage route
$router->a('/', function(){
	echo 'Hello World';
});

// Add route with class method
$router->a('/c', [new Foo, 'bar']);
// Add multiple slashed route with class method
$router->a('/c/d', [new Foo, 'bar']);

// Execute the route
$router->e();

// Callback handlers
function callbackFunction(){
	echo 'Hello A';
}

class Foo{
	function bar(){
		echo 'Hello Bar';
	}
}

Now visit your server root http://localhost/index.php, http://localhost/index.php/a, http://localhost/index.php/b, http://localhost/index.php/c and http://localhost/index.php/c/d.

Or you may run built-in PHP server from the command line (in the same dir)

[code]
php -S localhost:8081
[/code]

and visit http://localhost:8081/index.php.

Runs on 5.4+. 140 chars idea is inspired by Fabien Potencier’s Twittee.