How to save values outside of a Laravel each loop - php

I am not fully understanding Laravel Collections.
I need to know how save external values while iterating through a Lavavel Collection using the each(function(n){})
For example:
static public myFunction($laravelCollection) ={
$arr=[];
$laravelCollection->each(function($a){
$arr[]=$a
});
return $arr
}
...
$exampleArr = SomeClass::myFunction($aCollection);
var_dump($exampleArr);
//desired results: the var_dump of the collection
It seams that $arr inside of the each function is local to the function. How can I accomplish the above? I realize that if it was NOT a static function, I could simply use a $this->arr instead, but I need to do the above using a static function.

Modifying a variable inside a laravel collection, you will have to use use() method with reference &.
$arr = [];
$laravelCollection->each(function($a) use(&$arr) {
$arr[] = $a;
});
Or even better, since you are simply converting your collection into an array:
$arr = $laravelCollection->toArray();
Check out the collection docs.

Related

how to map collection in php laravel

i want return data if a < b then a = b, if using foreach i have to make empty array first and parsing data to te empty array, how if record i much, that take time
public function getDepreciation(){
$values = $this->repository->getDepreciation();
$data = [];
foreach($values as $value){
if($value->depresiation_per_month > $value->balance_value){
$value->depresiation_per_month = $value->balance_value;
}
array_push($data,$value->depresiation_per_month,$value->balance_value);
}
return $data;
}
is there is simple code than my above, since i have to make relist many array
You can convert this array in a Collection then handle it easier by using the transform method.
First you have to create the collection using your array Create Collection
$values = collect($values);
Then you can iterate over the collection using the transform method and apply your logic Transform Method
Finally you have to convert your collection into an array using the toArray method toArray Method
I hope this works for you

Class-Wide accessible static array, trying to push to it, but keeps coming back empty

class UpcomingEvents {
//Variable I'm trying to make accessible and modify throughout the class methods
private static $postObjArr = array();
private static $postIdArr = array();
private static $pinnedPost;
//My attempt at a get method to solve this issue, it did not
private static function getPostObjArr() {
$postObjArr = static::$postObjArr;
return $postObjArr;
}
private static function sortByDateProp($a, $b) {
$Adate = strtotime(get_field('event_date',$a->ID));
$Bdate = strtotime(get_field('event_date',$b->ID));
if ($Adate == $Bdate) {
return 0;
}
return ($Adate < $Bdate) ? -1 : 1;
}
private static function queryDatesAndSort($args) {
$postQuery = new WP_Query( $args );
if( $postQuery->have_posts() ) {
while( $postQuery->have_posts() ) {
$postQuery->the_post();
//Trying to push to the array, to no avail
array_push(static::getPostObjArr(), get_post());
}
}
//Trying to return the array after pushing to it, comes back empty
return(var_dump(static::getPostObjArr()));
//Trying to sort it
usort(static::getPostObjArr(), array(self,'sortByDateProp'));
foreach (static::getPostObjArr() as $key => $value) {
array_push(static::$postIdArr, $value->ID);
}
}
}
I'm trying to access $postObjArr within the class, and push to it with the queryDatesAndSort(); method. I've tried a couple of things, most recent being to use a get method for the variable. I don't want to make it global as it's bad practice I've heard. I've also tried passing by reference I.E
&static::$postObjArr;
But when it hits the vardump, it spits out an empty array. What would be the solution and best practice here? To allow the class methods to access and modify a single static array variable.
static::$postObjArr[] = get_post()
I didn't think it would of made a difference, but it worked. Can you explain to me why that worked but array.push(); Did not?
Arrays are always copy-on-write in PHP. If you assign an array to another variable, pass it into a function, or return it from a function, it's for all intents and purposes a different, new array. Modifying it does not modify the "original" array. If you want to pass an array around and continue to modify the original array, you'll have to use pass-by-reference everywhere. Meaning you will have to add a & everywhere you assign it to a different variable, pass it into a function, or return it from a function. If you forget your & anywhere, the reference is broken.
Since that's rather annoying to work with, you rarely use references in PHP and you either modify your arrays directly (static::$postObjArr), or you use objects (stdClass or a custom class) instead which can be passed around without breaking reference.

PHP - Getting an array of instantiated objects having an array of classes

My question is what is a neat way to obtain an array of objects from an array of classes.
The array of classes I get by using array_filter() on get_declared_classes().
EDIT:
My own attempts were pretty correct, the thing was I forgot to return value of in_array() in callback function :
$classes_array = array_filter(
get_declared_classes(),
function($class_name){
return in_array('IItem', class_implements($class_name));
}
$objects_array;
foreach($classes_array as $class){
$objects_array[] = new $class();
}
You can use array_map(), and refer to Creating PHP class instance with a string
$objects = array_map(function($v){
return new $v();
}, get_declared_classes());

What Interface to implement so an object behave like an array [duplicate]

I have a class called Collection which stores objects of same type.
Collection implements array interfaces: Iterator, ArrayAccess, SeekableIterator, and Countable.
I'd like to pass a Collection object as the array argument to the array_map function. But this fails with the error
PHP Warning: array_map(): Argument #2 should be an array
Can I achieve this by implementing other/more interfaces, so that Collection objects are seen as arrays?
The array_map() function doesn't support a Traversable as its array argument, so you would have to perform a conversion step:
array_map($fn, iterator_to_array($myCollection));
Besides iterating over the collection twice, it also yield an array that will not be used afterwards.
Another way is to write your own map function:
function map(callable $fn)
{
$result = array();
foreach ($this as $item) {
$result[] = $fn($item);
}
return $result;
}
Update
Judging by your use-case it seems that you're not even interested in the result of the map operation; therefore it makes more sense to use iterator_apply().
iterator_apply($myCollection, function($obj) {
$obj->method1();
$obj->method2();
return true;
});
array_map wants, as the name suggests, arrays. It's not called iterator_map after all. ;)
Apart from iterator_to_array(), which produces a potentially large temporary array, there's no trick to make iterable objects work with array_map.
The Functional PHP library has a map implementation which works on any iterable collection.
If you're not interested in creating a new array that is a function mapped over the original array, you could just use a foreach loop (because you implement Iterator).
foreach($item in $myCollection) {
$item->method1();
$item->method2();
}
if you actually want to use map, then I think you'll have to implement your own. I would suggest making it a method on Collection, eg:
$mutatedCollection = $myCollection->map(function($item) {
/* do some stuff to $item */
return $item;
});
I would ask yourself if you really want to use map or do you really just mean foreach
I came up with the following solution:
//lets say you have this iterator
$iterator = new ArrayIterator(array(1, 2, 3));
//and want to append the callback output to the following variable
$out = [];
//use iterator to apply the callback to every element of the iterator
iterator_apply(
$iterator,
function($iterator, &$out) {
$current = $iterator->current();
$out[] = $current*2;
return true;
},
array($iterator, &$out) //arguments for the callback
);
print_r($out);
This way, you can generate an array without iterating twice as you would to with the approach like:
$iterator = new ArrayIterator(array(1,2,3));
$array = iterator_to_array($iterator); //first iteration
$output = array_map(function() {}, $array); //second iteration
Good luck!
I just stumbled upon this question and I managed to cast the collection to an array to make it work:
array_map($cb, (array) $collection);
disclaimer For the original question this might not be a suitable option but I found the question while looking to solve a problem which I solved with this solution. I would recommend using a custom iterator map where possible/viable.
another option is to do something like this:
foreach($collection as &$item) {
$item = $cb($item);
}
which will mutate the underlying collection.
EDIT:
It has been pointed out that casting to an array can have unwanted side effects. It would be better to add a method to your collection to return the array from the iterator, and traverse that, or otherwise add a map method which accepts a callback and run a loop on the underlying iterator.

Using a function in php - what am I doing wrong?

$users = [
"Andrew",
"Max",
"Larry",
"Ricardo",
"Lucy",
"Marcus",
"Sophie"
];
$sector_rel = [];
$location_rel = [];
function sectorRel($user){
return sector_rel[] = round(1/rand(1,10),3);
}
function locationRel($user){
return $location_rel[] = round(1/rand(1,20),3);
}
foreach($users as $user){
sectorRel($user);
locationRel($user);
}
This:
function sectorRel($user){
return sector_rel[] = round(1/rand(1,10),3);
}
Should be/could be:
function sectorRel($user){
global sector_rel;
sector_rel[] = round(1/rand(1,10),3);
}
The problem is that the functions don't have access to the array variables. You can import them into the function scope using the keyword global, if they are indeed global variables. Now, having global variables isn't a good thing, and for a small test it's okay, but eventually you'll be eliminating your globals and this solution won't work.
But alternatively, you could pass the array variables to the function as an argument. However, this still introduces a lot of logic in the function. The function has to be told about the array, it must know that it needs to add a value to the end, and it also needs to calculate the actual value to add.
So better, make the function just return the calculated value and add it to the array outside of the function:
function sectorRel($user){
// Assuming your are going to use 'user' here somewhere?
return round(1/rand(1,10),3);
}
function locationRel($user){
return round(1/rand(1,20),3);
}
foreach($users as $user){
sector_rel[] = sectorRel($user);
$location_rel[] = locationRel($user);
}
You can then wrap this entire snippet of code into another function and call that to populate the arrays. That way, you've quite reasonably split the responsibilities of the functions and have a piece of code that looks nice and clean.
You do not need to use return in either of sectorRel or locationRel. At the moment this will return the reference to that array and it is not being stored in a variable. You would need to store them in a variable or just get rid of the return. My PHP is a little weak at the moment but you should probably append the values in those functions to the array.
Also if you have a parameter called $user for each of those functions you should either use that parameter or just get rid of it.

Categories