1

I want an app to use a URL structure something like this:

  1. /account/johnsmith/photos
  2. /account/johnsmith/messages
  3. /account/johnsmith/settings
  4. /account/joebloggs/photos

So users may add multiple accounts and then the route group selects the account automatically.

Route::group(['middleware' => 'auth', 'prefix' => 'account/{username}'], function () {
  Route::get('/photos', 'PhotosController@index')->name('photos.index');
});

In the above example I can access the {username} parameter inside of PhotosController@index.

Is there a way to write some middleware that gets the account information automatically and it's accessible to all child routes in the group? Or am is this a bad way to try to build this?

2 Answers 2

5

This should be possible with route model binding.

Route::bind('username', function ($username) {
    return Account::findByUsername($username);
});

Note: The above code could be put in your route provider or within the route group its self.

When done, you will pass the model Account into your controller methods as the first argument and it will automatically be the one matching that username. Or a 404 if it does not exist.

// If {username} is 'bob', the Account object now references Bob's account.
public function index(Account $account) {}

See Laravel Docs Here

Sign up to request clarification or add additional context in comments.

2 Comments

Hi Joe, do you know if there is a way to couple this with service providers so that I can parse the values into the view automatically?
With service providers, no. But you could use view composers and accept in the Request object in the constructor. Then pluck the properties out of the request ($request->route->parameters I believe, but not 100% sure). Although personally I probably wouldn't do this as I'm not a fan of "global" variables.
1

Yes, if you need to perform a operation before all your controller methods get the request o propagate some common data you should use Laravel middlewares. It will not only centralise your logic as well as make your controller code neat.

Even laravel sometimes want you to do that.

In previous versions of Laravel, you could access session variables or the authenticated user in your controller's constructor. This was never intended to be an explicit feature of the framework. In Laravel 5.3, you can't access the session or authenticated user in your controller's constructor because the middleware has not run yet.

As an alternative, you may define a Closure based middleware directly in your controller's constructor. Before using this feature, make sure that your application is running Laravel 5.3.4 or above

So you can either write a middleware to calculate account details and if you are using the laravel version 5.3.4 and above you can directly assign it to the controller properties in constructor using closure based middlewares.

Like this:

class ProjectController extends Controller
{
    /**
     * All of the current user's account details 
     */
    protected $accountDetails;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware(function ($request, $next) {
            $this->accountDetails= Auth::user()->accountDetails;

            return $next($request);
        });
    }
}

Hope this would help.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.