Foreach inside Foreach based on column value - laravel

I have an sql table knowledgebase like so
id , categoryid, title
id
categoryid
title
1
1
apple
2
1
fb
3
2
google
4
2
DB
5
3
Reebok
In my laravel blade, I am trying to create a tree view to look like the following
-1
--apple
--FB
-2
--google
--DB
-3
--Reebok
My controller does a basic query and returns the entire table to the view. I am a newbie to laravel so far, I can get a basic table to work like
#foreach($knowledgebase as $key => $value)
<tr>
<td>{!! $knowledgebase ->id !!}</td>
<td>{!! $knowledgebase ->title!!}</td>
<td>{!! $knowledgebase ->categoryid !!}</td>
</tr>
#endforeach
How would I iterate categroyid column , display first category and all child titles and then move on to the next categoryid.
Update
public function show($id) {
//get article
$knowledgebase = \App\Models\Knowledgebase::Where('knowledgebase_slug', request('knowledgebase_slug'))->first();
return view('knowledgebase', compact('knowledgebase'));
}

You will need to retrieve in controller the categories before ($categories)
#foreach($categories as $category)
<tr>
<td>{{ $category->id }}</td>
<td>{{ $category->title}}</td>
<td>{{ $category->categoryid }}</td>
</tr>
#endforeach

Anyways, I managed to solve this by adding a function children in my model. So in my Model added
public function children(){
return $this->hasMany('App\Models\Knowledgebase', 'categoryid');
}
After this, I simply called it as a foreach inside my foreach
#foreach($categories as $category)
<li>{{ $category->title}}</li>
#if($category->children)
#foreach($category->children as $child)
<ul>
<li class="pl-3"> {{ $child->title}} </li>
</ul>
#endforeach
#endif
#endforeach

Related

Value correlation from multiple tables in laravel

I have two tables. One employees and one timesheets
I would like to have correct name at the result but different ID. If you see the result I have the same name everywhere.
How can make the code to fixed my challenge?
Thank you.
In controller I have this code
$profile = ['no' => Auth::user()->no];
$timesheets = Timesheet::where($profile)->select('*')->orderBy('created_at','DESC')->get();
foreach ($timesheets as $employee) {
$emp = ['identification' => $employee->identification];
$oneemployee = Employees::where($emp)->select('*')->orderBy('created_at','DESC')->get();
}
return view('contractor.employees.timesheets', compact('timesheets', 'oneemployee'));
and in blade I have
#foreach ($timesheets as $row1)
<tr>
<td>#</td>
#foreach ($oneemployee as $row2)
<td>{{ $row2->fname}}</td>
<td>{{ $row2->lname}}</td>
#endforeach
<td>{{ $row1->identification}}</td>
<td>{{ $row1->week}}</td>
<td>{{ $row1->year}}</td>
</tr>
#endforeach
According to your commit, I suggest the following solution
If you want dispay timesheet with employees you can use eager loading.
For example:
In your controller:
$profile = ['no' => Auth::user()->no];
$timesheets = Timesheet::where($profile)->with("employees")->select('*')->orderBy('created_at','DESC')->get();
return view('contractor.employees.timesheets', compact('timesheets'));
In your Timesheet model add hasOne relation to Employee:
public function employee(){
return $this->hasOne(Employee::class,'identification','identification')
}
And your view:
#foreach ($timesheets as $timesheet)
<tr>
<td>#</td>
<td>{{ $timesheet->employee->fname}}</td>
<td>{{ $timesheet->employee->lname}}</td>
<td>{{ $timesheet->identification}}</td>
<td>{{ $timesheet->week}}</td>
<td>{{ $timesheet->year}}</td>
</tr>
#endforeach

How to order column by relationship in Laravel Livewire

I've just followed this tutorial about implementing a data table with Livewire in Laravel.
So far so good. Now I want to order a column that comes from a one-to-one relationship, but I just can't get the sorting work well when selecting this phones relationship column.
In this case, phones is the relationship method and number is the column I display in the table, which I want to allow the sorting, as well.
How do I implement the sorting by column relationship?
Here is part of my code of the livewire blade (original repo of the tutorial):
<select wire:model="orderBy" class="...">
<option value="firstname">Name</option>
<option value="lastname">Lastname</option>
<option value="email">E-mail</option>
<option value="phones">Phone number</option>
</select>
...
<table class="table-auto w-full mb-6">
<thead>
<tr>
<th class="px-4 py-2">Name</th>
<th class="px-4 py-2">Lastname</th>
<th class="px-4 py-2">E-mail</th>
<th class="px-4 py-2">Phone number</th>
</tr>
</thead>
<tbody>
#foreach($users as $user)
<tr>
<td class="border px-4 py-2">{{ $user->firstname }}</td>
<td class="border px-4 py-2">{{ $user->lastname }}</td>
<td class="border px-4 py-2">{{ $user->email }}</td>
<td class="border px-4 py-2">{{ $user->phones->number }}</td>
</tr>
#endforeach
</tbody>
</table>
{!! $users->links() !!}
And here is the Livewire controller (original repo of the tutorial):
class UsersTable extends Component
{
use WithPagination;
public $perPage=5;
public $search = '';//Search string
public $orderBy='firstname';
public $orderAsc=true;
public $relationship_columns=['phones'];
public function render()
{
if(!in_array($this->orderBy,$this->relationship_columns)){
$users = User::search($this->search)
->orderBy($this->orderBy,$this->orderAsc ? 'asc' : 'desc')
->simplePaginate($this->perPage);
}else if($this->orderBy=='phones'){
$order = $this->orderAsc ? 'asc': 'desc';
$users = User::search($this->search)
->with(['phones' => function ($q) use($order){
$q->orderBy('number',$order);
}])
->simplePaginate($this->perPage);
}
return view('livewire.users-table',compact('users'));
}
}
Reference.
The sorting of (order by) phones is not working well. It seems it sorts some parts well, but in general, sorting is flawed. It can be sorted neither ascendant nor descendant.
Looks like the sorting type (asc,desc) is not taking effect in
$q->orderBy('number',$order);
Moreover, if I use the whereHas() method:
$order = $this->orderAsc ? 'asc': 'desc';
$users = User::search($this->search)
->whereHas('phones',function ($q) use($order){
$q->orderBy('number',$order);
})
->simplePaginate($this->perPage);
I get the following error:
SQLSTATE[HY000]: General error: 20018 The ORDER BY clause is invalid
in views, inline functions, derived tables, subqueries, and common
table expressions, unless TOP, OFFSET or FOR XML is also specified.
[20018] (severity 15)
What am I missing? Any ideas on how to fix this?
How do I implement the order by functionality on the relationship column in Livewire?
Based on these posts Ordering database queries by relationship columns in Laravel and Laravel Eloquent whereColumn Query Example, I have solved the ordering by relationship this way:
I set any name to the relationship, in the parameter search function, let's say phone.number.
Then, with an if statement I detect if the ordering is that relationship:
if($this->field == 'phone.number'){
$users = $users->orderBy(\App\Models\Phone::select('number')->whereColumn('users.phone_id','phones.id'));
}else{
$users = $users->orderBy($this->field,$this->order);
}
Moreover, in this answer it is explained how to search inside a column relationship.
You can use
$user = User::search($this->search)
->whereHas('phones', function ($q){
$q->orderBy('number', $order);
})
->simplePaginate($this->perPage);
instead of
$users = User::search($this->search)
->with(['phones' => function ($q) use($order){
$q->orderBy('number',$order);
}])
->simplePaginate($this->perPage);

Display list of purchase order base from filtered vendor in Laravel eloquent

I am trying to display the list of vendor with their purchase orders in a table.
VENDOR MODEL
public function vendorPo()
{
return $this->hasMany('App\PurchasedOrder', 'vendor_id','vendor_id');
}
VENDOR CONTROLLER
public function vendor()
{
$vendorPo = Vendor::with('vendorPo')
->get()
->keyBy('id')
->groupBy('vendor_name');
$purchaseOrders = PurchasedOrder::all()->where('publish','=','1');
return view('backend.purchase-order.vendor', compact('purchaseOrders'))
->with('vendorPo', $vendorPo);
}
for my index
#foreach ($vendorPo as $vendor => $vendor_list)
<tr>
<th colspan="7"
style="background-color: #F7F7F7"> {{ $vendor }}: ({{ $vendor_list->count() }} vendors)
</th>
</tr>
#foreach ($vendor_list as $key => $vendorPoList)
<tr>
<td>
{{ $vendorPoList->vendorPo->po_id}}
</td>
</tr>
#endforeach
#endforeach
if I do this
...
#foreach ($vendor_list as $key => $vendorPoList)
<tr>
<td>
{{ $vendorPoList}}
</td>
</tr>
#endforeach
...
the result is this
and if I
...
<td>
{{ $vendorPoList->vendorPO->po_id}}}
</td>
...
the result is error
Facade\Ignition\Exceptions\ViewException
Property [po_id] does not exist on this collection instance. (View:
Please help me. Thanks!
You are getting this issue because your vendorPO relation is a HasMany relation. If you pull back the records from that sort of relation, the results are always an array (even if there is only one record), which is always converted by Eloquent into a Collection.
Therefore, $vendorPoList->vendorPO is a Collection, and there is no variable on a Collection called po_id.
Depending on your data model, you should either revisit the relation, or do a #foreach on $vendorPoList->vendorPO.

Laravel need data from two different collections in for each

I have a for each loop to iterate over the collection of records. It has the user_id, but not the other user credentials. I created another collection of user. How do I include this in my iteration?
Controller
public function index(Request $request, $id)
{
$thoughts = Thought::where('id', $id)->orderBy('created_at', 'desc')->paginate(100)->get();
$user = User::where('id', $thoughts->user_id);
return view('backend.pages.thought_list', compact('thoughts, user'));
}
View
#foreach ($thoughts as $thought)
<tr>
<td class="col-md-1">{{ $user->username}} <span class="user_id_thought">ID - {{ $user->user_id}}</span></td>
<td class="col-md-1">{{ $thought->response }}</td>
<td>{{ $thought->thought_type }}</td>
<td>{{ $thought->id }}</td>
</tr>
#endforeach
How do I display my users variable in the loop. Or is there a better way of doing this.
Eager Loading is the perfect use case for your requirement in my opinion.
e.g.
$thoughts = Thought::with('user')->get();
foreach ($thoughts as $thought) {
echo $thought->user->name;
}
For more details see: https://laravel.com/docs/5.6/eloquent-relationships#eager-loading

Trying to pass data from controller to view in laravel 5

I am trying to pass 2 different columns from my sql table to my view ,so that i can show them.
My controller is:
$interface = DB::table("users")->distinct()->get(['name']);
$interfac = DB::table("users")->distinct()->get(['email']);
view()->share('users',compact('interface','interfac'));
My view is :
#foreach ($users as $key => $value)
<tr>
<td>{{ $value->name }}</td>
<td>{{ $value->email }}</td>
</tr>
But this is not working while passing the two variables.If i pass one it is working but passing two is not working.thanks.
Controller
$users = DB::table('users')->get();
return view('users', compact('users'));

Resources