Create function with query in model, Laravel - laravel

I have a working function in my controller, but I want to place a part of the code in model, is repeatable and I want to use it in multiple controllers. but witch my current code is not working (no errors).
Controller
public function index(Request $request)
{
$query = new Question;
$query->select(
['questions.id',
'questions.free_text',
'questions.title',
'questions.created_at',
'lkp_answers.name as bestMatch',
]);
$query->with(['answer_history']);
$query->join('lkp_answers', 'lkp_answers.id', '=', 'questions.best_match');
$query->count_filter($query, $request); //here I try to use it
return response()->json($query->paginate($request->per_page));
}
Model
public function count_filter($query, $request){
if($request->sort_by){
$direction = ($request->sort_direction === 'false') ? 'asc' : 'desc';
if($request->sort_by === 'best_match'){
$query->orderBy('lkp_answers.name', $direction);
}else if ($request->sort_by === 'noneOfTheAbove') {
$query->withCount(['answer_history AS none' => function ($q) {
$q->where('answer_type', 'none');
return $q;
}])->orderBy('none', $direction);
} else if ($request->sort_by === 'skipped') {
$query->withCount(['answer_history AS skipped' => function ($q) {
$q->where('answer_type', 'skipped');
return $q;
}])->orderBy('skipped', $direction);
} else if ($request->sort_by === 'totalVotes') {
$query->withCount(['answer_history AS totalVotes' => function ($q) {
$q->where('answer_type', '!=','skipped');
return $q;
}])->orderBy('totalVotes', $direction);
}
else {
$query->orderBy($request->sort_by,$direction);
}
}
return $query;
}

The problem is that you defined the method to the model but you try to call it on an eloquent query. What you need to do is to use another variable for the query:
public function index(Request $request, Question $question)
{
$query = $question->newQuery();
$query->select(
['questions.id',
'questions.free_text',
'questions.title',
'questions.created_at',
'lkp_answers.name as bestMatch',
]);
$query->with(['answer_history']);
$query->join('lkp_answers', 'lkp_answers.id', '=', 'questions.best_match');
$question->count_filter($query, $request)
return response()->json($query->paginate($request->per_page));
}

Related

How do I call an Eloquent function with arguments?

I have a staff controller and transactions model. In the staff controller, I am fetching staff transactions with other data as below
StaffController.php
$transactions = Transaction::thisMerchant()
->earnedByStaff($staff)
->where(function ($q) use ($staffID) {
$q->where('staff_id', $staffID)
->orWhere(function ($qq) use ($staffID) {
$qq
->whereNull('staff_id')
->whereHas('items', function ($qqq) use ($staffID) {
$qqq->where('staff_id', $staffID);
});
})
->orWhereHas('associateCommissions', function ($qq) use ($staffID) {
$qq->where('staff_id', $staffID);
});
})
->when($start_date && $end_date, function ($q) use (
$start_date,
$end_date
) {
$q->whereBetween(\DB::raw('date(date)'), [
$start_date . ' 00:00:00',
$end_date . ' 23:59:59',
]);
})
->with('client')
->orderBy('date', 'DESC')
->where('is_void', null)
->where('is_draft', null)
->with('items.sellable.sellable')
->with('associateCommissions')
->paginate(10);
In the transactions model, I have this
Transaction.php
public function earnedFromTransaction($staff_id)
{
$staff = Staff::find($staff_id);
if ($this->is_void == '1') {
return 0;
}
if ($this->provider() == 'Empty') {
return 0;
}
if ($this->provider() == 'Split') {
$amounts = Titem::where('transaction_id', $this->id)
->where('staff_id', $staff_id)
->whereHas('product', function ($q) {
$q->whereNull('commission');
})
->whereHas('transaction', function ($q) {
$q->where('is_void', null);
})
->sum('frozen_staff_commission');
$discounts = Titem::where('transaction_id', $this->id)
->where('staff_id', $staff_id)
->whereHas('product', function ($q) {
$q->whereNull('commission');
})
->whereHas('transaction', function ($q) {
$q->where('is_void', null);
})
->sum('discount');
// When the frozen staff rate is zero, just give sellable commission
$titem_commissions = Titem::where('transaction_id', $this->id)
->where('staff_id', $staff_id)
->where('frozen_staff_commission', '<=', 0)
->whereHas('product', function ($q) {
$q->whereNotNull('commission');
})
->sum('commission');
$total =
floatval($amounts) +
floatval($titem_commissions) -
floatval($discounts);
return $total;
}
return floatval($this->frozen_staff_commission);
}
public function earnedByStaff(Staff $staff)
{
return StaffCommissionEngine::earnedFromTransaction($this, $staff);
}
I am getting this error BadMethodCallException: Call to undefined method Illuminate\Database\Eloquent\Builder::earnedByStaff() in file
I have tried using $transactions = Transaction::earnedByStaff($staff)... but this returns
Error: Non-static method App\Transaction::earnedByStaff() cannot be called statically in file
How do I call the earnedByStaff() method and pass the $staff to it?
Make the function 'earnedByStaff' static.
public static function earnedByStaff( Staff $staff)
{
return StaffCommissionEngine::earnedFromTransaction($this, $staff);
}
After that it will work fine.
You can use scope method
public function scopeEarnedByStaff($query,$arg)
{
.....
}
You can also use the call method on the query builder to call a function on the model class
MyModel::where('column', 'value')->get();
$transactions = Transaction::thisMerchant()
->call('earnedByStaff', [$staff])->where()
..
..

How to return from execution stack immediately as value is found

I have search functionality. If a user wants to find anothers' threads, it comes in as a boolean TRUE.
I am able to dd($threads) in its execution stack, but it seems like it follows through with the rest of the execution stack.
For example:
public function scopeSearch(Builder $query, ?string $search = null, ?array $users = null, ?bool $title = null, ?bool $threads = null)
{
if ($threads == TRUE) {
return $query->whereHas('thread', function ($query) use ($users) { return $query->whereIn('threads.user_id', $users)->toSql(); });
}
elseif (!$search) {
return $query->when($users, function ($q) use ($users) { $q->whereIn('user_id', $users)
->whereHas('thread', function ($query) use ($users) { $query->whereIn('threads.user_id', $users); })
->orWhereHas('reply', function ($query) use ($users) { $query->whereIn('replies.user_id', $users); })
->orWhereHas('product', function ($query) use ($users) { $query->whereIn('products.user_id', $users); })
->orWhereHas('review', function ($query) use ($users) { $query->whereIn('reviews.user_id', $users); })
;
});
}
}
I can dd($threads), but want to know how I can stop it right there, as it's not returning the toSql statement, and, I want it to just return the threads.
Any help is appreciated :) thanks all :).
In my controller method:
I had:
if ($threads) {
}
if (!empty($variable) {
}
It should have been "paired together" like such
if ($threads) {
} elseif (!empty($variable)) {
} elseif (etc, etc) {
}

How to make a filter with query string in laravel

I want to make a filter with query params, here I want to make 3 where, but if one of them is not there, then it will not be a problem because it will display according to the filter only, and if there is no query string then it will display all data
public function VendorInfoFilter(Request $request)
{
$vendor = DB::table('schema.data as d')
->where('d.status','=',$request->status)
->orderBy('d.id')
->get();
return response()->json($vendor);
}
Take as reference, exact code might not work for you.
public function VendorInfoFilter(Request $request)
{
$vendor = DB::table('schema.data as d');
if (!empty($request->status_one)) {
$vendor = $vendor->where('d.status','=', $request->status_one);
}
if (!empty($request->status_two)) {
$vendor = $vendor->where('d.status','=', $request->status_two);
}
if (!empty($request->status_three)) {
$vendor = $vendor->where('d.status','=', $request->status_three);
}
if (empty($request->status_one) && empty($request->status_two) && empty($request->status_three)) {
$vendor= $vendor->where('d.status','=', $request->status_one)->where('d.status','=', $request->status_two)->where('d.status','=', $request->status_three);
}
$result = $vendor->orderBy('d.id')
->get();
return response()->json($result);
}
public function VendorInfoFilter(Request $request)
{
$vendor = DB::table('schema.data as d')
->when($request->status, function ($q, $status) {
return $q->where('d.status','=', $status);
})
->when($request->status_two, function ($q, $status_two) {
return $q->where('d.status_two','=', $status_two);
})
->orderBy('d.id')
->get();
return response()->json($vendor);
}

Laravel How I can return view data with respone json (both in 1 time)?

public function index(Request $request)
{
$search_book = $request->id;
$proc=DB::select(DB::raw("SELECT * FROM BOOKS WHERE BOOKID = '$Search_book'")
if ($search_book!="") {
return response()->json($proc);
return view('status.status',[
'proc' => $proc
]);
}
How to return 2 data
To determine if a request is an ajax request, you can use the ajax() method on a Request object injected into the controll action:
public function index(Request $request)
{
$results = DB::table('books')
->where('bookid', $request->id)
->get();
if ($request->ajax()) {
return response()->json($results);
}
return view('status.status', [
'proc' => $results
]);
}
I went ahead and fixed the SQL injection vulnerability in your query for you by swapping the query for a proper one. It could still be improved by using a Book model instead of a plain database query, but it is fine this way as well.
The query from your comment can be simplified by replacing the left join. Simply take the sub query as base and right join it with processspj:
DB::table('processtrans as pt')
->leftJoin('processmaster as pm', 'pm.pcm_id', '=', 'pt.pct_pcm_id')
->rightJoin('processspj as ps', 'ps.pc_id', '=', 'pt.pct_pc_id')
->where('pt.pct_pc_id', $request->id)
->select([
'ps.*',
'pm.pcm_bname',
'pt.created_at',
'pt.updated_at',
'pt.pct_id',
'pt.pct_leadtime',
'pt.pct_pcm_id',
'pt.pct_pc_id',
'pt.pct_planfinishdate',
'pt.pct_startdate',
'pt.pct_status',
])
->get();
$(document).ready(function(){
$("#dl_books").change(function()
{
var getValue=$(this).val();
$.ajax({
type: 'GET',
url: '{{route('status')}}',
data: {id:getValue},
success:function(data)
{
//Json for value textbox
$("#txtbookname").text(data[0].pcm_bname);
}
});
});
});
Just save the rendered view in a variable and do a json response:
public function index(Request $request) {
$results = DB::table('books')
->where('bookid', $request->id)
->get();
if ($results) {
$view = view('status.status', [
'proc' => $results
])->render();
return response()->json(['view'=> $view, 'proc' => '$results']);
}
}

Laravel paginate view don't see

I'm trying to do paginate in my view. I have reaaalyy alot of products, but I want only 12 per page. This is my controller:
public function index(Request $request)
{
$products = Product::paginate(12);
if ($request->has('colorValue')) {
$products->whereHas('productColors', function ($query) use ($request) {
$query->whereIn('id', $request->colorValue);
});
}
if ($request->has('heelValue')) {
$products->whereHas('productHeelTypes', function ($query) use ($request) {
$query->whereIn('id', $request->heelValue);
});
}
if ($request->has('materialValue')) {
$products->whereHas('productColors', function ($query) use ($request) {
$query->whereIn('id', $request->materialValue);
});
}
if ($request->has('maxPrice')) {
if($request->maxPrice > 0){
$products->where('sell_price_gross', '<=', $request->maxPrice);
}
}
$colors = ProductColor::all();
$heels = ProductHeelType::all();
$materials = ProductMaterial::all();
return view('product-list', ['products' => $products->get(), 'colors' => $colors, 'heels' => $heels, 'materials' => $materials]);
}
}
Now I'm trying to render it in my view:
<div class="paginate">
{{$products->render()}}
</div>
But I have error:
Type error: Too few arguments to function
Illuminate\Support\Collection::get(), 0 passed in /home/ania/Dokumenty/Projekty/viola-kiosk/vendor/laravel/framework/src/Illuminate/Pagination/AbstractPaginator.php on line 568 and at least 1 expected
What is wrong??
I think you can try this change your return view code like:
return view(
'product-list',
['products' => $products, 'colors' => $colors, 'heels' => $heels, 'materials' => $materials]
);

Resources