public function showJobCategoryContent($id){
$jobsInfoById = DB::table('jobs')->where('category_id', '=', $id)->where('published', '=', 1)->paginate(3);
// Imagine here i got 5 data
foreach ($jobsInfoById as $jobInfoById) {
return $current=$jobInfoById->created_at;
//$trialExpires []= $current->addDays(30);
}
}
If i loop it it only show 1 data. How is it possible If use array sign then it will show 1 data.
If you want to get an array of all created_at dates, you don't need a loop.
public function showJobCategoryContent($id)
{
$jobsInfoById = DB::table('jobs')->where('category_id', '=', $id)->where('published', '=', 1)->paginate(3);
return $jobsInfoById->pluck('created_at');
}
Using the loop:
public function showJobCategoryContent($id)
{
$jobsInfoById = DB::table('jobs')->where('category_id', '=', $id)->where('published', '=', 1)->paginate(3);
$dates = [];
foreach ($jobsInfoById as $jobInfoById) {
$dates[] = $current = $jobInfoById->created_at;
}
return $dates;
}
If want to add 30 days to each date:
public function showJobCategoryContent($id)
{
$jobsInfoById = DB::table('jobs')->where('category_id', '=', $id)->where('published', '=', 1)->paginate(3);
$jobsInfoById = $jobsInfoById->map(function ($job) {
return $job->created_at->addDays(30);
});
return $jobsInfoById->pluck('created_at');
}
Have a look at Laravel collections and how they can be useful: link
Related
I am working on a view that allows users to select a staff member then a date range and when they click the filter button, it will only show that staff member's records for that date period. I have that working but I want to implement an export to excel feature for that staff member and range but when I click export, all my records get exported to excel. Does anyone know what is the right direction to go in?
Controller:
public function exportvehicles()
{
return Excel::download(new ExportV, 'users.xlsx');
}
Model:
class ExportV implements FromCollection
{
public function collection()
{
$startDate = request()->input('startDate', '2021-01-01');
$endDate = request()->input('endDate', '2021-12-12');
return VehicleLog::join('vehicle', 'vehicleslog.vehicle_id', '=', 'vehicle.id')
->join('smsstaff', 'vehicleslog.smsstaff_key', '=', 'smsstaff.smsstaff_key')
->when(request()->input('smsstaff_key'), function ($query) {
$query->where('smsstaff.smsstaff_key', request()->input('smsstaff_key'));
})
->whereDate('log_dt', '>=', $startDate)
->whereDate('log_dt', '<=', $endDate)
->get();
}
}
You can done query on controller before sending it to an ExportV, this will make you easy to implement multiple type of filter.
Controller :
public function exportvehicles()
{
$startDate = request()->input('startDate', '2021-01-01');
$endDate = request()->input('endDate', '2021-12-12');
$item = VehicleLog::join('vehicle', 'vehicleslog.vehicle_id', '=', 'vehicle.id')
->join('smsstaff', 'vehicleslog.smsstaff_key', '=', 'smsstaff.smsstaff_key')
->when(request()->input('smsstaff_key'), function ($query) {
$query->where('smsstaff.smsstaff_key', request()->input('smsstaff_key'));
})
->whereDate('log_dt', '>=', $startDate)
->whereDate('log_dt', '<=', $endDate)
->get();
return Excel::download(new ExportV($item), 'users.xlsx');
}
ExcelV :
class ExcelV implements FromCollection
{
protected $item;
function __constuct ($item) {
$this->item = $item;
}
public function collection() {
return $this->item;
}
}
What I want to do is to get all charts of accounts with extra value i.e. balance from the ledgers table with the parameter of $date, Is there any proper way to do it because I am facing N+1 query problem here.
Controller
public function get(Request $request){
$date = $request->date;
$coas = COA::where('parent_id', null)->get();
//return $coas;
$coas = $coas->map(function ($coa) use ($date) {
$coa['balance'] = $coa->balance($date);
return $coa;
});
return view('website.accounts.Trial.show', compact('coas', 'date'));
}
Model
public function balance($date){
$date = new Carbon($date);
$date= $date->addHours(23)->addMinutes(59)->addSeconds(59);
$balance = Ledger::where('c_o_a_id', $this->id)
->where('created_at' ,'<=', $date)
->orderBy('created_at', 'desc')
->orderBy('id', 'desc')
->pluck('balance')
->first();
if($balance){
return $balance;
}
return 0;
}
1. Set up a relationship between COA and Ledger
COA Model
public function ledgers()
{
return $this->hasMany(Ledger::class, 'c_o_a_id');
}
Ledger Model
public function coa()
{
return $this->belongsTo(COA::class, 'c_o_a_id');
}
2. Make you balance() function use that relationship to avoid querying N+1 times
COA Model
public function balance($date){
$date = new Carbon($date);
$date = $date->addHours(23)->addMinutes(59)->addSeconds(59);
if (!$this->relationLoaded('ledgers') $this->load('ledgers');
$balance = $this->ledgers->where('created_at' ,'<=', $date)
->sort(function ($a, $b) {
return [$b->created_at, $b->id] <=> [$a->created_at, $a->id];
})
->first()
->balance;
return $balance ?: 0;
}
Controller
$coas = COA::with('ledgers')->where('parent_id', null)->get();
How to pass nested foreach from laravel controller to view on the blade for a tree structure based in
three levels based on the referende_id on the above code I have fetched the three levels and now I would like to pass the value to the blade in laravel can anyone help me to sort out this.
class ClientController extends Controller {
public
function index($reference_id) {
$clients = table1::leftjoin('table2', function($join) {
$join -> on('table2.user_id', '=', 'table1.id');
}) -> where('table1.reference_id', '=', $reference_id) -> get();
foreach($clients as $levelOne) { //here $row is the current $data's collection
$clientsLevelOne = table1::leftjoin('table2', function($join) {
$join -> on('table2.user_id', '=', 'table1.id');
}) -> where('table1.under_reference', '=', $levelOne -> reference_id) -> get();
//$clientsLevelOne = arrayName["levelOne"];
//$variable_name['one'] = value;
$datas = array($clientsLevelOne);
foreach($datas as $items) {
//echo 'LEVEL ONE:<br><br>';
foreach($items as $values) {
$LevelOne = $values;
//echo $LevelOne.'<br><br>';
}
}
//return $LevelOne;
foreach($datas as $items) { //echo '<br>LEVEL TWO:<br><br>';
foreach($items as $values) {
$levelTwo = $values['reference_id'];
$clientsLevelTwo = table1::leftjoin('table2', function($join) {
$join -> on('table2.user_id', '=', 'table1.id');
}) -> where('table1.under_reference', '=', $levelTwo) -> get();
//dump($clientsLevelTwo);
$LevelDatas = array($clientsLevelTwo);
//$LevelDatas = array_merge($LevelTwo);
//print_r($LevelDatas);
//echo '<br>LEVEL TWO:<br><br>';
foreach($LevelDatas as $two) {
foreach($two as $values) {
$levelThree = $values;
}
}
}
}
foreach($datas as $items) { //echo '<br>LEVEL THREE:<br><br>';
foreach($items as $values) {
$levelThree = $values['reference_id'];
$clientsLevelThree = table1::leftjoin('table2', function($join) {
$join -> on('table2.user_id', '=', 'table1.id');
}) -> where('table1.under_reference', '=', $levelThree) -> get();
$LevelDatas = array($clientsLevelThree);
foreach($LevelDatas as $two) {
foreach($two as $values) {
$levelDatasThree = $values['reference_id'];
$clientsLevelDatasThree = table1::leftjoin('table2', function($join) {
$join -> on('table2.user_id', '=', 'table1.id');
}) -> where('table1.under_reference', '=', $levelDatasThree) -> get();
$ThreeDatas = array($clientsLevelDatasThree);
foreach($ThreeDatas as $three) {
foreach($three as $values) {
$levelThreeDatas = $values;
}
}
}
}
}
}
}
You may achieve 3 levels of associated data with Laravel's Eloquent ORM by fast and relevant way.
First create Model Level1,Level2 And Level3.
To create Relation With Level1 with Level2 in such way:
<?php
// Level 1 relation with Level 2 in App\Level1
public function level2(){
return $this->hasMany('App\Level2','level_id','id');
}
?>
To create Relation With Level1 with Level2 in such way:
<?php
// Level 2 relation with Level 3 in App\Level2
public function level3(){
return $this->hasMany('App\Level3','level_id','id');
}
?>
and then simply call it in controller's method
<?php
use App\Level1;
public function index(){
$levels = Level1::with(['level2.level3'])->get();
return view('path.file.anyone',compact('levels'));
}
?>
keep in mind! do not query in any kind of loop otherwise at one stage your system's procressing time will be effected
In my show function in which you can watch every single group, I load all articles with the same tags. And the article with the most votes will be displayed separately at the top. In addition, I indicate the average rating of the items in this group. This is how my function looks like:
public function show($id)
{
$group = group::find($id);
$tagIdArray = $group->tags->pluck('id')->all();
$mostvotedarticle = Article::where('type', 4)->whereIn('privacy', [1, 3])
->whereHas('tags', function($query) use ($tagIdArray) {
$query->whereIn('tags.id', $tagIdArray);
}, '>=', count($tagIdArray))
->orderByVotes()->first();
$articledown = Article::where('status', 1)->whereHas('tags', function($query) use ($tagIdArray) {
$query->whereIn('tags.id', $tagIdArray);
}, '>=', count($tagIdArray))->downVotesAll()->count();
$articleup = Article::where('status', 1)->whereHas('tags', function($query) use ($tagIdArray) {
$query->whereIn('tags.id', $tagIdArray);
}, '>=', count($tagIdArray))->upVotesAll()->count();
$ratio = null;
if($articleup + $articledown == 0) {
$ratio = 0;
} else {
$ratio = ($articleup*100)/($articleup + $articledown);
}
return view('singlegroup',compact('groups','mostvotedarticle', 'ratio'));
}
On a overview page, the individual groups are displayed with a foreach loop:
function:
public function index()
{
$user = Auth::user();
$groups = $user->groups()->latest()->with('tags')->paginate(20);
return view('groups', compact('groups'));
}
view:
#foreach ($groups as $group)
{{$group->name}}
<img src="-----load mostvotedarticle that is in this group------" alt="" />
<div class="progress-bar-primary" style="width:{{$ratio}}%;">
#endforeach
How can I have the mostvotedarticle and group ratings displayed in the foreach loop?
Article Model
public function scopeOrderByVotes($query)
{
$query->leftJoin('Article_activities', 'Article_activities.article_id', '=', 'articles.id')
->selectRaw('articles.*, count(Article_activities.id) as aggregate')
->groupBy('articles.id')
->orderBy('aggregate', 'desc');
}
public function scopeDownVotesAll($query)
{
$query->leftJoin('Article_activities', 'Article_activities.article_id', '=', 'articles.id')
->selectRaw('articles.*, count(Article_activities.id) as aggregate')
->where('Article_activities.activity', '=', '0');
}
public function scopeUpVotesAll($query)
{
$query->leftJoin('Article_activities', 'Article_activities.article_id', '=', 'articles.id')
->selectRaw('articles.*, count(Article_activities.id) as aggregate')
->where('Article_activities.activity', '=', '1');
}
you need put all inside your foreach groups
public function index()
{
$user = Auth::user();
$groups = $user->groups()->latest()->with('tags')->paginate(20);
$ratio = null;
foreach($groups as $key => $group)
{
$tagIdArray = $group->tags->pluck('id')->all();
$mostvotedarticle = Article::where('type', 4)->whereIn('privacy', [1, 3])
->whereHas('tags', function($query) use ($tagIdArray) {
$query->whereIn('tags.id', $tagIdArray);
}, '>=', count($tagIdArray))
->orderByVotes()->first();
$articledown = Article::where('status', 1)->whereHas('tags', function($query) use
($tagIdArray) {
$query->whereIn('tags.id', $tagIdArray);
}, '>=', count($tagIdArray))->downVotesAll()->count();
$articleup = Article::where('status', 1)->whereHas('tags', function($query) use
($tagIdArray) {
$query->whereIn('tags.id', $tagIdArray);
}, '>=', count($tagIdArray))->upVotesAll()->count();
if($articleup + $articledown == 0) {
$ratio = 0;
} else {
$ratio = ($articleup*100)/($articleup + $articledown);
}
$group->mostVote = $mostvotedarticle;
$group->ratio = $ratio;
}
return view('groups', compact('groups'));
}
I have products which have a many to many relationship with filters
The user may choose multiple filters and I want to display all products that match the selected filters. But by matching them I mean containing all of them (not only some of them). Here's an example to explain what I mean, let's say that the user is on the cars category page and he wants to filter all cars that are from year 2013 AND have 4x4. Now if the user selects those filters it will show all the cars that are from year 2013 OR have 4x4.
Here's my code in the controller:
public function showFilteredProducts(Request $request)
{
$products = collect([]);
$this->request = $request;
foreach ($request->filters as $filter_id => $active) {
$this->filter_id = $filter_id;
$queriedProducts = Product::whereHas('filters', function($query) {
$query->where('filters.id', $this->filter_id);
})
->whereHas('category', function($query) {
$query->where('slug', $this->request->category_slug);
})
->get();
foreach ($queriedProducts as $product) {
if (!$products->contains($product)) {
$products[] = $product;
}
}
}
return response()->json($products->chunk(3));
}
As i explained this now returns the products if they match only one of the filters, but I want them to match all of them.
try this
public function showFilteredProducts(Request $request)
{
$filters = $request->filters;
$query = Product::query();
foreach ($filters as $filter_id => $active) {
$query = $query->whereHas('filters', function($query) use ($filter_id) {
$query->where('filters.id', $filter_id);
});
}
$query = $query->whereHas('category', function($query) use ($request) {
$query->where('slug', $request->category_slug);
})
$products = $query->get();
return $products->chunk(3);
}
alternatively, based on your previous code, you can use array_intersect like this:
public function showFilteredProducts(Request $request)
{
$products = collect([]);
$this->request = $request;
foreach ($request->filters as $filter_id => $active) {
$this->filter_id = $filter_id;
$queriedProducts = Product::whereHas('filters', function($query) {
$query->where('filters.id', );
})
->whereHas('category', function($query) {
$query->where('slug', $this->request->category_slug);
})
->get();
$products = array_intersect($queriedProducts, $products);
}
return response()->json($products->chunk(3));
}
I think you want to use orWhereHas() instead of whereHas() on the second table that you are checking against.