October 15, 2015 15:26

By default, Laravel logs users in with their email and password. In some cases you might want them to use a username instead. This is pretty simple, just set the $username property on the AuthController class:

class AuthController extends Controller
{
    ...
    protected $username = 'username';
}

The AuthController uses the AuthenticatesUsers trait, which checks if the $username property is set, and if not, defaults to 'email'

If you want users to have the choice of logging in with email or username, it's a little more complex. You'll have to override the postLogin method in your controller.

class AuthController extends Controller
{
    use AuthenticatesAndRegistersUsers {
        AuthenticatesAndRegistersUsers::postLogin as laravelPostLogin;
    }

    /**
     * Login with email or username
     *
     * @param  Request  $request
     */
    public function postLogin(Request $request)
    {
        $field = filter_var($request->input('email'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
        $request->merge([$field => $request->input('email')]);
        $this->username = $field;

        return self::laravelPostLogin($request);
    }
}

To break that code down, first we use the trait, but we want to rename the original postLogin method so that we can use it later.

Then inside our postLogin method, we check if the email field that we're receiving is an email address or not. This assumes that you have some restrictions on usernames, e.g. that they're alphanumeric, or at the very least, don't allow the @ character.

Then it sets the $username attribute as either 'email' or 'username'.

Finally, it calls the laravelPostLogin method, which we had reassigned earlier, so that Laravel continues the login as before. That way we don't have to rewrite any of the logic in that original method.

Laravel, PHP

October 13, 2015 19:36

I actually thought of this while answering a question on StackOverflow

When querying sums of columns, I typically do something like this:

$query = $account->transactions()
    ->select(\DB::raw('SUM(amount) AS total'))
    ->first();
$total = $query->total;

Here's another way to accomplish the same thing. Of course if you end up fetching thousands of rows you'll probably want to just let MySQL do the math for you, but it's way easier to read and cleaner.

$amounts = $account->transactions()->lists('amount');
$total = $amounts->sum();

Laravel, MySQL, PHP

September 17, 2015 14:32

In Laravel, redirecting the user to one URL after logging in and another after registering (such as a welcome page) is very simple.

First, inside your AuthController, set the post-login URL as the default:

protected $redirectTo = '/url-after-login';

and then inside the create function, override it to the post-registration URL

protected function create(array $data)
{
    $this->redirectTo = '/url-after-register';

    return User::create([...]);
}

Laravel, PHP

September 2, 2015 22:58

I've uploaded most of my photos from Korea. Some of my favorites below

Photography, Travel

August 31, 2015 11:10

Router binding in Laravel used in conjunction with middleware makes model management really easy. No more passing in IDs, loading models, and checking permissions for every controller method.

This example makes use of my ślimak slugged models package

class Album extends SluggedModel
{
    protected $appends = ['url'];

    /**
     * @return string
     */
    public function getUrlAttribute()
    {
        return '/albums/' . $this->slug;
    }
}

In app/Http/routes.php

Route::get('albums/{album}', 'AlbumController@show');
Route::get('albums/{album}/edit', 'AlbumController@edit');

In app/Providers/RouteServiceProvider.php

$router->bind('album', function ($slug) {
    return \App\Album::findBySlug($slug);
});

Finally, in your controller:

use App\Album;

class AlbumController extends Controller
{
    public function show(Album $album)
    {
        return view('albums.show')
            ->with('album', $album);
    }
}

Now when linking to your album's permalink in Blade, you can simply link to {{ $album->url }}. To link to the edit URL, just link to {{ $album->url }}/edit

This gets even more useful when you start to add middleware. For example, I can check to make sure only the album's owner, and admins, have permission to edit the album.

class Owner {
    public function handle($request, Closure $next, $resource)
    {
        $user = \Auth::user();

        if ($request->{$resource} && $request->{$resource}->user_id != $user->id && ! $user->is_admin) {
            abort(403);
        }

        return $next($request);
    }
}

Then if I add this middleware to the controller it takes care of that protection easily:

class AlbumController extends Controller
{
    public function edit(Album $album)
    {
        $this->middleware('owner:album');

        return view('albums.edit')
            ->with('album', $album);
    }
}

Laravel, PHP