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.

New York Trip and The Laravel Conference

I and John at Laracon

I work remotely for Vegan Cuts, which is based in Canada and I work from Bangladesh. As the team is distributed, Vegan Cuts arranges meetings every year in different countries. This time I was invited to visit New York :).

It was a long journey for me, Sylhet > Dhaka > Istanbul > New York City, 20+ hours just in flight. I took 1.5 day break in Istanbul and explored the city, amazing, I must say.

At JFK airport our co-founders came to receive me, it was really nice to see them in person. We explored many cool places in New York City together and had a lot of fun. I bought a MacBook 15-inch Retina from Apple Store, which made me an OSX user after being Ubuntu user for years. Finally I and our co-founder John, who is more of a friend attended Laracon, a developer/PHP conference with focus on Laravel framework. At the conference we met some cool developers. Overall, it was an amazing experience, full of fun.

If you’re interested you can view the photos:
New York Photos
Istanbul Photos

Don’t Fear Exceptions

If you’re not one of the few, you surely get scared once you see one of these:

Fatal error: Uncaught exception ‘Exception’ with message ‘Not found’ in /home/usman/www/test.php on line 27

Fatal error: Uncaught exception ‘UnexpectedValueException’ in /home/usman/www/test.php on line 27

When you see Red or Orange screen with Exception you fear like you’ve committed a sin and just go back to code to repent. Congrats, you’re the majority.

What if I told you that Exceptions are no sin, rather blessings of object oriented programming?
What if I told you that an Exception doesn’t just mean that your code is wrong?

Let me show you how.

For example code, I am using Laravel PHP framework. But the knowledge is not Laravel specific. This article assumes that you know basics of Exception and how to catch it.

An Example

I believe in practical example, so rather than preaching, I am showing you a real life example.

It is really common, when a you search for an entry in database, you check if this entry exists. If not then you show an error.

$person = Person::find($id);

if (! $person) {
    // Show message: Person not found
}

// Person found
return View::make('person.show', compact('person'));

You handle this problem with an if everywhere, why? Why don’t you just throw an exception when something doesn’t exist? Do just this:

$person = Person::findOrFail($id); // Will throw an exception if not found
return View::make('person.show', compact('person'));

In just one place catch this error. For Laravel, put this in your app/start/global.php:

App::error(function(\Illuminate\Database\Eloquent\ModelNotFoundException $e)
{
    return 'Entry not found'; // You can show 404, or do whatever you want
});

If you’re not using Laravel then catch the exception using try-catch when you boot your application.

Advantages of Using Exceptions

An Exception is just what is not expected. Be fearless to throw an Exception whenever you think something is not expected and the function/method/application should stop executing further.

One of the big advantages of using Exception over traditional redirect, die/exit is that you separate your business logic from your transport layer(ex, HTTP).

For example, you use a direct HTTP redirect when a form validation fails. Now what if the end user is not using a browser at all, he is using your mobile app which uses the same business logic with an API? What if you’re unit testing? What if you’re firing a background job with CLI? No HTTP at all, now how?

You’re right, Exception. Create a class ValidationException which extends \Exception. And whenever a validation fails:

    throw new ValidationException('Hey kid, you forgot your name?');

Now catch this Exception:
In case of usual HTTP use, do a redirect.
In case of API, set a status code with JSON message perhaps.
In case of CLI, just dump the error message.

In the Example section above, you’ve seen another advantage. How we made our code simple and DRY(Don’t Repeat Yourself).
There are many other advantages, I’m not going over everything, please check this article if you’re not convinced.

In the end

I ask you one thing, please do yourself a favor, make use of object oriented best practices(like utilizing Exception) where it fits, you won’t regret. Our PHP community has been late in this regard, but the revolution is coming.

Please feel free to share your thoughts.

If you’re a Laravel developer then you may also like my model self-validating package with Exception – DRYVal.

Laravel 4 Uses Lots of Static, Not True.

Most of the time developers blame Laravel for using too much static. This claim is not true in case of Laravel 4, lets dig in and discuss why and how.

What is static?

In PHP you call it like this Class::$property.

As the name suggests, it preserves the state. Static variables preserve their values across the lifetime of the running application(in our case request). In a class if a static property is declared it becomes the property of the CLASS itself, NOT the property of the instance(s) of the class.

Why is static considered bad?

Well, there are debates. One of main reasons is, you can’t (quite) Mock a static variable or method as its difficult to override statics because the state is preserved and no object/instance is used. This makes it really difficult to Test(Unit Test) an application as Mocking is a must needed thing to unit-test an application fully.

When you start unit-testing your application then you will realize why static dependencies are so bad. It becomes quite impossible to replace implementations during testing. So you end up creating lots of hacks just for maintaining testability.

How does Laravel static work?

Laravel 4 doesn’t actually use static rather it mimics the static calling behavior. When you call a static method, actually much more things happen behind the scene than it appears. Lets go through the life cycle of a static call.

As an example we’re calling View::make('hello').
You will see literally there is no class View under the \ namespace. Rather Laravel uses aliases, so when you look at app/config/app.php, you will see View is just an alias of Illuminate\Support\Facades\View. So you’re actually calling:

Illuminate\Support\Facades\View::make('hello');

When we go to Illuminate\Support\Facades\View under (vendor/laravel/framework/src) we see just this code:

class View extends Facade {

	/**
	 * Get the registered name of the component.
	 *
	 * @return string
	 */
	protected static function getFacadeAccessor() { return 'view'; }

}

It extends the base Facade class, and in both classes there is no static method make(). The magic happens on the base Facade class, where there is a magic method __callStatic. This is called PHP Overloading, whenever you call a static method and this class doesn’t have that method then __callStatic is called(like a 404 page) with the called method name(‘make’) as the first parameter and the called parameters’ array as second parameter(array(‘hello’)).

What __callStatic does basically here, it calls the IoC Container binding with the name ‘view’ and calls the (non-static)method (‘make’) within it. What IoC Container contains, a pure instance of the original View class, in an object oriented way (not a class oriented way). So we can re-write the View::make('hello') as

$app->make('view')->make('hello')

Conclusion

Now we know Laravel makes it super easy to call methods which makes it look like static but actually its not, so we can easily mock the original View class and get our tests pass. Using these facades for static call is just a way to access Laravel classes, you can write your entire app without using these facades(static calls). Do you find anything incorrect, do you have something better to share? Please write in the comments.

Filter Eloquent Results by Overriding in Laravel (v 3 & 4)

Now Laravel has this feature built-in

What is Eloquent?

Eloquent has been a really popular ORM in the PHP community lately, it was initially built for Laravel framework only. But since Laravel 4 all the components including Eloquent are built as Packages which may depend on other packages. These packages can be installed through Composer and can be browsed on Packagist. So what’s cool? Think of people out there who either don’t use Laravel or don’t use any framework at all. They might roll their own code or just whack a bunch of packages (like Eloquent) from Packagist together. If you use Laravel you can install and use various Symfony components/packages or any other package like Hybrid Auth with a simple command.

Lets Code

When we run queries from Eloquent sometimes we need to filter results from the very beginning. I will do it with an example to make understanding easy, but you are free to apply it however you want.

So sometimes we have users in database and admin can ban few of them for whatever reason, then lets assume you set users table’s status=0 for these users, now you have to filter (status=1) everywhere to restrict banned users from appearing (like login, profile view, edit send message etc.), and this can be real pain and not-a-cool-way as well. What if we can filter banned users right from our Eloquent model each time, so however we call users, User::all() or User::find(2) or User::where('username', 'like', '%usman%')->get() or whatever, banned users won’t appear in the results as long as you use this Eloquent model? Pretty cool yeah! Lets do it:

You have a User model which extends Eloquent, put this code into that class:

    /**
     * Overrides (Laravel or)Illuminate\Database\Eloquent\Model 's query()
     *
     * @return mixed
     */
    public function newQuery($excludeDeleted = true)
    {
        $query = parent::newQuery($excludeDeleted);
        // A much better way to restrict access to all banned (status = 0) users
        // from beginning (including search, profile views etc.), disabling them
        // to access anything even if they were logged in previously.

        $query-&gt;where('status', '!=', 0);
        return $query;
    }

That’s pretty much it, now you will never see banned users 🙂

What if We Need to Get Banned Users?

Well, above code will basically serve the purpose, but what if we need to get banned users (too) sometimes, like in the admin panel or if we want to check why the login was denied, is it because his status=0? Well you can do it. After this feature, your overall class will look as follows:

class User extends Eloquent
{
    protected static $_allowBannedUsers = false;

    /**
     * Overrides (Laravel or)Illuminate\Database\Eloquent\Model 's query()
     *
     * @return mixed
     */
    public function newQuery()
    {
        $query = parent::newQuery();
        // A much better way to restrict access to all banned (status = 0) users
        // from beginning (including search, profile views etc.), disabling them
        // to access anything even if they were logged in previously.

        if(! static::$_allowBannedUsers)
        {
            $query-&gt;where('status', '!=', 0);
        }else{
            // If its true then make it false so that banned users don't appear in next calls.
            static::$_allowBannedUsers = false;
        }
        return $query;
    }

    /**
     * @return User
     */
    public static function allowBannedUsers()
    {
        static::$_allowBannedUsers = true;
        return new static;
    }
}

The above code seems self explanatory. Now you can get banned users if needed just by chaining allowBannedUsers() method, for example:
User::allowBannedUsers()->all() or User::allowBannedUsers()->find(2) or User::allowBannedUsers()->where('username', 'like', '%usman%')->get()

Laravel 3?

If you are using Laravel 3 then please change the name of the method newQuery() to query() (without any parameters) like:

public function query()

and

$query = parent::query();

If you like this tirck then you may like my new project Pixie Database Query Builder. It has Query Events built-in for doing such tricks.

Conclusion

Feel free to do whatever you need instead of just restricting banned users. Also I would like to hear any better solution or if you think this solution has any pitfall. How do you solve this problem? Please comment below.

I will be glad if this helps you, please share this tutorial if you think it would help others.

Stay tuned for more Laravel tutorials.