How to collect data using multiple eager loading in laravel 5 - laravel-5

I'm just wondering why my code is not working, I mean, after I collect single data using eager loading, after that, if I collect the nested relationship, it returns an error. Please see my code below.
Error
Trying to get property of non-object
My Code
Controller.php
$ex = Exam::with('answers', 'child.answers')->find($id);
$exam = collect($ex->answers);
$exams = $exam->merge(collect($ex->child->answers));
return view('school.exam.view', compact('exams'));
view.blade.php
#foreach($exams as $exam)
<li>{{ $exam->name }}</li>
#endforeach
What should I do with this?

Because this line here
$exam = collect($exam->answers);
Maybe you wanted this
$quizzes = collect($exam->answers);
EDIT:
It's because $exam->child is a collection. You need to loop through each childs and get the answers. You also should have named the relation into childs for clarity.
$ex = Exam::with('answers', 'childs.answers')->find($id);
$exam = collect($ex->answers);
foreach(collect($ex->childs) as $child) {
$exams = $exam->merge(collect($child->answers));
}
return view('school.exam.view', compact('exams'));

Related

How to dynamically switch between two arrays for attribute in my blade template

I have a controller method which retrieves data from a Queue, the queue can have a relationship to either a Guest or a Customer model.
In my blade template I iterate over the Queue and need to display either Guest.Name or Customer.Name depending on which column is populated.
Controller
$queue = Queue::where('business_id', '=', $business_id);
$customer_bag = $queue->pluck('user_id');
$guest_bag = $queue->pluck('guest_id');
$customers = User::whereIn('id', $customer_bag)->get();
$guests = Guest::whereIn('id', $guest_bag)->get();
return view('myqueue', compact(['queue', 'customers', 'guests']));
Blade Template
#foreach($queue as $quee)
{{ $customers->find($quee->user_id) ? $customers->find($quee->user_id)->name : $guests->find($quee->guest_id)->name }}
#endforeach
When I use this and the guest_id is blank I get an error stating "Trying to get property 'name' of non-object". How can I correctly detect which one to use?
I think so many problems with your code.
Firstly, $queue is findOrFail() which returns a single object data(not array or collection that can be used for foreach.) I think you need to change to get()
Also $customers and $guests are a collection, so you can not use find() method.
Then you didn't define $quee in the #foreach, so it's will give error result.
I think this code will return as you expected if you fix above problems:
#foreach($queue as $quee)
{{ \App\Customer::find($quee->user_id)->name ?? \App\Guest::find($quee->guest_id)->name ?? "no name" }}
#endforeach
But a better approach is using relation from your queue model:
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function guest()
{
return $this->belongsTo(Guest::class);
}
public function getNameAttribute()
{
return $this->customer?$this->customer->name:($this->guest->name??"no name");
}
and in the blade view
#foreach($queue as $quee)
{{ $quee->name }}
#endforeach
The issue turned out to be that one of my test data records didn't have a value in the guest_id when it should have, this caused the blade template to fail render.

How to check data in Array by using eloquent method in Laravel

I am working on a quiz. Below is a method and I am trying to get an array that can work in in_array function:
public function mcq($id)
{
$questions = Chapter::find($id)->questions()->inRandomOrder()->limit(1)->first();
$question_check = TestsResultsAnswer::where('user_id', auth::id())->pluck('question_id')->toArray();
$sponsors = Sponsor::All();
return view('pages.mcq', compact('questions', 'sponsors', 'question_check'));
}
Below is blade code where I am passing the question_check variable by using in_array function:
#foreach ($questions as $key => $question)
#if(in_array($key, $question_check))
{{'Question Already Attempted'}}
#endif
#endforeach
But I am getting following error:
(2/2) ErrorException
Trying to get property of non-object (View: E:\xampp\htdocs\laravel\lea\resources\views\pages\mcq.blade.php)
My goal is to check if question was already attempted then print something. Please Help me to resolve this problem.
Using first() will return a Model and not a collection, so you can't loop through. Use get() to fetch the result as a collection.
I.e: Instead of this
$questions = Chapter::find($id)->questions()->inRandomOrder()->limit(1)->first();
do this
$questions = Chapter::find($id)->questions()->inRandomOrder()->limit(1)->get();
This should fix your current problem.
Considering this,
My Target is to make a check if question already attempted then print something.
I think this is what you really want to do.
In Controller
$questions = Chapter::find($id)->questions()->inRandomOrder()->get()
In Blade
#foreach ($questions as $question)
#if(in_array($question->id, $question_check))
{{'Question Already Attempted'}}
#endif
#endforeach

laravel passing data to view blade

//model
return $this->hasMany('App\Model\Order', 'customer_id')->select('name');
//controller
$customer = Model\customer::find($id);
return view('customer', array('data' => $customer));
//view (blade)
{{ $data }} //{"id":1,"name":"Tony"}
{{ $data->orders }} //[{"name":"T-shirt"},{"name":"Macbook"}]
i'm new in laravel
I have a question about passing data to view.blade
I used hasMany to join 2 table together and pass $data to view
when I try to output $data, I could not see order object inside of data object
but when I did $data->orders, it shows object
can anyone tell me how it works?
The behavior you are seeing is because Laravel lazy loads relations when they are accessed. If the relation has not been loaded, Laravel will send another query and add it to your $data object behind the scenes. That's why when you dump the $data variable, you are not seeing the orders.
To demonstrate, run the following snippet.
{{ $data }} //{"id":1,"name":"Tony"}
// Laravel will lazy load the orders relation
{{ $data->orders }} //[{"name":"T-shirt"},{"name":"Macbook"}]
// Now the $data object has the orders property.
{{ $data }} //{"id":1,"name":"Tony", "orders": [{"name":"T-shirt"},{"name":"Macbook"}]}
Solution
You have a couple options here. Here are 2.
1. Eager load relation when querying model.
$customer = Model\customer::with('orders')->find($id);
This is the preferred method as it prevents n+1 querying.
2. Load relation after model has been queried.
$customer = Model\customer::find($id);
$customer->load('orders');
Now when you dump the model, you will see the orders property.
In your model,
public function orders(){
return $this->hasMany('App\Model\Order', 'customer_id');
}
In view
{{ $data->orders->order_name }}
I hope it will works
You have defined hasMany relationship in your model. So, for a particular customer there can be multiple orders. So, it shows in array. You have to loop through:
foreach($data->orders as $order)
{
$order->name
}
to get the orders.

Retrieving data from belongsToMany relationship in Laravel

I have some problems with getting data from my relationship. I need the tags of some domains.
$domains = Domains::where('customer_id', Auth::user()->customers_id)->get();
There are all the domains I need. On my Domains model I have this belongsToMany relation to my pivot table.
public function tags() {
return $this->belongsToMany('App\Models\Tags_Domains', 'domain_tag', 'domains_id', 'tags_id');
}
I was able to get all the datas from my relation with this:
dd($domains[0]->tags);
That gave me all the data I wanted but only for the very first domain. But I want this for every domain, to pass this new array to my Blade template. I tried many things out but couldn't make it work. ( $collection error, trying to get properly of non-object ... )
Can someone help me there?
Controller Code:
$domains = Domains::where('customer_id', Auth::user()->customers_id)->get();
return view('defaultLayout.domains.tagsdelete', [
'domains' => $domains
]);
This is because you use $domains[0] and you get the first domain.
You must loop through them:
foreach($domains as $domain) {
foreach($domain->tags as $tag) {
var_dump($tag);
}
}
Edit:
If you need the tags in your view here is how:
#foreach($domains as $domain)
<p>{{ $domain->name }}</p> //where name could be any field that $domain has
#foreach($domain->tags as $tag)
<p>{{ $tag->name }}</p> //where name could be any field that $tag has
#endforeach
#endforeach
Glad I was helpful :)

htmlentities() expects parameter 1 to be string, array given? Laravel

I've found many question realated to my problem but couldn't found an answer yet. It's about my foreach loop in my blade.
I want to print all product-names in my blade but I couln't figure out how to do that.
thats how I'm getting the products:
--- current code:
// controller
$id_array = Input::get('id');
$products= Products::whereIn('id', $id_array)->get();
$product_name = [];
foreach($products as $arr)
{
$product_name= $arr->lists('name');
}
returning $product_name gives me this as a output:
["football","cola","idontknow","freshunicorn","dummy-data"]
In my blade is just a simple:
#foreach($products as $product)
{{ $product}}
#endforeach
Error: htmlentities() expects parameter 1 to be string, array given
Thanks for your help and time.
It seems you are getting an object in an array in an array.
Like this:
array(
array(
object
)
)
It happens because you use the get() function to retrieve you model. The get() function always "wants" to retrieve multiple models. Instead you will have to use the first() function.
Like this:
foreach($id_array as $arr)
{
$want2editarray[] = Product::where('id', $arr)->first();
}
Hope it helps :)
Edit after #Wellno comment
That's probably because Product::where('id', $arr)->first(); returns null because it did not find anything.
I forgot to add a check after the retrieving of the product.
This can be done like this:
foreach($id_array as $arr)
{
// First try to get model from database
$product = Product::where('id', $arr)->first();
// If $product insert into array
if ($product) $want2editarray[] = $product;
}
Why do you use loop with IDs? You can find all products by IDs:
$products = Product::whereIn('id', $id_array)->get();
And then use $products in the blade template
#foreach($products as $product)
{{ $product->name }}
#endforeach
try to use Model/Eloquent to fetch data.
View should only display the data and not fetching directly from DB or do heavy calculations.

Resources