I am adding in an announcements feature to my application.
I have an announcements table which stores the announcement and an announcement_active table which stores the undismissed announcements for each user.
When an announcement is created, a record is generated in the announcements table to store this and a record entered in to the announcement_active table for every user for that announcement.
My user model holds a relationship for the active announcements:
public function activeAnnouncements()
{
return $this->hasMany('App\ActiveAnnouncements');
}
I am then accessing this in my view to check for any undismissed announcements like this:
#if (Auth::user()->activeAnnouncements()->count() > 0)
//code
#endif
The above works fine, it is when I am trying to do a for each loop on the announcements that I am having trouble:
#if (Auth::user()->activeAnnouncements()->count() > 0)
#foreach(Auth::user()->activeAnnouncements()->announcement as $announcement)
//code to display announcement
#endforeach
#endif
It is when I am chaining ->announcement that I run in to trouble. I have defined the relationship like so:
public function announcement()
{
return $this->belongsTo('\App\Announcements');
}
However I get the error:
Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$announcement
When using Tinker and running \App\User::find(1)->activeAnnouncements()->first()->announcement the correct announcement shows.
Where am I going wrong when trying to load these in to my foreach loop?
You're never actually retrieving the data in your foreach. Instead, Laravel thinks you're saying "build this query, don't execute it, then look for a property called 'announcement' on it". If you just change it to a get() call, it should work:
#foreach(Auth::user()->activeAnnouncements()->get() as $announcement)
Or better yet, use the automatic property version:
#foreach(Auth::user()->activeAnnouncements as $announcement)
By the way, it looks like you might want to check out Blade's #each functionality: https://laravel.com/docs/5.3/blade#rendering-views-for-collections
In your class User, definine a announcements relation like this :
public function announcements() {
return $this->hasManyThrough(Announcement::class,ActiveAnnouncement::class);
}
You can then access user's announcement with announcement :
#if (Auth::user()->announcements()->count() > 0)
#foreach(Auth::user()->announcements as $announcement)
//code to display announcement
#endforeach
#endif
Nota :
Maybe you could simply add a column is_active in announcement and drop ActiveAnnouncement model. This way, define announcements relation in your class User :
In your class User, definine a announcements relation like this :
public function announcements() {
return $this->hasMany(Announcement::class);
}
and access active announcements via :
$activeAnnouncements = $user->announcements()->whereIsActive(true)->get()
Hope this will help
Related
I'm trying to create a function in our Laravel 5.8 app that would add multiple records to a pivot table. At present we have the following setup;
Users
Training Courses
Users Training Courses (pivot table for the above relationships, with a few extra fields)
I want to be able to show all users in the database, then check their name, pick a training course and hit "Add" and it'll create a record in the pivot table for each user that was selected.
I can't figure out where to start with this - it seems like I need to have a "for each user selected, run the store function" loop in the controller, but I have no idea where to start.
I wasn't sure if there was an easy way to do this in eloquent or not. Is there a simple way to do this?
Eloquent does this automatically if you set up the relationships correctly and you don't have to worry about pivot tables.
class Users
{
public function trainingCourses()
{
return $this->hasMany(TrainingCourses::class);
}
}
class TrainingCourses
{
public function user()
{
return $this->belongsTo(User::class);
}
}
Then you can use the save() method to create the relationship. But I find it better to wrap this function inside a helper method that you can use throughout your code:
class Users
{
...
public function assignTrainingCourse(TrainingCourse $trainingCourse)
{
return $this->trainingCourses()->save($trainingCourse);
}
}
In your code, you could then do something as simple as this:
$user = User::find(1);
$trainingCourse = TrainingCourse::find(1);
$user->assignTrainingCourse($trainingCourse);
Building on this, suppose you have the following route to assign a training course, where it expects a trainingcourse_id in the request:
Route::post('/users/{user}/trainingcourses', 'UserTrainingCoursesController#store');
Thanks to route model binding, Laravel can inference the parent model (user) from the URL, and your controller might look like this:
// UserTrainingCoursesController.php
public function store(User $user)
{
$trainingCourse = TrainingCourse::find(request()->input('trainingcourse_id'));
$user->assignTrainingCourse($trainingCourse);
return back();
}
Of course, you'll want to put some validation in here, but this should get you started.
Problem
I have two classes, Users & Posts. A user "hasMany" posts and a post "belongTo" a user. But when I call "User::all()" it doesn't automatically pull the users posts for obvious reasons, because if my user had relations to 100 different tables pulling all users would start to become pretty chunky.
Question
Is there a way to pull all users and all user->posts in one or few lines of code without going through a foreach loop?
I know i can use a mutator but the problem I have is my field is called user_id and i have tested it with this code:
public function getUserIdAttribute($id)
{
return User::find($id);
}
But it will replace "user_id" field value with a user object, Id rather have it set to its own "temporary user" field within the result. I'm trying to find best practice!
Thank you in advance.
What you're looking for is called Eager Loading
Inside your post model :
class Post extends Model
{
protected $table='posts';
public $primaryKey='id';
public function user(){
return $this->belongsTo('App\User','user_id');
}
}
now you want to get post with user use below code :
$posts=Post::with('user')->get();
inside your user model :
class User extends Model
{
public function posts(){
return $this->hasMany('App\Model\Post');
}
}
now you want to get a user with all posts :
$user=User::where('id',$id)->first();
$user_posts=$user->posts;
I have a table notices. Model for this table is Notice.php
In this table I have notice and id column.
I have fetched all notices from notices table and viewed in my view. Here is my controller code for fetching all notices.
public function index()
{
$notice = Notice::orderBy('id','desc')->paginate(5);
return view('teacher.notice')->withNotices($notice));
}
Here is my view code to show all notices.
#foreach($notices as $notice)
{{$notice->id}}
{{ $notice->notices }}
#endforeach
Now I want to put two button inside this foreach loop. One is to confirm and another is remove confirmation.
To store this confirmation data I have created another table named notice_confirmed_student and model for this table is noticeConfirmedStudent.php. In this table have three column:
id
student_id
notice_id
If a student click confirm then his id and notice id will be stored in this table. I have done this perfect. But my problem is, in the foreach loop it shows both two button (confirm and remove confirm) at a time. I want to show confirm button if user already not confirmed for this notice. If user already confirmed for that notice then it should show remove confirmation button.
Here I am giving my blade foreach loop again with button for better understanding. Bellow code is not perfect, I have just written those code to understand my question.
#foreach($notices as $notice)
{{$notice->id}}
{{ $notice->notices }}
<?php $student_id= "select student_id from notice_confirmed_student where notice_id=$notice->id"; ?>
#if ($student_id == $auth::user()->id)
<button>confirm</button>
#else
<button>Remove Confirmation</button>
#endif
#endforeach
Thanks in advance.
Few things are wrong/incorrect here, to make it clear,
Notice <> User relation is Many-Many and notice_confirmed_student is a pivot table. so user model should have relation,
public function confirmedNotices()
{
return $this->belongsToMany(Notice::class, 'notice_confirmed_student')
}
Then in for each loop you can check like,
if(in_array($notice-id, Auth::user()->confirmedNotices->pluck('id')->all())) {
// user confirmed
} else {
// user not confirmed.
}
if I correctly understand your issue, you need to check if record with given id exists notice_confirmed_student table, and then check in your loop. retrieve the confirmed students with your notices.
$notice = Notice::with('notice_confirmed_student_or_whatever_your_relation_method_called)')->orderBy('id','desc')->paginate(5);
then check in loop, if related attribute is not empty like you do in your view
#if($notice->my_attr && $notice->my_attr->user_id == \Auth::user()->id)
// do stuff
#else
// it doesn't has record
#endif
I have created a user table in database for user and profile table for more details model like below
Profile.php
public function user() {
return $this->hasOne(User::class);
}
User.php
public function profile() {
return $this->belongsTo(Profile::class);
}
When I call {{Auth::user()}} it only giving me the details in user table
How can i get all details
This is normal behaviour. You are using Eloquent ORM and for many reasons for example performance, profile won't be automatically loaded from database. But if you need you can display user and his profile like this:
{{ dd(Auth::user(), Auth::user()->profile) }}
Here I'm using dd just to dump and die the content but you are getting the basic idea. I recommend you to read Eloquent documentation to get the idea how it's working
I want to retrieve the user's photo and display it in a thumbnail form which i have stored in public/assets/uploads/thumbnail/. I tried auth()->user()->user_detail->file_name but I can't get it to work. How do you do it ?
you have to first define a relationship if they are stored in different table
like i did in model
public function imagedata() {
return $this->hasMany(Images::class, 'listID', 'id');
}
and after that when you get the user just call this method like this
$listingimg = Listings::findOrfail($id);
and for calling the relationship
foreach (listingimg as $singleIlisting) {
$singleIlisting->imagedata;
}
modify the code according your needs as if needed and by the way relatio is one to many