Laravel: Avoiding “Method Illuminate\View\View::__toString() must not throw an exception” errors

So you’ve flubbed something in your code and been presented with an unhelpful and seemingly unrelated error message about __toString() exceptions. This leads to a wild goose chase as you try to figure out what went wrong.

Error message.

It usually happens when you return an instance of \Illuminate\View\View from your controller method or route closure:

namespace App\Http\Controllers;

class HomeController extends Controller
{
    /**
     * @return \Illuminate\View\View
     */
    public function index()
    {
        return view('home');
    }
}

When rendering the view object Laravel simply casts it to a string, triggering a __toString() magic method. Any exceptions that are thrown by code inside __toString() (i.e. code in your template or view composer) get superseded by FatalErrorException, as seen in the screenshot above.

There’s an easy but somewhat obscure fix for this: simply return view(…)->render() instead so that __toString() is never called.

public function index()
{
    return view('home')->render();
}

Problem solved. Or found…

Laravel: Injecting authenticated user as a dependency

Warning! This post contains questionable use of Laravel’s service container along with some oft-criticized marker interfaces. Use at your own risk, or feel free to expand it into something more structurally sound.

The application I’m currently developing relies a lot on authentication and user types so I’m constantly having to fetch the authenticated user in my controllers, view composers, etc.

$customer = Auth::guard('customers')->user();
// or...
$customer = auth('customers')->user();

Not only is this tiresome, I became concerned about how much I was coupling the authentication layer with completely unrelated parts of the system (e.g. the view composers). It got me thinking about how the authenticated user is ultimately a dependency and that it should be injected *into* my code rather than being requested by it.

The Service Container

After a little more thought I hit upon a slightly dubious solution using Laravel’s service container. As you may know, Laravel does a little magic to automatically inject type-hinted dependencies into certain parts of your application. For example:

namespace App\Controllers;

use App\Services\StockRetriever;

class HomeController 
{
    protected $stocksRetriever;

    public function __construct(StocksRetriever $stocksRetriever)
    {
        $this->stocksRetriever = $stocksRetriever;
    }

    public function index()
    {
        return '
            <h1>Current market data</h1>
            ' . $this->stocksRetriever->asHtml() . '
        ';
    }
}

In this case we don’t need to manually instantiate HomeController with a $stocksRetriever – Laravel does this for us by looking at the type-hint (StocksRetriever) and automatically creating & injecting the relevant object.

That’s all well and good, but how does it help my scenario?

Well, another feature of Laravel’s is that it can do the same thing for an interface, so long as that interface is bound to a class.

Interface

namespace App\Contracts;

interface StocksRetrieverContract 
{
    public function asHtml();
}

Implementing class

namespace App\Services;

use App\Contracts\StocksRetrieverContract;

class StocksRetriever implements StocksRetrieverContract
{
    public function asHtml() 
    {
        echo '
            FTSE 100 - 6,0111.81<br>
            FTSE 250 - 16,354.33
        ';
    }
}

Interface -> class binding

app()->bind('App\Contracts\StocksRetrieverContract', '\App\Services\StocksRetriever');

// OR...

app()->bind('App\Contracts\StocksRetrieverContract', function () {
    return new \App\Services\StocksRetriever();
});

Note that the second argument of app()->bind(…) can be a string representing the name of the class or a closure returning the instantiated class. We’ll make use of this handy feature later!

Controller

namespace App\Controllers;

use App\Contracts\StocksRetrieverContract;

class HomeController 
{
    protected $stocksRetriever;

    public function __construct(StocksRetrieverContract $stocksRetriever)
    {
        $this->stocksRetriever = $stocksRetriever;
    }

    public function index()
    {
        return '
            <h1>Current market data</h1>
            ' . $this->stocksRetriever->asHtml() . '
        ';
    }
}

Notice how the constructor of HomeController now accepts StocksRetrieverContract (an interface) rather than StocksRetreiever (a class). The automatic injection of StocksRetriever still occurs because we previously bound the interface to the class using app()->bind(…)

The purpose of this is that we can quickly swap stock retriever implementations by making one single change in the binding.

More information about Laravel’s Service Container is available in the documentation.

Putting it to work

At this point you can probably see where I’m going with this. The interface -> implementation binding (specifically the use of a closure to provide the implementation) allows us to inject an authenticated user into any class that needs it.

The first thing we need to do is create an interface.

namespace App\Contracts;

interface CustomerContract
{
}

Empty interfaces are known as marker interfaces and they are rarely a good thing. Remember that warning above? 🙂

Second, we need to make sure our Customer class implements this new interface.

namespace App;

use App\Contracts\CustomerContract;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Customer extends Authenticatable implements CustomerContract
{
    // Customer implementation goes here...
}

Next we need to bind the interface and the class together. We’ll do this in the AppServiceProvider.

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
    }

    public function register()
    {
        $this->app->bind(
            'App\Contracts\CustomerContract',
            function ($app) {
                return $app['auth']->guard('customers')->user();
            }
        );        
    }
}

You can see we are fetching the authenticated customer within the bind closure. This may be an architectural issue as we are fetching a container binding (auth) from a service provider while registering a different binding!

At this point we are done with the set-up and can update our classes to suit. Here’s an example controller:

namespace App\Controllers;

use App\Contracts\CustomerContract;

class HomeController 
{
    protected $customer;

    public function __construct(CustomerContract $customer)
    {
        $this->customer = $customer;
    }

    public function index()
    {
        $name = !is_null($customer) ? $customer->name : 'customer';

        return '
            <h1>Hello ' . $name . '!</h1>
        ';
    }
}

The $customer parameter that Laravel automatically injects into the HomeController constructor is our authenticated customer user!

Laravel: Passing callables to Illuminate\Support\Collection’s max() and min() methods

As of Laravel v5.3 you will be able to pass callable parameters into the max() and min() methods of Laravel’s Collection class.

$maximumPriceInGbp = $products->max(function ($product) {
    return $product->price()->inCurrency('GBP')->value();
});

Previously it was only possible to pass key names into these methods. More complicated operations required a much-less elegant call to the reduce() method:

$maximumPriceInGbp = $products->reduce(function ($carry, $product) {
    $value = $product->price()->inCurrency('GBP')->value();
    return isset($carry) ? $value + $carry : $value;
});

This brings max() and min() in line with other Collection aggregate methods such as sum() and avg().

The GitHub pull request for this change is https://github.com/laravel/framework/pull/13999

Laravel: Simplified Eloquent Model ordering

Out of the box, Laravel doesn’t support default ordering of Eloquent models. For the most part this isn’t an issue as Eloquent’s syntax makes ordering trivially simple:

$posts = Post::orderBy('title', 'asc')->get();

Nevertheless, when dealing with a sort order that never changes we have a level of verbosity that we don’t really need. Can this be cleaned up any? Of course!

One common solution is to use a query scope to handle the ordering.

class Post extends Model
{
    public function scopeOrdered($query)
    {
        return $query->orderBy('title', 'asc');
    }
}

$posts = Post::ordered()->get();

There are two benefits to this approach:

1. It’s much cleaner and easier to remember, especially if all models adhere to this concept.

2. It abstracts the ordering implementation to within the model class.

So far so good, but ordering models every time we retrieve them makes that ordered() call somewhat redundant. What else can we do?

Enter global scopes and traits. From the Laravel documentation:

Global scopes allow you to add constraints to all queries for a given model.

That sounds perfect for ordering!

Within our class we will create an anonymous global scope in its initializing boot() method that will be used to specify the ordering:

class Post extends Model
{
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('ordering', function(Builder $builder) {
            $builder->orderBy('title', 'asc');
        });
    }
}

From this point on, posts will be automatically ordered for us! Even better, it’s possible to sidestep this ordering process by using the ‘withoutGlobalScope‘ method:

$posts = Post::withoutGlobalScope('ordering')->get();

So now we have our solution, but it involves quite a lot of code that we don’t want to repeat for every applicable model. Enter traits.

Laravel has a handy feature that allows traits on Eloquent models to be booted along with the model itself. It essentially looks at every imported trait, determines if it has a static method named ‘boot[TraitClassName]()‘ then calls it during the model’s own boot process. By harnessing this we can create an Ordered trait which assigns a global scope to a model when it is used.

For some extra flexibility we’ll tell it to look for a static sortOrder property on the model then use it to build the ordering clause.

trait Ordered
{
    public static function bootOrdered()
    {
        if (!isset(self::$sortOrder)) {
            return;
        }
        static::addGlobalScope('ordered', function(Builder $builder) {
            foreach (self::$sortOrder as $column => $direction) {
                $builder->orderBy($column, $direction);
            }
        });
    }
}

To make use of this within our models we need to import the trait and specify the property:

class Post extends Model
{
    use Ordered;

    public static $sortOrder = ['name' => 'asc'];
}

There we have it; a clean, reusable way of providing default ordering to our models!

Laravel: Extending the validator within a FormRequest class

Oftentimes I need to create a custom validation rule that is used in only one place, specifically within a FormRequest class.

Laravel’s Illuminate\Foundation\Http\FormRequest class allows you to resolve the validator instance in a subclass by way of the getValidatorInstance() method. One option is to override that, but the method itself provides an alternative:

protected function getValidatorInstance()
{
	$factory = $this->container->make(ValidationFactory::class);

	if (method_exists($this, 'validator')) {
		return $this->container->call([$this, 'validator'], compact('factory'));
	}

	return $factory->make(
		$this->all(), $this->container->call([$this, 'rules']), $this->messages(), $this->attributes()
	);
}

As you can see, getValidatorInstance() will look for the existence of a validator() method and will pass it the validation factory registered in the IoC container. The result of this call is subsequently returned as the validator instance.

This means we can customize the validator by defining the aforementioned validator() method in our subclass:

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Factory as ValidationFactory;

class ContactRequest extends Request
{
    /**
     * @param \Illuminate\Contracts\Validation\Factory $factory
     * @return \Illuminate\Contracts\Validation\Validator
     */
    public function validator(ValidationFactory $factory)
    {
        $factory->extend('david', function($attribute, $value, $parameters, $validator) {
            return strcasecmp($value, 'david') === 0;
        });

        return $factory->make(
            $this->all(),
            $this->container->call([$this, 'rules']),
            $this->messages(),
            $this->attributes()
        );
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|david',
            'email' => 'required|email'
        ];
    }

    /**
     * Set custom messages for validator errors.
     *
     * @return array
     */
    public function messages()
    {
        return [
            'name.david' => 'Your name isn\'t David!'
        ];
    }
}

Laravel: Simple authentication with multiple guards

If you have developed an application that leverages Laravel 5.2’s multiple auth guards, you may have had difficulty performing quick authentication checks. I’ll demonstrate using some code I recently worked on.

Here is the list of guards defined in config/auth.php:

'guards' => [
	'customers' => [
		'driver' => 'session',
		'provider' => 'customers'
	],
	'admins' => [
		'driver' => 'session',
		'provider' => 'admins'
	],
]

In this case we have two separate guards set up – customers and admins, each with their own user provider.

To target one of these guards when using the Auth facade or auth() function we must call an additional guard() method:

$user = Auth::guard('customers')->user()
// Or...
$user = auth()->guard('customers')->user()

This is great in theory, but what happens when we need to run an auth method regardless of the guard type? Take a look at this Blade template snippet:

@if (Auth::guard('customers')->check())
    Currently logged in as {{ Auth::guard('customers')->user()->name }}
@elseif (Auth::guard('admins')->check())
    Currently logged in as {{ Auth::guard('admins')->user()->name }}
@endif

Very repetitive and unwieldy, especially if we have many different guards.

My solution was to replace the AuthManager class stored in Laravel’s IoC container with my own custom version. This is done in App\Providers\AppServiceProvider:

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Rewire authentication manager to provide additional functionality.
     *
     * @return void
     */
    protected function registerAuthenticator()
    {
        $this->app->singleton('auth', function ($app) {
            $app['auth.loaded'] = true;

            return new \App\Auth\AuthManager($app);
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->registerAuthenticator();
    }
}

Notice how we return an instance of App\Auth\AuthManager from the auth binding. This class extends Illuminate\Auth\AuthManager which is the default binding. We can extend it as follows:

namespace App\Auth;

use Illuminate\Auth\AuthManager as IlluminateAuthManager;

class AuthManager extends IlluminateAuthManager
{
    /**
     * @var \Illuminate\Foundation\Auth\User
     */
    protected $user;

    /**
     * Determine if a user has authenticated.
     *
     * This overrides the magic call to self::guard()->check()
     *
     * @return boolean
     */
    public function check()
    {
        foreach ($this->guards as $guard => $settings) {
            if ($this->guard($guard)->check()) {
                return true;
            }
        }

        return false;
    }

    /**
     * Return the authenticated user.
     *
     * This overrides the magic call to self::guard()->user()
     *
     * @return boolean
     */
    public function user()
    {
        if (isset($this->user)) {
            return $this->user;
        }

        foreach ($this->guards as $guard => $settings) {
            if ($this->guard($guard)->check()) {
                $this->user = $this->guard($guard)->user();
                return $this->user;
            }
        }

        return null;
    }

    /**
     * Log the authenticated user out.
     *
     * This overrides the magic call to self::guard()->logout()
     *
     * @return void
     */
    public function logout()
    {
        foreach ($this->guards as $guard => $settings) {
            $this->guard($guard)->logout();
        }
    }
}

The default Illuminate\Auth\AuthManager class doesn’t actually define methods for check(), user(), logout(), etc. Instead it uses some __call() magic to forward these calls to the application’s default guard (specified in config/app.php along with the list of available guards). By creating our own methods in a custom version of the class, we override that magic functionality. In this case we simply loop around all available guards looking for the one that is authenticated.

This means we can now call Auth::check(), Auth::user() and Auth::logout() without specifying a guard:

@if (Auth::check())
    Currently logged in as  {{ Auth::user()->name }}
@endif

To target a particular guard, we just can just specify it in the usual way:

@if (Auth::guard('customers')->check())
    Currently logged in as customer {{ Auth::guard('customers')->user()->name }}
@endif