Laravel 4 eloquent pivot table - php

I have three tables: users, items and user_items. A user has many items and a item belongs to many users.
The tables:
Users
id
username
password
Items
id
name
equipable
User_items
id
user_id
item_id
equipped
The models:
class User extends Eloquent {
public function items()
{
return $this->belongsToMany('Item', 'user_items')
->withPivot('equipped');
}
}
class Item extends Eloquent {
public function users()
{
return $this->belongsToMany('User', 'user_items');
}
}
In the pivot (user_items) table I've a very important column named "equipped".
I've a form where users can equip, unequip and throw items. This form has a hidden field with the pivot (user_items) table row id. So, when a user tries to equip an item, the system checks if the item is equipable.
So, I want a object with the pivot data and the item data, based on item_id from the pivot table, I can send to the handler (where all logic is handled).
So what I've to do is to first access the pivot table and then access the item table.
Something like this (does not work):
$item = User::find(1)->items->pivot->find(1);
Is this possible to do?

You first have to include 'equipable' on your pivot call:
return $this->belongsToMany('User', 'user_items')
->withPivot('equipable');
Then you can ask Eloquent if your item is equipable or not:
$item = User::with('items')->get()->find(1)->items->find(2)->pivot->equipable;
Keep two things in mind:
Eloquent uses 'items' as a key internally, so that might interfere.
Whatever method you put before "get()" is part of the db query. Everything after "get()" is handled by PHP on the Object. The latter will be slower in most cases.

Related

Eloquent hasOneThrough relation

Currently my database setup looks like this:
Users table (User model):
id,
email
Discounts table (Coupon model)
code
amount
Now, I decided to create a pivot table, where I will store a discount value for a user. One user will have a single discount value. For this, I created PractitionerVoucher model with this table setup:
voucher_id
practitioner_id
Upon creating a Coupon record, I save the coupon_id (voucher_id in this case) and the user_id (practitioner_id in this case) values to PractitionerVoucher table. Now, my question is, how do I get the User record from the Coupon model? For example:
$coupon = Coupon::first();
$coupon->practitioner;
I tried to create hasOneThrough relation on Coupon model, but no luck so far. This is what I tried:
public function practitioner(){
return $this->hasOneThrough(User::class, PractitionerVoucher::class, 'practitioner_id', 'id');
}
Using this relation, I get no query results for the User model. This is how my database records look like:
Coupons table
PractitionerVoucher table:
What am I doing wrong here? Any help is appreciated.
What you are trying to achieve can be easily done by adding a coupon_id column on users table and defining a One-to-Many relationship between User and Coupon model - there's no need for a pivot table.
On User model
public function discount()
{
return $this->belongsTo(Coupon::class, 'coupon_id');
}
On Coupon model
public function users()
{
return $this->hasMany(User::class);
}
Then you can use the relationship
$coupon = Coupon::with('users')->first();
$coupon->users;

Laravel 5.4 Relationships between 3 tables

I am new in laravel, I already know how to join tables using the query builder. I just like to learn how to use relationships to avoid repetition of codes and to simplify it. I can join 2 tables, but I can't get the 3rd table.
I like to display employees assigned tasks information from the Tasks table, this table only has the project id that needs to be joined to the Projects table. Other employees can join in existing projects with other employees.
Employee model:
public function tasks()
{
return $this->hasMany('\App\Task', 'project_coder', 'id');
}
Task model:
public function projects()
{
return $this->hasMany('\App\Project', 'id', 'project_id');
}
Projects model:
public function belongsToTasks()
{
return $this->belongsToMany('\App\Task', 'project_id', 'id');
}
I can only get the IDS from Task model. the ID will be use to fetch the project info from project tables. Unfortunately I cant do that part.
Employees controller:
public function show($id)
{
$data = Employees::find($id);
return view('show-employee')->withInfo($data);
}
Is it good practice to use query builder rather than relationships?
UPDATE:
Employees table
{
"id":1,
"name": "Juan"
}
Tasks table
{
"id":1, // autoincrement and will not be use for linking to other tables.
"project_id": 1, //use to connect to project table
"project_coder": 1 // use to connect to employees table
}
Projects table
{
"id":1,
"name": "First Project"
}
To deal with this is best to create pivot table like employee_task
where table will have just two columns task_id and employee_id
then you can define in Task model
public function employees()
{
return $this->belongsToMany('\App\Employee', 'employee_task');
}
and Employee model
public function tasks()
{
return $this->belongsToMany('\App\Task', 'employee_task');
}
now you can see all employee tasks and rest of you relations work just fine
$data = Employees::find($id);
$data->tasks //you get all tasks assigned to this employee
$data->tasks()->first()->projects //you get all your projects for first task
$data->tasks()->first()->employees //all employees assigned to first task with this employee
Also recommend to you to lookup pivot tables, attach(), detach() and sync() functions. you can check it here : https://laravel.com/docs/5.7/eloquent-relationships#updating-many-to-many-relationships
UPDATE:
Ok I understand now what you are trying to do. You already have pivot table. I was little confused with your Project model which is not necessary.
You can remove your Project class if you have it just for this relation
and update your model relations as I wrote above. You don't need project_id and project_coder_id in this relation. Also change the column names to more conventional names like employee_id and task_id as I mentioned or whatever your table names are.
And you can rename employee_task pivot table name to your project table or you can rename it as well.
EDIT
When you use Project model for another data, you need to create 4th table as I mentioned above.
FINAL
drop project_coder column in Tasks table - unecessary column
create pivot table employees_task with employee_id,task_id
create mentioned relations with pivot table
I assume that Project hasMany() tasks and Task only belongsTo() one project. So need to create these relations as well.
Then you can use these relations like this:
$employee = Employee::find($id);
$task = Task::find($id);
$project = Project::find($id);
$employee->tasks //all tasks assigned to employee
$task->employees //all employees assigned to task
$task->project //project info assigned to task
$employee->tasks()->first()->project //project data from first task of employee
$project->tasks()->first()->employees //all employees assigned to first project task

How do I allow multiple many-to-many entries in laravel?

In my Laravel5 app I have users, tasks, and user_tasks. A user can complete a task multiple times:
User:
id
name
...
Task:
id
name
value
...
UserTask:
id
user_id
task_id
completed_on
If this were a normal many-to-many relationship I would have this function in the user class:
class User extends Model {
// ...
public function tasks(){
return $this->belongsToMany(Task::class, 'user_tasks', 'user_id', 'task_id');
}
}
But I believe this means that user_id/task_id is a primary key on user_tasks. How do I change the relationships between Task and User if I want duplicate user_id/task_id entries in the join table?
Second question, what if I want a list of all unique tasks a user has completed, regardless of how many time a user has completed them?
EDIT: Sorry, I wasn't trying to mean it would place a unique key on those columns. I meant that it seems like belongsToMany should be used in a situation where there is only one join between any pair of User and Task objects, so situations where user_id/task_id could be a unique key.

Laravel eloquent get specific user with his relations

Hello i am trying to get one user with his relationships. So one user form user table could have many items, so relationship is one to many.
Booth model
public function booths() {
return $this->hasMany('App\Booth');
}
User model
public function users() {
return $this->belongsTo('App\User');
}
I set foreign key from Booths table user_id is connected with Id from User table.
I try this query
$booth =User::findOrFail(83)->booths()->get();
But get all users. Also tried with with() but in that case i get all booths.
Change your code to
$user = User::with('booths')->findOrFail(83);

Laravel 5 - return only one field from relationship

have a relationship which returns rows from a pivot table.
However I just want to return a collection of the user ids from the table.
If I have it as current:
public function followers()
{
return $this->hasMany('App\Follower')->select(array('project_id', 'user_id'));
}
It will return the 2 fields, but if I just have the select with a single field:
public function followers()
{
return $this->hasMany('App\Follower')->select( 'user_id');
}
It returns an an empty object.
Any ideas?
I'm guessing this function is in your Project model. When modifying the select on a relationship, you must, at a minimum, select the fields needed to match the records together.
In this case, if this in on your Project model, if you don't select the project_id from the related table, Laravel can't match up the Follower objects with the correct Project objects, since Laravel won't have any idea which Project the Follower belongs to without the foreign key.

Categories