How do I call an Eloquent function with arguments? - laravel

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()
..
..

Related

How to stop records coming back if relationship doesn't exist (Laravel)

I'm trying to stop 'addons' coming back in the AddonGroup if it doesn't have a 'productAddon'.
Is there a way this can be achieved?
Current Code:
$addonGroups = AddonGroup::whereIn("id", $addonGroups)
->whereHas(['addons.productAddon' => function ($query) use ($customise) {
$query->where('product_reference', $customise->package_reference);
}])
->with('addons')
->with(['addons.productAddon' => function ($query) use ($customise) {
$query->where('product_reference', $customise->package_reference);
}])
->with('addons.removals')
->get()->each(function($addonGroup) {
foreach ($addonGroup->addons as $key => $value) {
if ($value["image_key"]) {
$value["image_key"] = env("AWS_UPLOADS_URL") . $value["image_key"];
}
}
});
'addons':
public function addons() {
return $this->hasMany("App\Addon", "addon_group_id", "id")->where('active', 1);
}
'productAddon':
public function productAddon() {
return $this->hasOne("App\ProductAddon", "addon_id", "id")->without('product');
}
Error with current solution:
Call to a member function getRelationExistenceQuery() on array
After a lot of coffee and running multiple tests, I have finally answered my own question and came up with this solution:
$addonGroups = AddonGroup::whereIn("id", $addonGroups)
->with(["addons" => function ($query) use ($customise) {
$query->whereHas("productAddon", function ($builder) use ($customise) {
$builder->where('product_reference', $customise->package_reference);
})
->with('productAddon', 'removals');
}])
->get();

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) {
}

Create function with query in model, 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));
}

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 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