How to call a named function as a callback in laravel? - php

I got two functions in my model:
function getPersonsByGroup($groupId, $callback) {
$group = StutGroup::where('stg_id', $groupId)->get();
$persons = [];
foreach($group as $gr) {
foreach($gr->students as $stud) {
$persons[] = $stud->person;
}
}
return $callback(collect($persons));
}
function joinStudentsToPersons($person) {
return $person->each(function ($pers) {
$pers->student = \DB::connection('pgsql2')->table('students')->where('stud_pers_id', $pers->pers_id)->get();
});
}
I'm trying to call the function getPersonsByGroup in my controller passing the reference to the callback as follows:
$students = $studGroup->getPersonsByGroup($request->group, $studGroup->joinStudentsToPersons);
But if I pass an anonymous function to the getPersonsByGroup everything works well:
$students = $studGroup->getPersonsByGroup($request->group, function($person) {
return $person->each(function ($pers) {
$pers->student = \DB::connection('pgsql2')->table('students')->where('stud_pers_id', $pers->pers_id)->get();
});
});
What am I doing wrong?

The solution to your problem, if you want to keep this kind of structure, is to make the method return the closure like so:
function joinStudentsToPersons() {
return function ($person) {
$person->each(function ($pers) {
$pers->student = \DB::connection('pgsql2')->table('students')
->where('stud_pers_id', $pers->pers_id)
->get();
});
};
}
And then call it like:
$students = $studGroup->getPersonsByGroup($request->group, $studGroup->joinStudentsToPersons());

Related

RETURN values in PHP

I have 2 functions in PHP and i want to return a value to one function to another. this is my functions
public function save_payment_log_data($icasl_number, $exam_session) {
$paylog_av = $this->payment_log_exists($icasl_number, $exam_session);
}
function payment_log_exists($icasl_no, $exam_session) {
$this->db->where('icasl_no', $icasl_no);
$this->db->where('exam_session', $exam_session);
$query = $this->db->get('exm_paymentlog');
if ($query->num_rows() > 0) {
$pl = $query->row();
$pay_id = $pl->paylog_id;
return $pay_id;
} else {
return false;
}
}
I want to return $pay_id to the save_payment_log_data() function but in here $pay_id didn't return to that function. I think it's return from the function payment_log_exists()
so how can I return $pay_id to the save_payment_log_data() function
See this example it's working fine:
function save_payment_log_data() {
$paylog_av = payment_log_exists();
# print the return value
echo $paylog_av;
}
function payment_log_exists() {
return "Hello";
}
save_payment_log_data();
You can try to remove public and this form save_payment_log_data(),
and call the save_payment_log_data() function where you want.
your are only assigning a value to the $paylog_av your "save_payment_log_data" function should be:
public function save_payment_log_data($icasl_number, $exam_session) {
$paylog_av = $this->payment_log_exists($icasl_number, $exam_session);
return $paylog_av;
}

Filter models by multiples conditions in Laravel / Eloquent

I want to filter a list of products. The API is accessible in the route /q, I pass the filtering parameters like this /q?location=1,2&category=1,2,3 (if no arguments are passed, it will fetch all locations/categories.
public function getProductsByQuery()
{
$commaSeparatedLocations = Input::get('location');
$commaSeparatedCategories = Input::get('category');
if ($commaSeparatedLocations == null){
$numberOfLocations = Location::count();
for ($i=0;$i<=$numberOfLocations;$i++)
{
$locationsArray[$i] = $i;
}
} else {
$locationsArray = $this->toArray($commaSeparatedLocations);
}
if ($commaSeparatedCategories == null){
$numberOfCategories = Category::count();
for ($i=0;$i<=$numberOfCategories;$i++)
{
$categoriesArray[$i] = $i;
}
} else {
$categoriesArray = $this->toArray($commaSeparatedCategories);
}
return $products = Product::whereIn('category_id', $categoriesArray)->whereIn('location_id', $locationsArray)->paginate(config('app.products_per_page'));
}
public function toArray($commaSeparatedString)
{
return explode(",",$commaSeparatedString);
}
And well, it works. But I was wondering how can I improve my code. There must be a smarter way where not that many SQL queries are needed.
This looks much more readable to me:
public function getProductsByQuery()
{
$q = Product::query();
if (request('location')) {
$q->whereIn('location_id', $this->toArray(request('location')));
}
if (request('category')) {
$q->whereIn('category_id', $this->toArray(request('category')));
}
return $q->paginate(config('app.products_per_page'));
}
If you want to have a more complex query / with more parameters, you should have a look at https://github.com/Tucker-Eric/EloquentFilter
This is best way to filter sql query in laravel.
$q = Product::query();
$q->when(request('location'), function ($q) {
return $q->where('location', request('location'));
});
$q->when(request('category'), function ($q) {
return $q->where('category', request('category'));
});
$data['product_list'] = $q->paginate(5);
//OR
$data['product_list'] = $q->get(5);

Laravel, Method [...] does not exist

I have the controller:
class Comments extends Controller
{
public function GenerateComments($id)
{
$theme = DB::table('New_Themes')
->where('id', $id)
->get();
$Comments = NewTheme_Comment::where('id_theme', $id)->get();
$array = $this->tree($Comments);
function tree($Comments, $parent_id = 0, $level=0, $c=0)
{
global $var;
global $array;
global $m;
foreach($Comments as $Comment)
{
if ($Comment['parent_id'] == $parent_id) {
$m++;
$array[$m][0]=$Comment['id'];
If ($level > $var) {$var++; $array[$m][1]=0;} else {
if ($c < 0) $array[$m][1]=$var-$level+1; else {$c--; $array[$m][1]=0;};
$var=$level;
};
tree($Comments, $Comment['id'], $level+1,$c);
}
};
return $this->$array;
};
return view('comments', ['Themes'=> $theme, 'Comments'=> $Comments, 'Array' => $array]);
}
The problem is
Method [tree] does not exist.
but I don't understand why it appears, if I am calling a function within a function (like that below)
$array = $this->tree($Comments);
function tree($Comments, $parent_id = 0, $level=0, $c=0)
{
return $this->$array;
}
Are there any ideas why this isn't working?
You are calling your function tree with $this which means PHP will look tree as a method inside Comments class instead of your GenerateComments method.
Change
$array = $this->tree($Comments);
To this
$array = tree($Comments);
Note: You are also defining your function after you are calling it. PHP will look tree as it is in the namespace so it'll either won't work. Instead just define your function before you call it. Like so
function tree($Comments, $parent_id = 0, $level = 0, $c = 0) {
// ...
}
$array = tree($Comments);
It is also not recommended to define your function inside of a function. Instead doing that, just make your tree function a method inside your controller and use that instead. Like so
class Comments extends Controller
{
public function GenerateComments()
{
// ...
$array = $this->tree($comments);
}
public function tree($tree)
{
// ...
}
}
Your tree function is inside the controller GenerateComments function.
It appears you want to use it as a class method.
Try calling the function with call_user_func this way:
$array = call_user_func('tree', $Comments);

Laravel cookie in compose function

To build my menu i have a file Providers/ViewComposerServiceProvicer.php . in this file I have:
public function boot()
{
$this->composeNavigation();
}
public function composeNavigation()
{
view()->composer('front.layouts.menu', function ($view) {
$view->with('menuItems', \App\MenuItem::orderBy('priority', 'asc')->get());
});
}
What i want is add a where query based on a Coockie value like:
$brand = $request->cookie('brand');
// if value not set use default value.
if($brand == null)
{
$brand = 1;
}
view()->composer('front.layouts.menu', function ($view) {
//extra where function
$view->with('menuItems', \App\MenuItem::Where('brand','=',$brand)->orderBy('priority', 'asc')->get());
});
How can I get the coockie value in the compose function? Is there a special way to pass Request to my composeNavigation function?
EDIT i got it working but i cant access $brand in view()->composer(), if i copy my code inside the function i cant access request
My updated code :
public function boot(Request $request)
{
$this->composeNavigation($request);
}
public function composeNavigation(Request $request)
{
$coockieValue = $request->cookie('brand');
// if value not set use default value.
if($coockieValue == null)
{
$coockieValue = null;
}
$brands = \App\Brand::orderBy('priority', 'asc')->get();
foreach($brands as $brand){
if($brand->id == $coockieValue){
$brand->menuActive = true;
}
else{
$brand->menuActive = false;
}
}
view()->composer('front.layouts.menu', function ($view) {
$view->with('brandItems',$brands );
});
}

Mediator pattern passing data php

class Mediator {
protected $events = array();
public function attach($eventName, $callback) {
if (!isset($this->events[$eventName])) {
$this->events[$eventName] = array();
}
$this->events[$eventName][] = $callback;
}
public function trigger($eventName, $data = null) {
foreach ($this->events[$eventName] as $callback) {
$callback($eventName, $data);
}
}
}
$mediator = new Mediator;
$mediator->attach('stop', function() { echo "Stopping"; });
$mediator->attach('stop', function() { echo "Stopped"; });
$mediator->trigger('stop'); // prints "StoppingStopped"
I can't figure out how I can successfully pass data to the pattern, i.e. I would want to pass the database object, but it ends up like this.
$mediator->attach('test', function($test) { echo $test; });
$mediator->trigger('test', '123');
It prints out "test", not 123.
All you need is to replace :
$callback($eventName, $data);
With
$callback($data);
See Live Demo

Categories