I want to get all users with courses through transaction table.
Here is my db structure
course
id | name | description | price
transactions
id | course_id | user_id | name | description | expires
users
id | username | email
http://laravel.io/bin/da08n
I have tried with joins but it returns the same user multiple times.
DB::table('transactions')->join('users', 'transactions.user_id', '=', 'users.id')->join('courses', 'transactions.course_id', '=', 'courses.id')->distinct()->get();
How can I achieve this with Eloquent or in an other way?
Well.
you have a table called transactions, and a table of courses. Now, each transaction is related to a course.
Pay Attention: You have one record in one table which is related to another one record in another table, this is called one-to-one relationship.
In laravel, you achieve this by using Model's relationship.
You have one model called 'Transaction', and another model which is called 'Courses".
You get, for example one record from courses table by using Cources::find($myId).
Now, if you want to get a record of transactions by relating it to courses table., you should do this (in Laravel):
In your translation model define a method called course:
public function course ()
{
$this->hasOne("course"); // course is the name of another model which should be related
}
And then you use it like this:
$result = Transaction::find($myCourseId)->course();
Though for your case, you want to get many records through matching one record of a table to the another record of another table. Well:
In Transaction model add the following method:
public function Users()
{
return $this->hasManyThrough('User', 'Course');
}
With the above method you should be able to get the Users through Course method based on transactions.
More on that, please visit:
http://laravel.com/docs/eloquent#relationships
Related
I have two models/tables: publisher and campaign.
Publisher
id | name
Campaign
id | name | PubID
I created a relationship to get the Publisher's campaigns.
$this->hasMany(Campaign::class, 'PubID'); /* In Publisher Model */
I believe the above line will help me to retrieve relevant campaigns, but I'm confused about the inverse relationship.
As you can see, there is no key campaign_id inside the publisher table. Would the below relationship be enough for the inverse?
return $this->belongsTo('App\Publisher'); /* In Campaign Model */
Can someone kindly guide me? I would appreciate it.
Yes, this is so called one to many relationship, which means one publisher has many campaigns. And the inverse is that a campaign belongs to a publisher.
So in order to get all the campaigns for the publisher you use:
Publisher::find($id)->campaigns;
In order to get what is the publisher of the campaign, you use:
Campaign::find($id)->publisher;
You don't need campaign_id inside the publisher table, that is known by the PubID in your campaign table.
You have two models and adding two foreign id. It is a many to many working. You just need add pivot table with campain_id and publiser_id
It’s a perfect example of many-to-many relationship: one publisher can belong to several campains, and one campains can have multiple publisher.
publishers
ID | NAME
campaigns
ID | NAME
campaign_publisher
campain_id | publisher_id
The final table in the list – campaign_publisher is called a “pivot” table, as mentioned in the topic title.
So, option 1:
class Campaign extends Model
{
/**
* The products that belong to the shop.
*/
public function publishers()
{
return $this->belongsToMany('App\Publisher');
}
}
So, option 2:
class Publisher extends Model
{
/**
* The shops that belong to the product.
*/
public function campaigns()
{
return $this->belongsToMany('App\Campaign');
}
}
You ,eed to specify the foreign key name in the belongsTo
return $this->belongsTo('App\Publisher','PubID');
Laravel Relationships
I have two tables. Table reports
report_id | user_id | item_id
and reports_messages
report_id | user_id | item_id | messages
I want when I delete report_id on reports all related rows which matching report_id in reports_messages to be deleted too.
In my ReportMessages Model I have this relation
public function reports(){
return $this->belongsTo('App\Report');
}
public function item(){
return $this->belongsTo('App\Item', 'item_id', 'id');
}
In Report model
public function reportedItem(){
return $this->belongsTo('App\Item');
}
public function user(){
return $this->hasOne('App\User', 'id', 'user_id');
}
So far I've tried this solution founded here on SO
public function destroy($report_id){
Report::destroy($report_id);
ReportMessages::find(1)->reports()->where('report_id',$report_id)->delete();
return redirect()->route('user.ports');
This deletes only in reports.. doesn't delete related report_id's in pivot table.
}
Laravel has the functions detach and attach to deal with pivot tables.
So you can do this to remove the record in the pivot table:
ReportMessages::find(1)->reports()->detach($report_id);
This will however not remove the row in the reports table because it could still be linked to another object.
Update:
So, I just noticed, you don't have pivot tables, you only have two models that are linked.
You don't have to load the reports() relation in your query to remove the ReportMessages, you can just do it like this:
Report::destroy($report_id);
ReportMessages::where('report_id',$report_id)->delete();
This will remove the report, and all corresponding reportmessages.
I'm know I'm late but the best option with this kind of relationship, it is best to define foreign keys to particular linking tables in your table " reports_messages" like below
>
$table->integer('report_id')->unsigned()->index();
$table->foreign('report_id')->references('id')->on('reports')->onDelete('cascade');
$table->integer('message_id')->unsigned()->index();
$table->foreign('message_id')->references('id')->on('messages')->onDelete('cascade');
When you do something like this, the pivot table data will be removed as long as either message or report is deleted from database without a need of detaching methods.
Best option in case message or report has relationship with other data,such that when data is deleted message should be deleted automatically, in this case we do not have to worry about detaching data again
To remove a many-to-many relationship record, use the detach method. The detach method will remove the appropriate record out of the intermediate table; however, both models will remain in the database:
ReportMessages::find(1)->reports()->detach($report_id);
official documentation is here
I have the following relation in my Users model
public function events($user_id)
{
return $this->find($user_id)->hasManyThrough('Event', 'Event_Member', 'user_id', 'id');
}
And the three tables
User
id|name|...
1 |bob |
2 |mike|
Event
id|name |location
1 |meeting|office
Event_Member
user_id|event_id|status
1 |1 |Owner
2 |1 |Guest
The hasManyThrough relationship gives me the information from the Event table, but I also need the status information from the pivot table, how can this be done?
What you have looks like a many-to-many relation rather than a has-many-through one. You have two tables connected through a pivot, not three parent-child-grandchild tables.
I would strongly suggest changing the relationship in both models. In the user model, it would look like this:
public function events()
{
return $this->belongsToMany('Event', 'event_members');
}
Note that a pivot table is typically called model1_model2 in alphabetical order - that is, event_user in this case. I assumed your pivot table is called event_members, if not just change it. Also note that I removed the user_id since the user model already knows which user it's using.
Then you can access pivot data easily, e.g. like this:
foreach ($user->events as $event) {
echo $event->pivot->status;
}
I have three Models (Organization, User, Visit) and 4 tables (organizations, users, organization_user, visits). I'm trying to get the accumulative total of user visits for an Organization.
Organization
------------
id,
name
User
---------
id,
name
Organization_User
----------------
id,
organization_id,
user_id
Visit
--------------
id,
user_id
views
Just to clarify, there is no Organization_User model, that is just the pivot table used by User and Organization:
$organization->belongsToMany('User');
$user->belongsToMany('Organization');
I could query all the user_ids from the pivot table by group_id, and then get all the visits for each user_id, but what's the more Eloquent approach?
A User hasMany Visits and a Visit belongsTo a User. A Visit doesn't belong to an Organization.
Solved it by using whereIn(). Basically with no change to my current relationship setup...to get accumulative views I did this:
$org = Organization::find($org_id);
return DB::table('visits')->whereIn('user_id', $org->users->modelKeys())->sum("views");
The modelKeys() returns all the user ids tied to that Organization. Then I get the sum of all the views for those users.
*Note it's also important to use Organization::find and not DB::table('organization') in order to maintain the Eloquent relationship. Otherwise $organization->users will give an error.
I think you might want a 'Has Many Through' relationship like so:
class Organization extends Model
{
public function visits()
{
return $this->hasManyThrough('App\Visit', 'App\User');
}
}
Then you could call count().
Laravel 5.1 doc
I have 3 classes - User, Business and BusinessRoleUser (and respective tables)
(user) id | first_name | last_name
(business) business_id | business_name
(business_role_user) user_id | business_id | role_id
I have combined the role of the user in the same table as their are multiple roles that user's can have towards a business i.e. admin, staff, etc. which are in the business_roles table.
I would like to access the Business Model through a logged in User to update fields i.e.
$business = User::find(Auth::id())->business();
$business->fill(Input::all());
$business->save();
At present in my User class I have the following (really each user will only be associated to one business):
public function business()
{
return $this->hasManyThrough('App\Business', 'App\BusinessRoleUser', 'business_id', 'user_id');
}
But If I do a simple dd(User::find(Auth::id())->business->business_name);
it throws an error
business name is undefined
It's not actually finding the business model associated to the user. I've looked at many examples of hasManyThrough but am failing to get this to work, appreciate the help!
(note user table uses id where as other tables use user_id, not sure if this is causing an issue)