So I have two functions named 'search' and 'pdfview'.
Every time I use the search function, I want to pass a query where it selects certain data to the pdfview function.
Here's my search function:
public function search(Request $request)
{
if ($request->period == 'Daily') {
$datefrom = Carbon::now()->startOfDay();
$dateto = Carbon::now()->endOfDay();
}
elseif ($request->period == 'Weekly') {
$datefrom = Carbon::now()->startOfWeek();
$dateto = Carbon::now()->endOfWeek();
}
elseif ($request->period == 'Monthly') {
$datefrom = Carbon::now()->startOfMonth();
$dateto = Carbon::now()->endOfMonth();
}
elseif ($request->period == 'Yearly') {
$datefrom = Carbon::now()->startOfYear();
$dateto = Carbon::now()->endOfYear();
}
else {
$datefrom = Carbon::parse($request->datefrom);
$dateto = Carbon::parse($request->dateto);
}
$solditems = DB::table('orders')
// ->join('orders', 'receipts.receipt_id', '=', 'orders.receipt_id')
->whereDate('orders.created_at', '>=', $datefrom)
->whereDate('orders.created_at', '<=', $dateto)
->where('status','=', 'served')
->select('orders.*', DB::raw('SUM(subtotal) as subtotal'), DB::raw('SUM(qty) as qty'))
->groupBy('item_id')
->orderBy('created_at', 'dsc')
->get();
return view('salesreports.sellingitems.index', compact('solditems'));
}
And here's my pdfview function:
public function pdfview(Request $request)
{
$solditems = DB::table('orders')
->where('status', 'served')
->select('orders.*', DB::raw('SUM(subtotal) as subtotal'), DB::raw('SUM(qty) as qty'))
->groupBy('item_id')
->orderBy('qty', 'dsc')
->get();
view()->share('solditems', $solditems);
if ($request->has('download')) {
$pdf = PDF::loadView('salesreports.sellingitems.pdf');
return $pdf->download('sellingitems-' . Carbon::now() . '.pdf');
}
return view('salesreports.sellingitems.pdf');
}
As you can see, the pdfview function has a default query for the $solditems. But I wanted that variable to come from my search function.
UPDATE: I managed to solve the problem using session.
Here's how you store with session:
session()->put('period', 'Daily');
and this is how you retrieve with session:
$period = $request->session()->get('period', 'default');
public function getSolditems()
{
if (!isset($this->solditems)) {
$solditems = DB::table('orders')
// ->join('orders', 'receipts.receipt_id', '=', 'orders.receipt_id')
->whereDate('orders.created_at','>=', $datefrom)
->whereDate('orders.created_at', '<=', $dateto)
->where('status','=', 'served')
->select('orders.*', DB::raw('SUM(subtotal) as subtotal'), DB::raw('SUM(qty) as qty'))
->groupBy('item_id')
->orderBy('created_at','dsc')
->get();
$this->solditems = $solditems;
} else {
$solditems = $this->solditems;
}
return $solditems;
}
public function search(Request $request)
{
....
$solditems = getSolditems();
....
}
public function pdfview(Request $request)
{
....
$solditems = getSolditems();
....
}
I think you can use $request->merge() method to pass $solditems data to pdfview() method from search()
public function search(Request $request)
{
....
$request->merge(['solditems'=>$solditems]);
$this->pdfview()
}
public function pdfview(Request $request)
{
$solditems = $request->get('solditems');
....
}
Related
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();
My 3 different function given me value as below: in JSON.
I want to PRINT name of function which has highest value. The Functions are;
public function firstHourTrades()
{
$user_id = Auth::user()->id;
$data = DB::table('finaltrade')
->select(DB::raw('count(*) as first_hour'))
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->where('finaltrade.user_id', $user_id)
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '>=', DB::raw('exchanges.start_time'))
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '<=', DB::raw("ADDTIME(exchanges.start_time, '1:00:00')"))
->get();
return response()->json($data);
}
public function lastHourTrades()
{
$user_id = Auth::user()->id;
$data = DB::table('finaltrade')
->select(DB::raw('count(*) as last_hour'))
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->where('finaltrade.user_id', $user_id)
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '<=', DB::raw('exchanges.close_time'))
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '>=', DB::raw("SUBTIME(exchanges.close_time, '01:00:00')"))
->get();
return response()->json($data);
}
public function otherHoursTrades()
{
$user_id = Auth::user()->id;
$data = DB::table('finaltrade')
->select(DB::raw('count(*) as other_hours'))
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->where('finaltrade.user_id', $user_id)
->whereRaw('finaltrade.created_at NOT BETWEEN exchanges.start_time AND DATE_ADD(exchanges.start_time, INTERVAL 1 HOUR)')
->whereRaw('finaltrade.created_at NOT BETWEEN exchanges.close_time AND DATE_SUB(exchanges.close_time, INTERVAL 1 HOUR)')
->get();
return response()->json($data);
}
FROM THE ANSWER I HAVE CREATED:
public function allCmp()
{
$func_names = ['firstHourTrades()','lastHourTrades()','otherHoursTrades()'];
foreach($func_names as $name)
$results[$name] = $name();
$max = max($results);
DD($max);
}
<?php
function one()
{
return 1;
}
function two()
{
return 2;
}
function three()
{
return 3;
}
$func_names = ['three','one','two'];
// Call each function and store result.
foreach($func_names as $name)
$results[$name] = $name();
$max = max($results);
$max_funcs = array_keys($results, $max);
var_dump($max_funcs);
Output:
array(1) {
[0]=>
string(5) "three"
}
You may need to decode your JSON at some point, something like:
function get_val_from_my_json($json) {
return array_values(json_decode($json, true))[0];
}
print get_val_from_my_json('{"some_key":5}');
Output:
5
And run all the results through that function (assuming valid json).
$results = array_map('get_val_from_my_json', $results);
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
Hi so I have this large query for a search form, And I am just wondering how I would go about moving this into the Model, I have read up on Query Scopes and so on but this is a lot more complex than just searching 1 table for 1 field and I am just so lost, Any help is appreciated!
public function index()
{
$input = Request::all();
$date = \Carbon\Carbon::now()->subMinute(30);
$query = User::rightJoin('user_profiles', 'users.id', '=', 'user_profiles.user_id');
if (isset($input ['minAge']) && $input['minAge']) {
$minAge = $input['minAge'];
$maxDate = \Carbon\Carbon::today()->subYears($minAge)->endOfDay();
}
if (isset($input ['maxAge']) && $input['maxAge']) {
if ($input['maxAge'] < $input['minAge']) {
$maxAge = $input['minAge'];
}
else {
$maxAge = $input['maxAge'];
}
$minDate = \Carbon\Carbon::today()->subYears($maxAge + 1);
}
if (isset($input['u']) && $input['u'])
$query->where('users.username', '=', $input['u']);
if (isset($input['p']) && $input['p'])
$query->where('user_profiles.postcode', '=', $input ['p']);
if (isset($input['o1']) && $input['o1'])
$query->where('users.last_online','>=',$date);
if (isset($input['o2']) && $input['o2'])
$query->whereNotNull('user_profiles.avatar');
if (isset($input ['o3']) && $input['o3'])
$query->orderBy('users.type', 'ASC');
if (isset($input ['minAge']) && $input['minAge'])
$query->whereBetween('user_profiles.dob', [$minDate, $maxDate]);
if (isset($input ['g']))
$query->whereIn('user_profiles.gender',$input ['g']);
$query->orderBy('users.last_online', 'DESC');
$users = $query->paginate(1);
return view('view', compact('users'));
}
You could do this way. Accept $input as parameter in the function in User model.
In User model, add the following code.
public static function allUsers($input)
{
$date = \Carbon\Carbon::now()->subMinute(30);
$query = User::rightJoin('user_profiles', 'users.id', '=', 'user_profiles.user_id');
if (isset($input ['minAge']) && $input['minAge']) {
$minAge = $input['minAge'];
$maxDate = \Carbon\Carbon::today()->subYears($minAge)->endOfDay();
}
if (isset($input ['maxAge']) && $input['maxAge']) {
if ($input['maxAge'] < $input['minAge']) {
$maxAge = $input['minAge'];
}
else {
$maxAge = $input['maxAge'];
}
$minDate = \Carbon\Carbon::today()->subYears($maxAge + 1);
}
if (isset($input['u']) && $input['u'])
$query->where('users.username', '=', $input['u']);
if (isset($input['p']) && $input['p'])
$query->where('user_profiles.postcode', '=', $input ['p']);
if (isset($input['o1']) && $input['o1'])
$query->where('users.last_online','>=',$date);
if (isset($input['o2']) && $input['o2'])
$query->whereNotNull('user_profiles.avatar');
if (isset($input ['o3']) && $input['o3'])
$query->orderBy('users.type', 'ASC');
if (isset($input ['minAge']) && $input['minAge'])
$query->whereBetween('user_profiles.dob', [$minDate, $maxDate]);
if (isset($input ['g']))
$query->whereIn('user_profiles.gender',$input ['g']);
$query->orderBy('users.last_online', 'DESC');
$users = $query->paginate(1);
return $users;
}
Then in your Controller, simply update the following.
With static,
public function index()
{
$users = User::allUsers(Request::all());
return view('view', compact('users'));
}
Alternatively,
public function index()
{
$user = new User;
$user->allUsers(Request::all());
return view('view', compact('users'));
}
Once you have done it this way, you can easily start to use smaller scopes. To use sample scope, you may checkout this Laravel. Use scope() in models with relation
Let me know if it works for you.
I'm wondering how can I rewrite the following User model eloquent business logic to be a bit more DRY. I'm passing three parameters to the model, where all of them are optional, to narrow down the DB search. I'm sure there has to be a elegant way to do this, but it is beyond me at the moment.
public function guests_age($location_id, $year, $gender)
{
if($location_id && $year && $gender)
{
return Guest::select('age')
->where('location_id', '=', $location)
->where('created_at', '=', $year)
->where('gender', '=', $gender)
->get();
}
elseif($location_id && $year && !$gender)
{
return Guest::select('age')
->where('location_id', '=', $location)
->where('created_at', '=', $year)
->get();
}
elseif($location_id && !$year && !$gender)
{
return Guest::select('age')
->where('location_id', '=', $location)
->get();
}
... and so on to cover all cases...
}
Thanks for any help.
try this method
public function guests_age($location_id, $year, $gender)
{
$this->qry = Guest::select('age');
if($location_id)
{
$this->qry->where('location_id', '=', $location);
}
if($year)
{
$this->qry->->where('created_at', '=', $year)
}
if($gender)
{
$this->qry->where('gender', '=', $gender)
}
return $this->qry->get()
... and so on to cover all cases...
}
public function guests_age($args = array())
{
$columns = array('location_id', 'created_at', 'gender');
$query = Guest::select('age');
foreach($columns as $column)
{
if(!empty($args[$column]))
$query = $query->where($column, $args[$column]);
}
return $query->get();
}
//usage:
guests_age(array('location_id' => '1'));
guests_age(array('location_id' => '1', 'gender' => 'm'));
//etc..