skip to Main Content

I’m trying to work out how I can achieve this with Laravel route and controller.
I’m having 3 tables as below:

user

  • id
  • name

company

  • id
  • name

company_user

  • id
  • user_id
  • company_id

So as you might have guessed I have the following models:

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens, HasFactory, Notifiable;

    public function companies(): BelongsToMany
    {
        return $this->belongsToMany(Company::class);
    }
}
class Company extends Model
{
    use HasFactory, SoftDeletes;

    public function users(): BelongsToMany
    {
        return $this->belongsToMany(User::class);
    }
}

The relationship is ManyToMany and it works all fine.

So I’m trying to achieve the following route:

Route::apiResource('company/user', CompanyUserController::class);

I know I can achieve such this by the following route easily:

Route::apiResource('company.user', CompanyUserController::class);

However what I need in my route is not to require to pass the company id as route parameter.

I want the company_id to be set automatically through payload from JWT token which I already have. So imagine we have company_id as 1 in JWT token payload and I want the user to go to this link:
GET /company/user
and controller would then list all users who belong to the company_id 1 which is grabbed from logged in user JWT token payload. I want the nested resource functionality without needing to pass the parent parameter in the route and instead grabbing it automatically from logged in user token.

I don’t want the route to be like /company/1/user.

I hope someone could help me achieve such these. This also needs to apply to all other controller methods automatically as in show, store, update etc.

Thanks guys.

2

Answers


  1. Chosen as BEST ANSWER

    Just to answer my own question, I ended up doing this route:

    Route::apiResource('company/user', CompanyUserController::class); As @Legoraccio suggested.

    Then I did the following in my CompanyUserController constructor to make sure I'm sanitising data before hitting the methods.

    public function __construct()
        {
            $payload = auth()->payload();
            $companyId = $payload->get('companyId');
            // making sure the selected company exists
            try {
                $this->company = Company::where('id', $companyId)->firstOrFail();
            } catch (ModelNotFoundException $exception) {
                abort(Response::HTTP_NOT_FOUND, "Unable to find company");
            }
    
            // making sure the logged in user is part of the selected company
            try {
                $this->company->users()->where('users.id', Auth::user()->id)->firstOrFail();
            } catch (ModelNotFoundException $exception) {
                abort(Response::HTTP_NOT_FOUND, "You don't belong to this company.");
            }
        }
    

  2. Avoid using apiResources for both company and user routes, define a custom route group instead:

    Route::group(['prefix' => 'company'], function(){
        Route::apiResource('user', CompanyUserController::class);
        ... Other company routes if you need ...
    });
    

    Now, in CompanyUserController you can read the correct company id from JWT Token and do your stuffs.

    The php artisan route:list result:

      GET|HEAD        company/user
      POST            company/user
      GET|HEAD        company/user/{user}
      PUT|PATCH       company/user/{user}
      DELETE          company/user/{user}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search