I have a platform where I have Users that are a Shop, they can place Orders, and I have Users that are Suppliers, they can view the placed Orders.
Now I'm running into some logic issue's, for example in my User class I woud like for the Supplier to be able to do this
Auth::user()->orders
But the User that is a shop should also be able to do this
Auth::user()->orders
I illustrated a bad example on how to do this here:
class User extends Authenticatable
{
public function orders()
{
return $this->hasMany(Order::class, 'created_by');
}
public function alsoHasOrders()
{
return $this->hasMany(Order::class, 'fulfilled_by');
}
}
There should be a better way to do this right?
For starters, I'm going to suggest you redesign your data model. Your User model is your Authenticator, and this is all it should be concerned with. It should not also be a shop or a supplier, or anything else. Supplier and Shop should be distinct models on their own which 'have' a User.
What you're doing at the moment violates S.O.L.I.D. as do most of the answers to your question here. Specifically O or Open for extension, closed for modification. For example, what if a user is a shop AND a supplier? What if later down the line you add a Distributer type as well? You have to go back to that model and add more if/else statements, more types of relations etc etc...
Instead, I would consider having roles of 'shop' and 'supplier' as well as distinct Shop and Supplier Models that have a User, which one or both of can be assigned to a user. You will likely already have the User object once authentication has been done, so after this point you can use a service retrieve Shop and Supplier information based on that users assigned roles.
Some quick sudo code of a basic implementation:
class ShopService
{
public function listOrders(User $user)
{
if ($user->hasRole('shop')) {
return Shop::with('orders')->where('user_id', $user->id)->get()
}
return null;
}
}
class SupplierService
{
public function listOrders(User $user)
{
if ($user->hasRole('supplier')) {
return Supplier::with('orders')->where('user_id', $user->id)->get()
}
return null;
}
}
This means you can very easily extend this by adding a 'distributer' Role and a DistributerService
However, If you are still determined to go down this route, at the very least I would suggest that you still have distinct Shop and Supplier models, that each extend the base User model, and then apply the relevant relations within each.
For example:
class User extends Authenticatable
{
... user stuff
}
class Shop extends User
{
public function orders()
{
return $this->hasMany(Order::class, 'created_by');
}
}
class Supplier extends User
{
public function orders()
{
return $this->hasMany(Order::class, 'fulfilled_by');
}
}
For authentication, look at using guard: https://laravel.com/docs/5.4/authentication
As far as for your user()->orders
idea, I would suggest user()->fulfilled()
and user()->supplied()