How to join tables in Laravel? - php

I am new to Laravel, I have a question regarding Eloquent:
This is my DB table structure:
users
- id
- user_id
- username
- name
- email
- password
- email_verified_at
- remember_tok
- created_at
- updated_at
challenges
- id
- challenge_id
- category_id
- hashtag
- title
- description
- duration
- link
- created_at
- updated_at
- user_id
user_challenges
- user_id
- challenge_id
- duration
- created_at
- updated_at
What I want to achieve is to display the user's challenges, so for example, if a user joins a challenge in the user dashboard I want to display the challenges that he joined, but also the challenges that the user has created (if he has created any);
Models\User.php
class User extends Authenticatable
{
use Notifiable;
public function challenges() {
return $this->hasMany(Challenge::class, 'user_id');
}
public function userChallenges() {
return $this->hasMany(UserChallenge::class, 'user_id');
}
}
Models\Challenge.php
class Challenge extends Model
{
public function user () {
return $this->belongsTo(User::class, 'user_id');
}
}
Models\UserChallenge.php
class UserChallenge extends Model
{
public function user () {
return $this->belongsTo(User::class, 'user_id');
}
}
This is what I have in my Home Controller:
App\Http\Controllers\HomeController.php
class HomeController extends Controller
{
public function index()
{
$user_id = auth()->id();
$user = User::find($user_id);
return view('home')
->with('challenges', $user->challenges)
->with('userChallenges', $user->userChallenges);
}
}
This is what I get currently for the "Joined Challenges" in My Dashboard - but how can I join the tables when returning the view so I can also get the challenge hashtag title? Like I get above under "My Challenges" section?
Dashboard
UPDATE:
What should I add to my database so I can count the number of users that have joined the challenge?

To get user created challenges, I believe you are already doing it correctly.
And to get user joined challenges. You almost get it right with your pivot table. You can have look on many-to-many relationship in laravel documentation.
These are the sample code to retrieve challenges created by a user and challenges joined by a user. These code should reside in your User Model, you should keep the model.
public function created_challenges()
{
return $this->hasMany(Challenge::class,'user_id','id');
}
public function joined_challenges()
{
return $this->belongsToMany(Challenges::class, 'user_challenges', 'user_id', 'challenges_id');
}
Once you get the relationship working right, you can simply use the collection returned from the relationship. Once you pass the $user->joined_challenges to your view, you can do as below
#foreach ($joined_challenges as $challenge)
<p>{{$challenge->hashtag}}</p>
<p>{{$challenge->title}}</p>
#endforeach
Let me know it this works, cheers! ;)

Related

Laravel accessing BelongsTo Model of a HasMany relationship

Basically I have three models , Wedding , invites , and users. Weddings has invites and invites has users ( keeping in mind that user can belong to multiple invites ). I want to access $wedding->users directly.
Wedding.php
class Wedding extends Model
{
public function invites()
{
return $this->hasMany(Invite::class);
}
...
Invites.php
class Invite extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
...
Tables:
Wedding
- id
- name
Invite
- invite_date
- wedding_id
- user_id
User
- id
- name
- email
And i want to access retrieve users directly , using $wedding->users
What's the relationship between Wedding and users?
It's a BelongsToMany relationship:
public function users() {
return $this->belongsToMany(User::class, 'invites');
}
Add this method to your Widding class
public function users()
{
return $this->hasManyThrough('App\User', 'App\Invite');
}
for more about hasManyThrough see the documentation.

LARAVEL ELOQUENT - I want to add column from user table to a relation table

I am not much familiar with eloquent orm in laravel
I have 3 tables they are
-- leads
|
Lead_appointments
and users table
since lead_appointments belongs to leads references id on leads by lead_id
the leads_appointments has a column called created_by with user's id in it
I am trying to query user's name and email along with the result as another column when query using eloquent
Lead Model
class Leads extends Model
{
public function appointments()
{
return $this->hasMany('App\Models\LeadsAppointments', 'lead_id');
}
}
My eloquent query in controller
return $this->lead->with('appointments')->find($id);
the result is like this
In under appointments i also want user email and name along with created by in it
But I couldn't figure it out
Add a relation to LeadAppointment model like this:
class LeadAppointment extends Model
{
public function users()
{
return $this->belongsTo('App\Models\User', 'created_by');
}
}
and change leads model like this:
class Leads extends Model
{
public function appointments()
{
return $this->hasMany('App\Models\LeadsAppointments', 'lead_id')->with('users');
}
}

Laravel - How to chain Eloquent relationship - Eager Loading

I'm using Laravel 5.4, Laravel Roles from here and Eloquent relationships.
I'm trying to retrieve the users of a company along with their roles.
User::find(1)->roles gets me the user's roles whose id =1
Company::find(1)->users gets me all the users that belongs to the company whose id =1 (without the roles of users).
Company::find(1)->users->roles returns an error Property [roles] does not exist on this collection instance.
Questions
Is it possible to do what I want to do ?
If so, how should I do it ?
User.php
class User extends Authenticatable
{
use HasRoleAndPermission;
public function company()
{
return $this->belongsTo('App\Company');
}
public function user()
{
return $this->belongsTo(User::class);
}
}
HasRoleAndPermission.php
trait HasRoleAndPermission
{
public function roles()
{
return $this->belongsToMany(config('roles.models.role'));
}
}
Company.php
class Company extends Model
{
public function users() {
return $this->hasMany('App\User');
}
}
$company = Company::with('users.roles')->find(1);
Will load all the users, and all the roles for each user.
Update
According to your comment, you don't want the company data. Just users and roles Using eager loading and relationship existence.
$users = User::with('roles')
->whereHas('company' => function($query){
$query->where('name', '=', 'company'); //If you don't have the company ID
})->get();
Without relationship existence
$users = User::where('company_id', 1)->with('roles')->get();
1 company has many users.
1 users has many roles.
You are trying to get the roles of a collection of users (the property only exists for one user) thus, the property doesn't exists for the collection.
If you want to get all the roles of all users in the company, you might try the above code:
$roles = [];
Company::find(1)->users->foreach(function($user) {
$roles = array_merge($roles, $user->roles);
});
--------- edit ---------
For eager loading the roles of users, you must use with, as suggested by #Ohgodwhy, but I'd refactor a little:
$users = User::with('roles')->where('company_id', $companyId)->get();
Now you have the array of users eager loading their roles. You still can't access directly $users->roles, you must first get a user, only then get its roles.

Models relate in laravel 4

I hope you are well, I need your help, I am working with Laravel and I need to relate information, I have the User, TypeCost and CostCenter models where relationships are:
user:
hasMany ('TypeCost');
belongsTo ('CostCenter', 'id');
TypeCost:
belongsTo ('User');
CostCenter:
hasMany ('User');
I have my view index in the TypeCost module, there are loads information from the cost of each user, I need is that if the user logged belongs to CostCenter one simply show records of users who belong in CostCenter 1 and so CostCenter for the 2, 3, etc.
This is my Index method that is responsible for displaying the list of expenses:
public function index ()
{
$ type_costs = TypeCost :: paginate ();
return View :: make ('type_costs.index' compact ('type_costs'));
}
//for user model
public function costcenter()
{
$this->belongsTo('CostCenter');
}
//for costcenter model
public function users()
{
$this->hasMany('User');
}
//controller function
public function index ()
{
$cost_centers = Auth::user()->costcenter;
$cost_users = $cost_centers->users;
return View::make ('type_costs.index', compact ('cost_users'));
}
it will return list of users that belongs to CostCenter of logged user.
If the field of costcenter_id in user table is nullable, u can add some validation on controller.

Laravel Object queries - 3 tables

I have three tables like this:
**Users**
id
**Posts**
id
user_id
**Favorites**
id
user_id
post_id
Currently, I made it so when I query my posts for display, it pulls all the related user data who created the post with that row which is great! But what I'm trying to do now is also add to see if the user Authorized (Logged in) has favorited the post (row) so I can display to that they already favorited it. I don't want to re-query for every post (i think its called the N+1 problem?). I'm using Laravel4
Post model
class Post extends Eloquent{
public function user(){
return $this->belongsTo('User');
}
User model
public function posts(){
return $this->hasMany('Post');
}
PostsController
public function index()
{
$posts = Post::with('user')->paginate(25);
return View::make('index', compact('posts'));
}
Step 1. Add favorites relationship in Post model.
public function favorites() {
return $this->hasMany('Favorite');
}
When querying the Model.
$auth_user_id = Auth::user()->id;
$posts = Post::with(array('user', 'favorites' => function($query) use ($auth_user_id){
$query->where('user_id', '=', $auth_user_id);
}))->get();
For more information refer to the eager load constraints,
http://laravel.com/docs/eloquent#eager-loading
Adding a many-to-many relationship using the favorites table as pivot would be one approach.
Add favorites relationship in User model:
public function favorites() {
return $this->belongsToMany('Post', 'favorites');
}
You should then be able to get all favorites by simply accessing
Auth::user()->favorites
To find whether the current post is a favorite, use
$isFavorite = Auth::user()->favorites->has($post->id);

Categories