Displaying total answer and correct answer of each user - php

I have a db structure like this:
Tables:
users(id, email, password, ...) //default laravel users table
examinees(id, user_id, ...)
exam_quizzes(id, title, explanation)
exam_quiz_answers(id, title, exam_quiz_id, is_correct_ans)
submitted_answers(id, user_id, exam_quiz_id, exam_quiz_answer_id)
I already have the respective models and relationship methods set up.
Models:
User, Examinee, ExamQuiz, ExamQuizAnswer, SubmittedAnswer
Relationships:
// User -> hasOne() -> Examinee
$user->examinee
// ExamQuiz -> hasMany() -> ExamQuizAnswer
$examQuiz->examQuizAnswers
// SubmittedAnswer -> hasMany() -> ExamQuiz
$submittedAnswer->examQuizzes
// SubmittedAnswer -> hasMany() -> ExamQuizAnswer
$submittedAnswer->examQuizAnswers
// User -> hasMany() -> SubmittedAnswer
$user->submittedAnswers
In my view, how can I display the Name, Total Answered and Total Correct for every user who is also an examinee, in a table like this:
<tr>
<th>Name</th>
<th>Answered</th>
<th>Correct</th>
</tr>
#foreach()
{{-- I have no idea what to do here --}}
<tr>
<td></td>
<td></td>
<td></td>
</tr>
#endforeach

In your controller, u get the users an pass it to view.
$users = User:get();
and the make a foreach loop to get the answer and correct answers:
<tr>
<th>Name</th>
<th>Answered</th>
<th>Correct</th>
</tr>
#foreach($users as $user)
<tr>
<td>{{$user->name}}</td>
<td>{{count($user->submittedAnswers()->get())}}</td>
#php
foreach($user->submittedAnswers()->get() as $answer){
foreach($answer->examQuizAnswers->get() as $quiz){
$count = $quiz->where('is_correct_answer',1)->count()
}
}
#endphp
<td>{{$count}}</td>
</tr>
#endforeach
But of course you can write a method in a model to retrieve the correct answers. and just call that method instead.
you can write a method like this in User model:
public function get_correct_answers($user_id){
$user = User::whereId($user_id)->first();
foreach($user->submittedAnswers()->get() as $answer){
foreach($answer->examQuizAnswers->get() as $quiz){
$count = $quiz->where('is_correct_answer',1)->count()
}
}
return $count;
}
And then in the view u just call that method like this:
<tr>
<th>Name</th>
<th>Answered</th>
<th>Correct</th>
</tr>
#foreach($users as $user)
<tr>
<td>{{$user->name}}</td>
<td>{{count($user->submittedAnswers()->get())}}</td>
<td>{{$user->get_correct_answers($user->id)}}</td>
</tr>
#endforeach

Loop your $users and echo the 3 fields you want. Something roughly like this:
{{ $user->name }}
{{ $user->submittedAnswers->examQuizAnswers()->where('is_correct_answer', 1)->get()->count() }}
{{ $user->submittedAnswers->examQuizAnswers->count() }}
But please don't actually query in view files for the sake of the children.
Eager load related models in your controller:
User::with(['submitted_answers', 'submitted_answers.exam_quiz_answers'])->get()

Related

Retrieve data with relations in laravel

I would like to display the name of each entity in my table but it returns me
Property [name] does not exist on this collection instance.
My Controller
$users = User::with('pearls')->latest()->get();
the index.blade.php
<thead>
<tr>
<th scope="col">SL No</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
#foreach($users as $user)
<th>{{ $user->pearls->name}}</th>
#endforeach
<th scope="col">Actions</th>
</tr>
</thead>
Because pearls is a collection, not object!
I think you've performed a one-to-many relationship between user and pearl, so, you should use foreach for pearls too:
foreach ($user->pearls as $pearl){
echo $pearl->name;
}
The issue is this line: {{ $user->pearls->name}} in your blade.php
For hasMany relations you cant retrieve data like this.
Any relationship that has Many in it's name, example: hasMany or belongsToMany will always return a collection object.
Try dd($users->pearls), it'll return a collection of data.
You are trying to call the property name on a collection object, not from a singe model.
When you're using get() method you will get a collection. In this case you need to iterate over it to get properties.
#foreach ($user->pearls as $pearl)
{{ $pearl->name}}
#endforeach
By using its index you will get one of the object property
#foreach($users as $user)
<th>{{ $user->pearls[0]->name}}</th>
#endforeach
Or you can use the first() method instead of get() method in your query , so you can easily call the object property like {{ $user->pearls->name}} ,also you need to use one to one relation like hasOne.

Laravel orderby with relationship

i'm trying to sort the student list by each level with using relationship method with OrderBy function but unfortunately i can't make it work any idea whats missing on my code?
Note:
every-time i remove the orderby my code will work but students level are not arrange accordingly
Controller:
$students=Student::with('level')->where(['status' => 'ENROLLED'])->get()->orderBy('level_name','asc');
View
<table>
<tr>
<th>Name</th>
<th>Level</th>
</tr>
#foreach($students as $std)
<tr>
<td>
{{$std->student_name}}
</td>
<td>
#foreach($std->level as $lv)
{{$lv->level_name}}
#endforeach
</td>
</tr>
#endforeach
</table>
You can't order by a relationship because under the hood laravel makes two seperate queries under the hood.
You can instead use a join, something like this (beware I guessed your table names, so you may have to update them).
$users = Student::join('levels', 'students.level_id', '=', 'levels.id')
->orderBy('levels. level_name', 'asc')->select('students.*')->paginate(10);
Try this:
Controller:
$students = Student::with(['level' => function (Builder $query) {
$query->orderBy('level_name', 'asc');
}])->where(['status' => 'ENROLLED'])->get();
In addition you can add orderBy() to relation method.
Student Model:
public function level()
{
return $this->relationMethod(Level::class)->orderBy('level_name', 'asc');
}
Try this
$students=Student::with('level')->where(['status' => 'ENROLLED'])->orderBy('level_name','asc')->get();

How to get the username through an id in Laravel?

I am trying to create an offers forum, where some user can create their offers in order to provide their services and I want to show the name of the person that created that offer instead of the id.
In my database I have the two tables:
Offers table:
User table:
In offers I have a column of the professor_id, that is related to the id of users table.
This is what i have in my controller to show the offers:
public function ofertes(){
$ofertes = Oferta::all()->sortByDesc('id');
return view('create.ofertes')->with(compact('ofertes'));
}
and in the blade.php I have that code:
#foreach($ofertes as $oferta)
<tr>
<td>Nom : {{$oferta->professor_id}}</td> <br>
<td>Títol : {{$oferta->titol}}</td> <br>
<td>Descripció: {{$oferta->descripcio}}</td> <br>
<td>Data: {{$oferta->created_at}}</td> <br><br>
</tr>
#endforeach
and that is what is shown:
Where it says nom, how I can show the name instead of the id?
Thank you!
If you have specified the relationship to professor in your Oferta model you can use the following code:
public function ofertes(){
$ofertes = Oferta::with('professor')->latest()->get();
return view('create.ofertes')->with(compact('ofertes'));
}
Your blade:
#foreach($ofertes as $oferta)
<tr>
<td>Nom : {{$oferta->professor->nom}}</td> <br>
<td>Títol : {{$oferta->titol}}</td> <br>
<td>Descripció: {{$oferta->descripcio}}</td> <br>
<td>Data: {{$oferta->created_at}}</td> <br><br>
</tr>
#endforeach
If you haven't specified the relation you should add the following method to your Oferta model (you might need to tweak this a little bit based on your namespaces):
public function professor()
{
return $this->belongsTo(User::class);
}
Very easy
public function ofertes(){
$ofertes = Oferta::with('professor')->latest()->get();
$users = User::all();
return view('create.ofertes')->with(compact('ofertes', 'users'));
}
In blade file:
<td>Nom : #foreach ($users as $user)
#if ($oferta->professor_id === $user->id) $user->nom $user->cognom
#endif
#endforeach
</td><br>
Join two table like
$oferta = DB::table('users')
->join('offers','users.id','=','offers.professor_id')
->select('offers.*','users.nom')
->orderby('offers.id','DESC')->get();
Then in place of {{$oferta->professor_id}}, replace {{$oferta->nom}}
Your problem should be solved

Trying to get property of non-object - Laravel 5

I'm trying to echo out the name of the user in my article and I'm getting the
ErrorException: Trying to get property of non-object
My code:
Models
1. News
class News extends Model
{
public function postedBy()
{
return $this->belongsTo('App\User');
}
protected $table = 'news';
protected $fillable = ['newsContent', 'newsTitle', 'postedBy'];
}
2. User
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
protected $table = 'users';
protected $fillable = ['name', 'email', 'password'];
protected $hidden = ['password', 'remember_token'];
}
Schema
table users
table news
Controller
public function showArticle($slug)
{
$article = News::where('slug', $slug)->firstOrFail();
return view('article', compact('article'));
}
Blade
{{ $article->postedBy->name }}
When I try to remove the name in the blade {{ $article->postedBy }} it outputs the id, but when I try to add the ->name there it says Trying to get property of non-object but I have a field namein my table and aUser` model. Am I missing something?
Is your query returning array or object? If you dump it out, you might find that it's an array and all you need is an array access ([]) instead of an object access (->).
I got it working by using Jimmy Zoto's answer and adding a second parameter to my belongsTo. Here it is:
First, as suggested by Jimmy Zoto, my code in blade
from
$article->poster->name
to
$article->poster['name']
Next is to add a second parameter in my belongsTo,
from
return $this->belongsTo('App\User');
to
return $this->belongsTo('App\User', 'user_id');
in which user_id is my foreign key in the news table.
If you working with or loops (for, foreach, etc.) or relationships (one to many, many to many, etc.), this may mean that one of the queries is returning a null variable or a null relationship member.
For example: In a table, you may want to list users with their roles.
<table>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
#foreach ($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->role->name }}</td>
</tr>
#endforeach
</table>
In the above case, you may receive this error if there is even one User who does not have a Role. You should replace {{ $user->role->name }} with {{ !empty($user->role) ? $user->role->name:'' }}, like this:
<table>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
#foreach ($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ !empty($user->role) ? $user->role->name:'' }}</td>
</tr>
#endforeach
</table>
Edit:
You can use Laravel's the optional method to avoid errors (more information). For example:
<table>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
#foreach ($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ optional($user->role)->name }}</td>
</tr>
#endforeach
</table>
If you are using PHP 8, you can use the null safe operator:
<table>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
#foreach ($users as $user)
<tr>
<td>{{ $user?->name }}</td>
<td>{{ $user?->role?->name }}</td>
</tr>
#endforeach
</table>
I implemented a hasOne relation in my parent class, defined both the foreign and local key, it returned an object but the columns of the child must be accessed as an array.
i.e. $parent->child['column']
Kind of confusing.
REASON WHY THIS HAPPENS (EXPLANATION)
suppose we have 2 tables users and subscription.
1 user has 1 subscription
IN USER MODEL, we have
public function subscription()
{
return $this->hasOne('App\Subscription','user_id');
}
we can access subscription details as follows
$users = User:all();
foreach($users as $user){
echo $user->subscription;
}
if any of the user does not have a subscription, which can be a case.
we cannot use arrow function further after subscription like below
$user->subscription->abc [this will not work]
$user->subscription['abc'] [this will work]
but if the user has a subscription
$user->subscription->abc [this will work]
NOTE: try putting a if condition like this
if($user->subscription){
return $user->subscription->abc;
}
It happen that after some time we need to run
'php artisan passport:install --force
again to generate a key this solved my problem ,
I had also this problem. Add code like below in the related controller (e.g. UserController)
$users = User::all();
return view('mytemplate.home.homeContent')->with('users',$users);
Laravel optional() Helper is comes to solve this problem.
Try this helper so that if any key have not value then it not return error
foreach ($sample_arr as $key => $value) {
$sample_data[] = array(
'client_phone' =>optional($users)->phone
);
}
print_r($sample_data);
Worked for me:
{{ !empty($user->role) ? $user->role->name:'' }}
In my case the problem was in wrong column's naming:
In model Product I've tried to access category relationship instance to get it's name, but both column name and relationship had the same name:
category
instead of:
category_id - for column name
category - for relationship
Setting up key name in relationship definition like
public function category():hasOne
{
return $this->hasOne(Category::class,'category');
}
didn't help because as soon as Laravel found property named category gave up on looking for relationship etc.
Solution was to either:
change property name (in model and database) or
change relationship name (Eg. productCategory )
It wasn't an error in my case. However, this happened to me when I was trying to open users.index, because while testing I've deleted some data from the 'STUDENTS' table and in the 'USERS' table, a foreign key ('student_id') represents the 'STUDENTS' table. So, now when the system tries to access the 'USERS' table in which foreign key ('student_id') is null since the value got deleted from the 'STUDENTS' table.
After checking for hours when I realise this, I insert the same data again in the 'STUDENTS' table and this resolved the issue.

relationship and blade in laravel

I have 3 table as mentioned below.
Table 1(user):
id username password Name Age
Table 2(tasks):
id task_name description
Table 3(logs)
id user_id task_id date hours
Table Relationships:
user has_many logs
task has_many logs
logs belongs_to user
logs belongs_to task
what i am trying to achieve is to get the logs with the user Name, task Name, date and hours.
Controller:
return View::make('log.index')
->with('logs',log::all());
Blade template
#foreach($logs as $log)
<tr>
<td>{{$log->id}}</td>
<td>{{$log->users()->name}}</td>
<td>{{$log->tasks()->name}}</td>
<tr>
#endforeach
but unable to fetch users Name and Tasks name from the respective table. any help is appreciated.
A better way is to define inverse hasMany relation in your Model, as documented here
So in your logs model, probably you need to define:
class Log extends Eloquent {
protected $table = "logs";
public function user(){
return $this->belongsTo('User');
}
public function task(){
return $this->belongsTo('Task');
}
}
Then in your view you can either use :
$log->user()->first()->name
or even better, by using Dynamic Properties:
$log->user->name
$log->users() and $log->tasks() returns a query object. Below, each call returns the result which is the same as calling $log->users()->get() and $log->tasks()->get(). Because the relationships are many to many, you'll need to iterate over $log->users and $log->tasks to retrieve each record.
#foreach($logs as $log)
<tr>
<td>{{$log->id}}</td>
<td>
#foreach($log->users as $user)
{{$user->name}},
#endforeach
</td>
<td>
#foreach($log->tasks as $task)
{{$task->name}},
#endforeach
</td>
<tr>
#endforeach
If you want a specific user/task attached to a log you'll have to build a query.
#foreach($logs as $log)
<tr>
<td>{{$log->id}}</td>
<td>{{$log->users()->where('id', '=', $userID)->first()->name}} </td>
<td>{{$log->tasks()->where('id', '=', $taskID)->first()->name}} </td>
<tr>
#endforeach

Categories