Hey from my website I'm sending multiple notifications to users, I'm assigning users to a team and then I assign this team to the notifications table.
However when I do SiteNotification::find(1)->notifications() then I get the name of the team, however, I was looking to get the user model and all the details related to that. Is there an easy way to obtain this using Laravel Eloquent relationships?
My DB model and Eloquent model are below;
DB tables;
User
id | username | email
Teams
id | name |
Team Members
team_id | user_id
Site Notifications
site_notification_id | team_id
Model Here:
class SiteNotification extends Model {
public function notifications()
{
return $this->belongsToMany(Team::class, 'site_check_notifications', 'site_check_id', 'team_id');
}
}
Update:
I've tried updating the Team Model as follows;
class Team extends Model
{
public function users()
{
return $this->hasManyThrough(
User::class,
TeamMember::class,
'team_id',
'id'
);
}
}
However this throws an error as follows when running this;
$site = Site::find(1);
foreach( $site->notifications as $notification) {
dd($notification->users);
}
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'team_members.id' in 'on clause' (SQL: select `users`.*, `team_members`.`team_id` from `users` inner join `team_members` on `team_members`.`id` = `users`.`id` where `team_members`.`team_id` = 4)
Any ideas what I'm doing wrong??
I've found a solution which has meant that I do not need to amend my existing database structure and I've found the correct relationship to use.
public function users()
{
return $this->belongsToMany(
User::class,
'team_members',
'team_id',
'user_id'
);
}
Now I can do Site::find(1)->users->pluck('email')
You have to change the model structure... This is how I would have reached your goal... Take it as a "working solution", maybe not the best!
First of all, database. You should have these tables, there is no need to
users => users table
teams => teams table
team_user => pivot table n:n
team_site_notification => pivot table n:n
site_notifications => notifications table
user_site_notification => pivot table n:n
Then you create the related models relations
public class User {
// [...]
public function teams() {
return $this->belongsToMany(Team::class)
}
public function notifications() {
return $this->belongsToMany(SiteNotification::class)
}
}
public class Team {
// [...]
public function users() {
return $this->belongsToMany(User::class)
}
public function notifications() {
return $this->belongsToMany(SiteNotification::class)
}
}
public class SiteNotification {
// [...]
public function teams() {
return $this->belongsToMany(Team::class)
}
public function users() {
return $this->belongsToMany(User::class)
}
}
In your controller, when you create the SiteNotification model, you'll have to associate also the users. For example
public function store(Request $request) {
// Do your stuff
$team = Team::findOrFail($request->your_team_id);
$notification = Notification::create($data);
$notification->teams()->associate($request->your_team_id);
// Retrieve the users from the team... Maybe not everyone should receive a notification
$team->users()->whereIn('id', $user_ids)->get()->pluck('id')
$notification->users()->associate($ids);
}
When you want to get your users list you simple retrive the associated users in this way:
dd($notification->users);
// [ User:{id: 1, '...'}, User:{id: 2}, User:{id: 7} ]
Hope this is what you're looking for!
Related
I need advice about my model relationships,
Logic
Group has many users
Group has many admins
User has many groups (as user)
User has many groups (as admin)
Database Structure
Group Table
User Table
Group_Users table (save id of user and id of group)
Group_Admins table (save id of user and id of group)
Relationship Code
User model
public function groupsUser() {
return $this->hasMany(GroupUser::class);
}
public function groupsAdmin() {
return $this->hasMany(GroupAdmin::class);
}
Group model
public function users() {
return $this->hasMany(GroupUser::class);
}
public function admins() {
return $this->hasMany(GroupAdmin::class);
}
GroupUser model
public function group() {
return $this->belongsTo(Group::class);
}
public function user() {
return $this->belongsTo(User::class);
}
GroupAdmin model
public function group() {
return $this->belongsTo(Group::class);
}
public function user() {
return $this->belongsTo(User::class);
}
Help wanted
Basically as the relationships between users and groups is many to many normally I shouldn't need models of GroupUser and GroupAdmin and then just using sync() function in order to add/remove users and group id's from those tables.
What is my concerns then?
Normally I use that type of connection when I want input bulk ids into database (let say adding tags to posts, suddenly relate 10 tags id to 1 post) that moment using sync() and removing GroupUser and GroupAdmin models makes sense but in my case as users joins/adds to groups one by one, what do you suggest for this relationships?
Is my current approach makes sense?
Is is better if I remove those GroupUser and GroupAdmin models and add them to user, group model like:
public function users()
{
return $this->hasMany(User::class, 'group_users', 'user_id', 'id');
}
and such so?
What do you think is the best practice?
users and groups is many to many
your tables like this?
users, user_group , groups ?
How about use 'belongsToMany' relation?
Laravel many to many relation
// User model
public function groups() {
return $this->belognsToMany(Group::class);
}
// Group model
public function users() {
return $this->belognsToMany(User::class);
}
And use like.
User::find(1)->groups; // return user 1 groups
User::find(1)->groups()->sync($groupIds); // relate user and groups
Group::find(1)->users; // return group 1 users
If you have role column in your users table, you cold add relation like.
// Group model
public function users() {
return $this->belognsToMany(User::class)->where('role', 'the role of normal user');
}
public function admins() {
return $this->belognsToMany(User::class)->where('role', 'the role of admin user');
}
Hope it helps you.
Have researched extensively eloquent relationships and laravel all afternoon and can't seem to find a solution.
I have a transaction table displaying User IDs in the From and To columns. I want to show the users emails that correspond to their IDs.
Here is my relationships:
Transaction model:
public function user()
{
return $this->belongsTo('App\User', 'id', 'email');
}
User model:
public function transaction()
{
return $this->hasMany(App\Transaction);
}
And heres the code from the controller. However I KNOW this just returns ALL the transactions. But I really can't find how I would display the emails instead of the IDs:
public function index()
{
$table = Table::create(Transaction::get());
return view('table', compact('table'));
}
Maybe you should try to get transactions with related model (user) or with join to users table?
$transactions = Transaction::query()->with(['user'])->get();
$table = Table::create(Transaction::get());
$table->addColumn('email', 'E-mail', function($model) {
return $model->user->email;
});
return view('table', compact('table'));
I'm currently working on a quiz application in laravel 5.6 and am attempting to fetch all quizzes that belong to the current authenticated user.
I have three tables:
users
quizzes
user_quizzes
The quizzes table simply holds all the information relating to the quiz such as:
- id
- quiz_name
- quiz_description
- active
- total_plays
- created_at
- updated_at
The users table is just the laravel default with minor changes:
- id
- username
- email
- password
- remember_token
- created_at
- updated_at
The user_quizzes table holds two fields (both foreign keys): user_id and quiz_id.
At the moment it outputs ALL the quizzes, rather than just ones belonging to the current user.
In my QuizController I have:
$quizzes = Quiz::find(Auth::user()->id)->with('user')->get();
And my QuizModel:
class Quiz extends Model
{
protected $table = 'quizzes';
public function user()
{
return $this->belongsTo('App\Models\User');
}
}
Finally the UserModel contains:
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'username', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function activation()
{
return $this->hasOne('App\Models\Activation');
}
public function profile()
{
return $this->hasOne('App\Models\Profile');
}
public function quizzes()
{
return $this->hasMany('App\Models\Quiz');
}
}
I have also tried using the DB facade with joins but received the same output (all quizzes returned, not just ones belonging to the current user). Here is what I did for that, just for reference:
$quizzes = DB::table('user_quizzes')
->join('users', 'users.id', '=', 'user_quizzes.user_id')
->join('quizzes', 'quizzes.id', '=', 'user_quizzes.quiz_id')
->get();
I feel like I am making a silly mistake, so any guidance would be greatly appreciated.
You need to change Eloquent relationship in the Model.
class User extends Model {
public function quizzes()
{
return $this->belongsToMany(Quiz::class, 'user_quizzes','user_id', 'quiz_id');
}
}
Same with Quiz Model
class Quiz extends Model
{
protected $table = 'quizzes';
public function user()
{
return $this->belongsToMany(User::class, 'user_quizzes','quiz_id', 'user_id');
}
}
DB facade you're doing incorrectly.
You want to fetch all quizzes for the users so you need to query quizzes table like this.
DB::table('quizzes')->leftJoin('user_quizzes', 'user_quizzes.quiz_id', 'quizzes.id')->join('users', 'user_quizzes.user_id', 'user_id')->where('users.id', $USER_ID)->get();
I have 4 tables:
Table name: clients
Fields: id, name, slug
Table name: projects
Fields: id, slug
Table name: project_translation
Fields: id, locale, project_id, title
Table name: client_project
Fields: id, client_id, project_id
Relationships
In the Project model
public function clients()
{
return $this->belongsToMany(Client::class,'client_project')->withTimestamps();
//return $this->belongsToMany('Client')->withTimestamps()->orderBy('priority', 'desc');
}
In the Client model
public function projects()
{
return $this->belongsToMany(Project::class,'client_project')->withTimestamps();
}
public function translate()
{
return $this->belongsToMany(ProjectTranslation::class,'project_translations')->withTimestamps();
}
In Client_Project model
public function clients()
{
return $this->hasMany('App\Models\Project');
}
public function projects()
{
return $this->hasOne('App\Models\Client');
}
In ProjectTranslation model
public function client()
{
return $this->hasMany('App\Models\Client');
}
And I'm trying to access data in controller like this:
$client_project = Client::find($id)->translate;
return $client_project;
This give me the next error:
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique
table/alias: 'project_translations' (SQL: select
`project_translations`.*, `project_translations`.`client_id` as
`pivot_client_id`, `project_translations`.`project_translation_id` as
`pivot_project_translation_id`, `project_translations`.`created_at` as
`pivot_created_at`, `project_translations`.`updated_at` as
`pivot_updated_at` from `project_translations` inner join
`project_translations` on `project_translations`.`id` =
`project_translations`.`project_translation_id` where `project_translations`.`client_id` = 22)
I'm not sure, but I think something is wrong with Relationships.
I'm in Client blade, and I want to show the projectstranslations of the projects of this client.
Here I formatted you query so it's readable, as I said in the comments I am not a laravel user. But I know Sql
select
`project_translations`.*,
`project_translations`.`client_id` as `pivot_client_id`,
`project_translations`.`project_translation_id` as `pivot_project_translation_id`,
`project_translations`.`created_at` as `pivot_created_at`,
`project_translations`.`updated_at` as `pivot_updated_at`
from
`project_translations` <-- Duplicate Table with no alias
inner join
`project_translations` on `project_translations`.`id` = `project_translations`.`project_translation_id`
where
`project_translations`.`client_id` = 22
you don't need Client_Project model.
In the Project model
public function clients()
{
return $this->belongsToMany(Client::class,'client_project')->withTimestamps();
}
public function translates()
{
return $this->hasMany(ProjectTranslation::class);
}
In the Client model :
public function projects()
{
return $this->belongsToMany(Project::class,'client_project')->withTimestamps();
}
In the ProjectTranslation model :
public function project()
{
return $this->belongsTo('App\Models\Project');
}
In the controller :
$client_projects = Client::find($id)->projects; //all client projects
return $client_projects;
In the view after geting this $client_projects and looping over it you can get the translations of a project by :
$client_project->translates // for single projects you will get its translates :)
For Project you have many to many with clients and it has one to many translates => in the documentation links there are many examples :)
I have two tables: users, orders. I try to get all orders for current user.
Users Orders
_____ ______
id | name id | user_id
User model:
public function orders(){
return $this->hasMany("App\Order");
}
Order model:
public function user(){
return $this->hasOne("App\User", 'user_id', 'id');
}
Query in controller:
public function index()
{
$orders = Order::where('user_id', Auth::guard('api')->id())->get();
return response()->json(
$orders->user
);
}
I get NULL result, I do something wrong, because there are related rows in both tables.
If you want to retrieve all the Orders belonging to the current user, try using the following function.
public function index()
{
$orders = Auth::user()->with('Orders')->get()->toArray();//To get the output in array
/* ^ ^
This will get the user | This will get all the Orders related to the user*/
return response()->json($orders);
}
As pointed out by #Martin Heralecký, you would also need to change the hasOne() to belongsTo() in Order Model. See following (copied from #Martin Heralecký answer)
public function user(){
return $this->belongsTo("App\User");// second and third arguments are unnecessary.
}
Why belongsTo():
has_one and belongs_to generally are the same in the sense that they point to the other related model. belongs_to make sure that this model has the foreign_key defined. has_one makes sure that the other model has_foreign key defined.
Your $orders array will look something like this:
User => [
id => 'user id',
name => 'user name'
orders => [
0 => [
//order data
]
1 => [
//order data
]
.
.
.
.
]
]
In Order model you need to use the belongsTo relationship:
public function user()
{
return $this->belongsTo("App\User"); // second and third arguments are unnecessary.
}
In User model you can use hasMany relationship, for example in:
App/User.php
Add
public function orders()
{
return $this->hasMany("App\Order", "user_id", "id");
}
Now you can use this:
return User::find(1)->orders;