Question

I have Laravel's built in auth working. Users can register and login.

What I'd like to do is set the $id parameter for the UserController's show() method with the value from Auth::user()->id;

My thoughts behind this is, to not have to use id's in the routes.

I'm pretty new to OOP, and php in general, so I'm not sure how to tackle this.

Thanks in advance for any tips or help!

Was it helpful?

Solution

1st method

You can have a route with an optional user id:

Route::get('user/show/{id?}', 'UsersController@show')

If the show method of your controller doesn't get an id, it can use Auth::user() instead:

class UsersController extends BaseController {

    public function show($id = null) 
    {
        return View::make('userProfile')->with('user', $this->getCurrentUser($id));
    }

    public function getCurrentUser($id)
    {
        $this->currentUser = $id ? User::find($id) : Auth::user();
    }

}

Then in your view you will be able to always

{{ $user->name }}

2nd method

You could also have a BaseController which does that automatically for you using View::share():

class BaseController extends Controller {

    public function __construct()
    {
        parent::__construct();

        $this->shareUser();
    }

    public function shareUser($id = null)
    {
        View::share('user', $id ? User::find($id) : Auth::user());
    }

}

Then in your controller you don't need to pass the user:

class UsersController extends BaseController {

    public function show() 
    {
        return View::make('userProfile');
    }

    public function thisIsAMethodOverridingIt($id)
    {
        $this->shareUser($id);

        return View::make('userProfile');
    }

}

It would even better to have this provided by a Service, but you'll have to read about Service Providers and Facades to make it happen.

And you are still able to do that:

{{ $user->name }}

Because View::share() will send that variable to all your views.

3rd method

If you just need your user everywhere, use a global View::composer():

View::composer('*', function($view)
{
    $view->with('currentUserName', Auth::check() ? Auth::user()->firstname : '');
});

You can put this in your routes.php or, better create a file for this purpose, something like app/composers.php and load it in your app/start/global.php:

require app_path().'/composers.php';

As always, you can use it in your view, this way:

{{ $user->currentUserName }}

If you just need it for a couple of views, you can

View::composer(array('profile','dashboard'), function($view)
{
    $view->with('currentUserName', Auth::check() ? Auth::user()->firstname : '');
});

OTHER TIPS

This is actually a recent problem that I encountered while working on an API.

The way I handled it, was to introduce /me endpoints, so for example, you'd have:

Route::group(['before' => 'auth'], function() {
    Route::get('/user/show/{id}', 'UsersController@show');
    Route::get('/me', 'UsersController@show');
}

You'll notice that both routes point to the same code, but have different addresses. This means that you can simplify requests by using the /me convention, without having to duplicate code. You'll also notice that I enclosed these in a group which applies the auth filter. This basically just makes sure that the user is authed, and while it may not be required for the first one, it'd definitely be required for the second.

Then your show method would look like this:

public function show($id = false)
{
    $user = $this->getUserOrMe($id);

    return View::make('myview', ['user' => $user]);
}

This would require the below function:

private function getUserOrme($id)
{
    return $id !== false ? User::find($id) : Auth::user();
}

A controllers methods should be accessed independently of each other, meaning that once the User object is returned, all the relevant code for the current request has access to it. Storing the User object in a class property would just over engineering.

Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top