Get details about pivot column [Laravel 5] - php

I have 3 tables: Project, Group, User
and one relation pivot table: project_group with colmuns:
id
project_id
group_id
and pivot field user_id
I know how to take all Groups and Projects:
Project::find(1)->groups()->get();
groups() is belongToMany function inside Project Model.
Problem is I don't know how to get all users for particular project. I need to get project and all users names and ids for that project, any solution for this?
Thanks in advance

You can try on your Project.php model adding a pivot relationship
public function users() {
return $this->hasMany(App\User::class, 'project_group');
}
However this may be misleading as project_group should be a pivot table between the project table and the group table. user_id doesn't belong in there.
Create a second pivot table called group_user with group_id, user_id. Then you can use this on your Group.php model:
public function users() {
return $this->hasMany(App\User::class, 'group_user');
}
An example would then be:
$project = Project::find(1);
foreach($project->groups as $group) {
$users = $group->users; // Now you should have access to all the users for each group
}

Related

Laravel Accessor or HasManyThrough or something else?

I have four models: User, Product, Order, OrderItem
When a User adds an item to his cart, it creates a new Order and the item becomes a new OrderItem.
The tables:
users
id - integer
name - string
products
id - integer
name - string
orders
id - integer
user_id - integer
paid - boolean
order_items
order_id - integer
product_id - integer
quantity -integer
price - double
Relationships:
`Product` hasMany `OrderItem`
`OrderItem` belongsTo `Order`
`OrderItem` belongsTo `Product`
`Order` hasMany `OrderItem`
`User` hasMany `Order`
I want to be able to list all Product and under each, all the Users who bought that Product (Order whereNotNull 'paid').
Inversely, I'd like to show a User all the Products they have purchased.
I've tried taking it in steps with relationships. I can get {{ $product->orderItems }} to work, but not {{ $product->orderItems->orders }}
Laravel doesn't allow hasManyThrough relationships with a pivot table, which is essentially what order_items is, so that won't work.
Maybe I could do this with an Accessor with a join, but I can't wrap my head around it because I can't really set the relationship.
Maybe a custom Eloquent collection so every time I call Product it already has all the paid User and every time I call User the collection will already have all his Product?
Laravel has no native support for a direct relationship.
I've created a package for cases like this: https://github.com/staudenmeir/eloquent-has-many-deep
class Product extends Model
{
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function users()
{
return $this->hasManyDeep(
User::class,
['order_items', Order::class],
[null, null, 'id'],
[null, null, 'user_id']
)->whereNotNull('orders.paid');
}
}
$users = Product::find($id)->users;

Laravel, attach a pivot table value to Auth::user, what's missing/wrong?

I'm trying to have Auth::user()->building to return the building ID it is attached to. Right now it's returning Null. What am I doing wrong? Should I explicitly declare something somewhere? Thank you.
My tables :
users (id, name, etc.)
buildings (id, name)
building_user (building_id, user_id) has values ( 7 = building_id, 1 = user_id) with primary key on the two of them combined.
App\User
...
public function building(){
return $this->belongsTo('App\Building');
}
...
and
App\Building
...
public function users()
{
return $this->hasMany('App\User');
}
...
** EDIT **
I tried doing $building->users on view, and received the error
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'users.building_id' in 'where clause' (SQL: select * from `users` where `users`.`building_id` = 7 and `users`.`building_id` is not null)
Seems it's trying to not do a relational search. And searching the user table for a building_id column.
First of all you don't need a third table (building_user) unless you have something else in mind.
You need to make some modifications in your users table.
Add a field named building_id for storing the corresponding building_id the user belongs to.
Make a relation from building_id to reference id on buildings table.
Of course remove the third table, you don't need it if you've done the above steps.
Then Auth::user()->building()->id gives you the building id of the logged in user.
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many-inverse

Laravel, Eloquent: Fetch all entries from many-to-many relation

I have two tables linked by a pivot table (with a custom migration):
Interest table:
ID | label
Person table:
ID | label
PersonHasInterest table (custom migration):
InterestID | PersonID | notes
How can I get all records from the pivot table (with persons and interests joined in)? I don't want to get all interests of a person or all persons that have an interest but all entries (with joins) of the pivot table.
Even though Pivot extends Model it is not possible to call the standard model functions on a Pivot-object. Issue on Github.
What I came up is using the DB-Facade to execute a select statement, like so:
DB::table('person_has_interest')
->join('interest', 'person_has_interest.interest_id', '=', 'interest.id')
->join('person', 'person_has_interest.person_id', '=', 'person.id')
->get(); // further manipulation like select possible
Try to define a pivot model like this:
<?php
...
use Illuminate\Database\Eloquent\Relations\Pivot;
...
class PersonHasInterest extends Pivot
{
protected $table = '...'; // table name
}
Then use it: PersonHasInterest::all();

How can I model 2 different relationships between the same objects in Laravel 5's Eloquent?

Edit 4: Problem solved. The issue arising in edit 3 was only a data error.
Final answer: specifying foreign keys in the belongstomany relationships and clearing my PHP cache afterwards.
Edit 3: I've made the queries come out differently by specifying a foreign key in the belongsToMany relationship. However the query still doesn't return the results I need. Here is the generated query:
select `streams`.*, `followers`.`user_id` as `pivot_user_id`, `followers`.`stream_id` as `pivot_stream_id` from `streams` inner join `followers` on `streams`.`id` = `followers`.`stream_id` where `followers`.`user_id` =
Edit 2: The root problem is that User::following() and Stream::followers() are generating the exact same query despite being different sides of a many to many relationship.
Edit: I captured the query coming from User::following() and it looks like it's basing the query on a stream_id rather than the user_id, I'm not sure how to fix this.
select `users`.*, `followers`.`stream_id` as `pivot_stream_id`, `followers`.`user_id` as `pivot_user_id` from `users` inner join `followers` on `users`.`id` = `followers`.`user_id` where `followers`.`stream_id` = ?
I have a Users table, and A Streams table.
Each User has many Streams
Each Stream also has many Users(followers) in addition to the one User that owns it.
How Do I correctly set up this functionality in Eloquent? Right now I have a belongsToMany relationship in both models, setting up a many-to-many relationship on a pivot table. However this seems to conflict with the hasMany relationship in the User model and the belongsTo relationship in the Streams model that use the foreign key user_id on the Streams table.
To clarify, the final functionality I'm expecting is that a User object can return both a list of the Stream objects it owns, and the Stream objects it is following. A Stream object should be able to return both the one User object that owns it, and the multiple User objects that follow it.
However, right now, when I try to obtain a list of the streams a user is following, using the User::following() method, it returns the same results as the User::streams() method.
Here are how the tables are currently laid out:
Users
| id | name | email | password | token | created_at | updated_at |
|----|------|-------|----------|-------|------------|------------|
Streams
| id | name | user_id | created_at | updated_at |
|----|------|---------|------------|------------|
Pivot "followers"
| id | stream_id | user_id | created_at | updated_at |
|----|-----------|---------|------------|------------|
And here are the two model classes:
Stream
class Stream extends Model {
public function user() {
return $this->belongsTo(User::class);
}
public function followers() {
return $this->belongsToMany(User::class, 'followers');
}
}
User
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
protected $hidden = ['password', 'token'];
public function streams() {
return $this->hasMany(Stream::class);
}
public function following() {
return $this->belongsToMany(Stream::class, 'followers');
}
}

Pluck some rows of a table in laravel 4

I have subject table that contains
id name
and languages table that contains
id subject_id
and division table
id name
finally subject-division table (pivot table)
id subject_id division_id
now exist one-To-one relationship between subject table and languages table and many-To-many relationship between subject table and division table, i need to pluck only the subjects of subject table without the languages by using the relationship function
now i can get the languages only of the subject table of the relationship function In Division Model as the following
public function langSubject ()
{
return $this->belongsToMany('Subject' , 'subject_division','division_id','subject_id')
->join('lang_subject', 'lang_subject.subject_id' ,'=', 'subject.id')->get();
}
But till now I can't get the subjects only without the languages
Any Suggestions ?
You need to add the clause ->select('tableName1.fieldName1','tableName2.fieldName2','tableName3.fieldName3') to your statement after the join statement to get the tableName.fieldName and you may need to use leftJoin instead of join to get the results whether if there is a match or not.
Check out Eloquent relationship documentation -> sub headline "Querying Relationship Existence". There it mentions ::has method, which you could use in fashion
Division::has('subject.lang', '<', 1)->get()
Or at least that's the theory. Haven't had the need for it yet ;-)
It should be supported by Laravel 4 as well.

Categories