How Laravel anonymous function know it's parameter - php

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

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.

Access to out-of-scope variable within anonymous functions in Laravel (PHP)

I want to seed the related tables in Laravel. I had a problem in access to the out-of-scope variable inside the anonymous function which I had defined for whereHas methods to put "where" conditions on my has queries.
$id = $user->id; // out-of-scope variable
$posts = Post::whereHas('comments', function ($query) {
$query->where('user_id', $id);
})->get();
Technically I don't have access to $id inside the anonymous function.
This isn't a Laravel question, but a PHP one. Just add use ($variable) after the parameter list:
$posts = Post::whereHas('comments', function ($query) use ($id) {
$query->where('user_id', $id);
})->get();

Laravel Advanced Wheres how to pass variable into function?

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

laravel how to pass the paramters to the query scope?

look at code first:
$bookname = 'www';
User::with(array('roles' => function($query) {
$query->where('bookname' => $bookname);
}))->find(1);
but it lead an error"undefined variable $bookname"..how to fix this?thanks
Wrong syntax.
$bookname = 'www';
User::with(array('roles' => function($query) use ($bookname) {
$query->where('bookname', '=', $bookname);
}))->find(1);
To use the $bookname inside of the anonymous function you need to pass it using use statement. In addition where() function inside your anonymous function takes 3 parameters:
column name, comparing operator, search value.

Query builder: passing argument to anonymous function

I got a problem in passing variable to query builder closure, here is my code:
function get_usersbyname($name){
dd($name);
$resultset = DB::table('users')->where(function($query){
$query->where('username', 'LIKE', $name);
});
....
}
if I run it, it returns an error "undefined name variable", but I already passed $name variable and checked its existence.
Also I cann't find any resouce explains how to pass variable to query builder anonymous function.
Could you help me with this problem?
You need to the tell the anonymous function to use that variable like...
Because that variable is outside the scope of the annonymous function it needs to be passed in using the use keyword as shown in the example below.
function get_usersbyname($name){
dd($name);
$resultset = DB::table('users')->where(function($query) use ($name) {
$query->where('username', 'LIKE', $name);
});
....
}

Categories