MikelMedina wrote a reply+100 XP
12h ago
for example? i don't understand :(
MikelMedina wrote a reply+100 XP
12h ago
I think I might be misunderstanding something here, so let me explain how I currently have it structured.
In my case, actualTrainer() is not a relationship in itself but a helper method built on top of the existing trainers() relationship in the User model. It basically does something like:
return $this->trainers()->wherePivot('active', true)->limit(1);
Then, on Microcycle, I have another helper actualTrainer() that simply delegates through the chain:
return $this->mesocycle->macrocycle->user->actualTrainer();
So what I end up doing is basically traversing the relationships step by step, but encapsulated inside these helpers to avoid repeating long chains everywhere.
Because of that, I was wondering if a package like has-many-deep would actually change the underlying behavior, or if it would just be a different way of expressing the same traversal.
My understanding is that even with a deep relationship, Laravel would still need to resolve the same underlying relations, unless everything is eager loaded or translated into a single SQL query with joins.
Am I understanding this correctly, or is there a more fundamental difference I’m missing in terms of how the data is actually retrieved or optimized?
I'm really confused :(
MikelMedina wrote a reply+100 XP
4d ago
like this:
public function microcycles()
{
return $this->belongsTo(Microcycle::class);
}
MikelMedina started a new conversation+100 XP
6d ago
I have a nested relationship chain in my app: WorkoutSession → Microcycle → Mesocycle → Macrocycle → User → actualTrainer.
I defined a helper method on the Microcycle model called actualTrainer() that traverses this chain internally:
public function actualTrainer() { return $this->mesocycle->macrocycle->user->actualTrainer()->first(); }
My question is: if I eager load all the relationships beforehand with load('mesocycle.macrocycle.user.actualTrainer'), will calling this helper method still use the already loaded relationships from memory? Or will it fire additional queries because it's traversing the chain through its own internal logic?
And more generally, does it make sense to define these kinds of helper methods on models when the relationships are this deeply nested, or is it better to always traverse the chain directly and rely on eager loading?
Thanks
MikelMedina wrote a reply+100 XP
1w ago
yees, thx for your help I really appreciate it :)
MikelMedina liked a comment+100 XP
1w ago
Yes, something like this looks fine for me. You should agree this is clean and simple.
MikelMedina wrote a reply+100 XP
1w ago
something like this looks better?: /** * Determine whether the user can view any models. */ public function viewAny(User $user, Mesocycle $mesocycle): bool { //verlo el entrenador o el user return $user->is($mesocycle->actualTrainer()) || $user->is($mesocycle->user()); }
/**
* Determine whether the user can view the model.
*/
public function view(User $user, Microcycle $microcycle): bool
{
return $user->is($microcycle->actualTrainer()) || $user->is($microcycle->user());
}
/**
* Determine whether the user can create models.
*/
public function create(User $user, User $actual_trainer): bool
{
return $user->is($actual_trainer);
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, User $actual_trainer): bool
{
return $user->is($actual_trainer);
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, User $actual_trainer): bool
{
return $user->is($actual_trainer);
}
MikelMedina wrote a reply+100 XP
1w ago
Yes, I realized that while I was writing the post, thx
MikelMedina liked a comment+100 XP
1w ago
It seems you just put in before logic that should be in actual create, viewAny, ...etc policies (you literally refer to them in your code), so I don't see the point here.
before is for cases that are completely out of a regular policy, for example "if a user is main admin then everything is allowed".
I'm also not sure if accessing route models directly through request() inside policies is considered good practice.
No, it's bad practice. Policies shouldn't know about your HTTP request, they just answer a question: can specific user do specific action or not?
Imagine your app is accessed other than via HTTP, let's say from console command. In that case calling request() in a policy is pointless.
Instead, you should apply a policy to a route with a middleware: https://laravel.com/docs/13.x/authorization#via-middleware
Laravel will take a user from a request and apply a policy to it.
Also I suggest comparing models using built-in method is():
if ($user->is($actualTrainer)) { ... }
Comparing integer ids is less readable and can be wrong when using multiple database connections. is() method handles it right way.
MikelMedina wrote a reply+100 XP
1w ago
"It seems you just put in before logic that should be in actual create, viewAny, ...etc policies (you literally refer to them in your code), so I don't see the point here."
is it okay even if i repeat the code in most of policies?
so, they should receive the extra information from the controller (or requests)?
MikelMedina started a new conversation+100 XP
1w ago
Hello everyone,
I'm building a REST API and while writing the before() method of one of my policies, I started wondering if this is actually a good use case for it or if I'm abusing the method.
This is the code:
public function before(User $user, string $ability)
{
if (in_array($ability, ['create', 'viewAny'])) {
$actualTrainerId = request()
->mesocycle
->macrocycle
->user
->actualTrainer?->first()?->id;
return $user->id == $actualTrainerId ? true : null;
}
if (in_array($ability, ['view', 'update', 'delete'])) {
$actualTrainerId = request()
->microcycle
->mesocycle
->macrocycle
->user
->actualTrainer?->first()?->id;
return $user->id == $actualTrainerId ? true : null;
}
return null;
}
The idea is:
- If the authenticated user is the current trainer of the client who owns the microcycle/mesocycle, the request should automatically pass authorization through the
before()method. - Otherwise, the authorization flow should continue to the corresponding policy ability method (
view,update, etc.).
So my question is:
Is this a correct/clean way to use the before() method in Laravel policies, or should this logic live somewhere else?
I'm also not sure if accessing route models directly through request() inside policies is considered good practice.
MikelMedina wrote a reply+100 XP
1w ago
exactly, i was looking for something similar and this post helped me a lot
MikelMedina liked a comment+100 XP
1w ago
It's always useful not only for topic starter but also for future generations that encounters same problems. Like me now.
MikelMedina liked a comment+100 XP
1mo ago
I’d personally add a separate timestamp column for recording “start” and “end” dates, just so users can set up training to start at a future date rather than the exact second a record just happens to be created in your database.
MikelMedina liked a comment+100 XP
1mo ago
Yes ,keep one users table & a self-referencing many-to-many pivot (e.g. trainer_client with trainer_id, client_id, start_date). In your User model:
php public function clients() { return $this->belongsToMany(self::class, 'trainer_client', 'trainer_id', 'client_id') ->withPivot('start_date'); }
public function trainers() { return $this->belongsToMany(self::class, 'trainer_client', 'client_id', 'trainer_id') ->withPivot('start_date'); }
This is perfectly fine.
MikelMedina liked a comment+100 XP
1mo ago
Yeah, your approach actually makes sense, using a pivot/intermediate table for trainer-client relationships is pretty standard, especially when you need extra fields like start date. Definitely not bad practice.
MikelMedina liked a comment+100 XP
1mo ago
@mikelmedina Yes, my advice is to use a single table for users. If some users can be trainers, then you could either have some sort of TrainerProfile model that is attached to those users, or just inherently determine if a user is a trainer via the existence of related models, e.g. if they have defined any workouts.
For the associations between users and trainers, I’d create a separate pivot table with two foreign keys, both pointing to a user record. One pointing to the trainer, and one pointing to the user that’s appointed that trainer. If a user can only appoint one trainer at a time, then you can make that foreign key unique.
If when a user selects a trainer, that appointment is temporary (i.e, has a start date and end date) then you can add those as columns on the pivot table. By doing this, you’d also get a historic record of what trainers a user has worked with, and vice versa.
MikelMedina wrote a reply+100 XP
1mo ago
For the initiation date, should I just use the default created_at timestamp that Laravel adds to the table?
For the end_date I'd create a new column , but for de initiation date? is it necessary if I already have de created_at?
MikelMedina wrote a reply+100 XP
2mos ago
For the initiation date, should I just use the default created_at timestamp that Laravel adds to the table?
Thanks :)
MikelMedina wrote a reply+100 XP
2mos ago
Even if the user can only have one trainer at time? There is no problem with it?
Thanks for your help :D
MikelMedina liked a comment+100 XP
2mos ago
Yes it is still worth it, and they do have AI dubbed lessons, and Spanish is one of those.
MikelMedina wrote a reply+100 XP
2mos ago
do you think is still worth it? I mean, to get a job... By the way, is any kind of support for spanish speakers?
MikelMedina started a new conversation+100 XP
2mos ago
I'm building a Laravel Sanctum API project for my portfolio. The project is a system where users and trainers exist, and it basically allows trainers to create workout plans for users. Without going too deep into the workout side of things, here's my situation:
I was planning to create a single users table to authenticate everyone with a bearer token, and create an intermediate table containing the FK of clients and the FK of trainers, along with additional data like start date, etc. The thing is, when I start defining the relationship methods between tables, I realize I can't use a belongsTo (for the client-trainer relationship) because I can't tell it which table to look in for the client — the clients table has no fields referencing any trainer ID. I think I don't have issues with the hasMany (trainer to clients), but I still need to store related data like the start date, which is why I think the intermediate table makes sense.
My question is (sorry for the long explanation): does what I'm planning make sense and could it be considered good practice (or at least not bad practice)? Or is it a mess?
pd: i've used AI to translate this, because I don't really domain English yet. Sorry :(