Laravel Advanced Wheres how to pass variable into function? - php

Example in doc:
DB::table('users')
->whereExists(function($query)
{
$query->select(DB::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
But what if I need to use external variable like that:
->where('city_id', '=', $this->city->id)
->where(function($query)
{
$query->where('name', 'LIKE', '%'.$searchQuery.'%')
->orWhere('address', 'LIKE', '%'.$searchQuery.'%')
})
For now I created new property and accessed it through $this->, but is there any more convenient way?

You can pass the necessary variables from the parent scope into the closure with the use keyword.
For example:
DB::table('users')->where(function ($query) use ($activated) {
$query->where('activated', '=', $activated);
})->get();
More on that here.
EDIT (2019 update):
PHP 7.4 (will be released at November 28, 2019) introduces a shorter variation of the anonymous functions called arrow functions which makes this a bit less verbose.
An example using PHP 7.4 which is functionally nearly equivalent (see the 3rd bullet point below):
DB::table('users')->where(fn($query) => $query->where('activated', '=', $activated))->get();
Differences compared to the regular syntax:
fn keyword instead of function.
No need to explicitly list all variables which should be captured from the parent scope - this is now done automatically by-value. See the lack of use keyword in the latter example.
Arrow functions always return a value. This also means that it's impossible to use void return type when declaring them.
The return keyword must be omitted.
Arrow functions must have a single expression which is the return statement. Multi-line functions aren't supported at the moment. You can still chain methods though.

#kajetons' answer is fully functional.
You can also pass multiple variables by passing them like: use($var1, $var2)
DB::table('users')->where(function ($query) use ($activated,$var2) {
$query->where('activated', '=', $activated);
$query->where('var2', '>', $var2);
})->get();

If you are using Laravel eloquent you may try this as well.
$result = self::select('*')
->with('user')
->where('subscriptionPlan', function($query) use($activated){
$query->where('activated', '=', $roleId);
})
->get();

You can pass variables using this...
$status =1;
$info = JOBS::where(function($query) use ($status){
$query->where('status',$status);
})->get();
print_r($info);

Related

passed variable in nested where query in laravel 9

I am trying to use variable to nested where() query in laravel 9 but i get an error that variable Undefined
my code:
public function edit($id)
{
$category = Category::findOrFail($id);
$parents = Category::
where('status' , 'active')
->where('id' , '<>' , $id)
->where(function($query){
return $query
->whereNull('parent_id')
->orWhere('parent_id', '<>', $id);
})->get();
}
the error:
Undefined variable $id
$parents = Category::
where('status' , 'active')
->where('id' , '<>' , $id)
->where(function($query) use ($id) { <-- problem is here
return $query
->whereNull('parent_id')
->orWhere('parent_id', '<>', $id);
})->get();
in this section of your code: ->where(function($query){ you need use keyword to pass value inside this inner function as below:
->where(function($query) use ($id) { .. };
the detail for this action is:
The closure is a function assigned to a variable, so you can pass it around
A closure is a separate namespace, normally, you can not access variables defined outside of this namespace. There comes the use keyword:
use allows you to access (use) the succeeding variables inside the closure.
use is early binding. That means the variable values are COPIED upon DEFINING the closure. So modifying $id inside the closure has no external effect, unless it is a pointer like an object is.
You can pass in variables as pointers like in case of &$id. This way, modifying the value of $total DOES HAVE an external effect, the original variable's value changes.
Variables defined inside the closure are not accessible from outside the closure either.
Closures and functions have the same speed. Yes, you can use them all over your scripts.
for more info read this.

Object of class Illuminate\Database\Query\Builder could not be converted to string in Laravel

I'm trying to add orwhere using the below syntax for searching :
->where(function($query) {
$query->where(DB::raw("g.title"), 'LIKE', "%{$query}%");
$query->orWhere(DB::raw("s.step"), 'LIKE', "%{$query}%");
})
but I'm receiving the below error
Object of class Illuminate\Database\Query\Builder could not be converted to string
It is working fine if I used the normal syntax as below :
->where(DB::raw("g.title"), 'LIKE', "%{$query}%")
->orwhere(DB::raw("s.step"), 'LIKE', "%{$query}%")
But I will add another where condition, so I have to use the first syntax.
You are defining $query twice. Both in your where() Closure and as a value. Also when you use closures and what to access values from outside the scope you have to use the use() statement. This code is not included but i assume it looks something similar to this and will work like that.
// replace this with whatever $query is in your code, from outside the closure scope
$search = $request->get('query');
Model::query()
->where(function($query) use ($search) {
$query->where(DB::raw("g.title"), 'LIKE', "%{$search}%");
$query->orWhere(DB::raw("s.step"), 'LIKE', "%{$search}%");
})
->get();

Laravel Eloquent Query -> Undefined Variable

Attached is a screenshot of the error I am facing. I have the log show the value of the $team variable. What am I doing wrong?
You don't have access to parents variables from a closure, you need to explicitly send variables to the closure with use keyword
function($query) use ($team)
Use forget to use $team variable inside your closure. It must be function($query) use ($team)
$data = User::whereHas('roles' => function($query) use ($team) {
$query->where('role_code', '=', $team)
})->get();

How Laravel anonymous function know it's parameter

Consider this code:
$fn = FormNilai::whereHas('mataPelajaranLokalGuru',function($mlg) {
$mlg->where('guru_id','=',$this->uid);
})->get();
How is $mlg always treated as FormNilai instance? how is the scenario? I read a lot about dependency injection but still don't get the point.
Dependency Injection is a different part. As per your code example, You need to the tell the anonymous function to use that variable like...
$uid = $this->uid;
$fn = FormNilai::whereHas('mataPelajaranLokalGuru',function($mlg) use($uid)
{
$mlg->where('guru_id','=',$uid);
})->get();
As that variable uid is outside the scope of the anonymous function it needs to be passed in using the use keyword as shown in the above code.
You can get more idea on use with example here
The parameter $mlg isn't treated as FormNilai instance, it's just treated as an instance of Illuminate\Database\Eloquent\Builder.
You can see that how it works in the source codes.
Illuminate/Database/Eloquent/Builder.php#L934
Example:
Define an anonymous function accepts an regular argument:
$example = function ($arg) {
var_dump($arg);
};
$example("hello");
You can change the argument name to any string, just like $myArgument.
And the the output would not been changed whatever the argument name is.
Laterally i've realize that laravel support php anonymous style so we can implement such a javascript function usage but surely it hard for me to do for first time
For simple usage, they display an example like this
$users = User::with(array('posts' => function($query)
{
$query->where('title', 'like', '%first%');
}))->get();
What if the user wanted to make the third parameter is filled with variable. When i check it out with replacing those '%first%' word with any global variable, it ruins the structure, and it happend to me.
$title = 'heirlom of marineford';
$users = User::with(array('posts' => function($query)
{
$query->where('title', 'like', $title);
}))->get();
After searching to PHP documentation, i found that the technique to passing parameter to that anonymous function by extending function block with use() so the function would assume to use all variable that defined by the use() section
$title = 'heirlom of marineford';
$users = User::with(array('posts' => function($query) use($title)
{
$query->where('title', 'like', $title);
}))->get();
I hope that could help you

Laravel inner join saying variable undefined

I am doing a search to filter through users that are displayed on my screen. The display of the users is working without the search. However when I type in the search a name, and go to display it, I get an undefined variable for search.
$Search = $request->search_code; //print_r($Search);die(); // this works
// this next line was used for testing and it works as well
//$findTrainers = DB::table('users')->where('users.name', 'like', "%$Search%")->get();
// This is what we want to work, but the search variable is now undefined
$findTrainers = DB::table('users')
->join('bios', function ($findTrainers) {
$findTrainers->on('users.id', '=', 'bios.user_id')
->where('users.name', 'like', "%$Search%");
})
->get();
This is due to how closures and scoping work. Closures don't know about variables defined outside of their scope, so you must tell a closure to use that variable when you want to access it within the scope of the closure, like this:
$findTrainers = DB::table('users')
->join('bios', function ($findTrainers) use ($Search){
$findTrainers->on('users.id', '=', 'bios.user_id')
->where('users.name', 'like', "%$Search%");
})
->get();

Categories