I have one array that I am foreaching over:
array:8132 [
0 => {#551
"address_id": "94e224af-135f-af31-3619-535acfae9930"
"fiber_phase": "101"
"parsed_hash": "1bc7fb114ee10d7cb9cea10693d238b5"
"min_number": 400
"max_number": 499
"sales_rep": "164"
"id": "abd90d6b-28a8-2be6-d6c1-abd9007aef38"
"name": "48TH ST E"
"block_minimum": 400
"block_maximum": 498
}
Inside the foreach, I have another array, that I need to access certain properties for an if statement that will then add a new property to the original array ($data):
foreach ($data as $phase) {
$all_phases = EmeraldFiber::getPhases();
dd($all_phases);
if ($phase->fiber_phase === $all_phases[1]['name']) {
$phase->fiber_status = $all_phases[1]['fiber_status'];
}
return $data;
}
The dd($all_phases); looks like this:
array:270 [
1 => array:7 [
"id" => "10bc06d0-05de-07e2-b2de-5214fba5045a"
"name" => "1"
"description" => "50th France"
"encoded_points" => "_sbqGnesxPJwv#iJBKpv#fJ#"
"fiber_status" => "Live"
"status_date" => "2010-09-01 00:00:00"
]
With the above foreach, I am only getting the original array returned, without the new property fiber_status. Am I not returning it correctly? Or do I need to map over the second array ($all_phases) to access those properties properly?
I presume you don't need to return anything:
// receive object once instead receiving of it multiple times
$all_phases = EmeraldFiber::getPhases();
// extract required values
$phase_name = $all_phases[1]['name'];
$phase_status = $all_phases[1]['fiber_status'];
foreach ($data as $phase) {
if ($phase->fiber_phase === $phase_name) {
$phase->fiber_status = $phase_status;
}
}
// if you have this code in a function - return data here
// otherwise - you don't need return
// return $data;
Update:
If $all_phases is array with all available phases and you need to check if $phase->fiber_phase is among them, then you should do the following:
// receive object once instead receiving of it multiple times
$all_phases = EmeraldFiber::getPhases();
// create pairs
$phase_names = [];
foreach ($all_phases as $item) {
$phase_names[$item['name']] = $item['fiber_status'];
}
foreach ($data as $phase) {
// check if `$phase->fiber_phase` exists in `$phase_names`
if (isset($phase_names[$phase->fiber_phase])) {
// if it does - add it's value to `$phase` object
$phase->fiber_status = $phase_names[$phase->fiber_phase];
}
}
Related
I am iterating trough array in php and I got result like:
It's a an array with DOM elements within a DOM Crawler library.
{
"data": [
{
"content": null,
"property": null
},
{
"content": "Build your communication strategy and unleash the effectiveness and efficiency of your storytelling",
"property": null
}
}
...
In my code:
$crawler = new Crawler(file_get_contents($url));
$items =$crawler->filter('meta');
$metaData = [];
foreach ($items as $item) {
$itemCrawler = new Crawler($item);
$metaData[] = [
'content' => $itemCrawler->eq(0)->attr('content'),
'property' => $itemCrawler->eq(0)->attr('property')
];
}
What I try to accomplish is to get rid of rows where both fields are NULL like first one (if there is one of the fileds, like second one than skip).
Tried with array_filter() but with no success.
return array_filter($metaData, 'strlen');
Not sure why the first answer wouldn't be accepted. It would be just a bit of tweaks to make it work.
In your loop
$itemCrawler = new Crawler($item);
$content = $itemCrawler->eq(0)->attr('content');
$property = $itemCrawler->eq(0)->attr('property');
if(!is_null($content) || !is_null($property)) {
$metaData[] = compact('content', 'property');
}
Or if you insist on using array_filter after getting the $metaData array
$filteredMetaData = array_filter($metaData, function($item) {
return !is_null($item['content']) || !is_null($item['property']);
});
Actually, array_filter() works for empty elements.
Even if the element values are blank, if the keys are there, the blank values will not be removed.
In the code:
$item Has two keys
So, add explicit conditions to check for blank elements and please modify the code like:
$data = [];
$items =$service->get('allData');
foreach ($items as $item) {
if (! empty($item['content']) && ! empty($item['property'])) {
$data[] = [
'content' => $item['content'],
'property' => $item['property]
];
}
}
I have a very large object that I have to loop through to get a specific object.
I tried foreach($obj as $item), foreach($obj as $item => $value) and for in various configurations.
I want to get all the objects where the class is "table-responsive"
My Element looks like this (in JSON):
{
"dummy":"dummytext",
"children": [
{
"tag":null
},
{
"tag":"body",
"children": [
{
"class":"not_the_one"
},
{
"class":"table-responsive",
"html":"Gotcha!"
}
]
}
]
}
What I want to get as a result is:
{
"class":"table-responsive",
"html":"Gotcha!"
}
There could be more than one object that has the class of "table-responsive", so if there are multiple ones:
[
{
"class":"table-responsive",
"html":"Gotcha!"
},
{
"class":"table-responsive",
"html":"Gotcha!"
}
]
I was trying to accomplish a function that goes through all the elements and checks where the key of class equals "table-responsive" if so, push the object to an array. (array_push($result, $obj);) If the current element is an array, loop through it too. There can be a lot of dimensions so ideally the function calls itself. (recursive)
What you're after is a recursive reduce operation. Something that can
Iterate your elements
Capture any with the matching property, and
Perform the same operation on any children
// decode your JSON into an associative array
$data = json_decode($json, true);
// setup search parameters
$findKey = 'class';
$findValue = 'table-responsive';
// create a recursive reducer
$reducer = function($carry, $item) use (&$reducer, $findKey, $findValue) {
if (array_key_exists($findKey, $item) && $item[$findKey] === $findValue) {
// if this $item matches, add it to the $carry array
$carry[] = $item;
}
if (!empty($item['children'])) {
// this $item has children so dive deeper
return array_reduce($item['children'], $reducer, $carry);
}
// no children in this one so on to the next iteration
return $carry;
};
// Run the reducer at the top level.
// Note I've wrapped the root object in an array so the reducer can iterate it
$found = array_reduce([ $data ], $reducer, []);
// and display
echo json_encode($found, JSON_PRETTY_PRINT);
Demo ~ https://3v4l.org/6mWmC
I'm trying to add random numbers with array_push to an array in the field 'notes' => [] but I think I'm not doing it right since I do not see the random numbers stored in the array.
I am doing it in the following way:
$person1= [
'name' => 'person1',
'note' => []
];
$person2= [
'name' => 'person2',
'note' => []
];
$person3= [
'name' => 'person3',
'note' => []
];
$data=[$person1, $person2, $person3];
$_SESSION['data'] = $data;
function insertNumRandom(){
$data = $_SESSION['data'];
foreach ( $data as $student ) {
array_push($student['note'], rand(0,10));
}
}
function showNotes(){
foreach ( $data as $student ) {
echo implode($student['note']);
}
}
showNotes(); // To show the notes but it shows nothing.
You should change insertNumRandom like as below
function insertNumRandom(){
$data = $_SESSION['data'];
foreach ( $data as &$student ) {
array_push($student['note'], rand(0,10));
}
$_SESSION['data'] = $data;
}
showNotes function
function showNotes(){
$data = $_SESSION['data'];
foreach ( $data as $student ) {
echo implode($student['note']);
}
}
and call insertNumRandom before showNotes.
insertNumRandom();
showNotes();
You're referencing the $data with the "as" keyword which creates a new object.
You should instead iterate through the object you already have.
function insertNumRandom(){
$index = 0;
for($index = 0; $index<sizeof($data['data']); $index++ ) {
array_push($data[$index]['note'], rand(0,10));
}
}
try this maybe, still not sure how you're calling the insertNumRandom() function
function showNotes($arr){
foreach ( $arr as $student ) {
var_dump(implode($student['note']));
}
}
insertNumRandom();
showNotes($data);
you have a number of issues in your example.
First of all, the way you are using the $_SESSION object to pass some values to the function is not necessary, and not clean. You can either use global $data inside of the functions and they will suddenly have access to the $data variable from the parent scope. But even that is not very clean. I would suggest that you pass the data object by reference to the functions. That will make your function more portable and testable.
Your example is accessing the $student variable by value. All you need to do is to access it by reference by using the ampersand (&) in the foreach() like this foreach ( $data as &$student ) { ... }
I have noticed that you have never made a single call to insertNumRandom()
To have a better idea about what's in the arrays, I would suggest that you use a field separator for the implode() function and that you print a new line after imploding the array. I bet you will like the result.
Finally, just a word of advice ... array_push() lets you push one or more items in an array. But I personally use it only when I need to push multiple items in an array. For push just item new items, I use the short-hand $myArray[] = "new item";
So in practice, here is what your example will become ...
<?php
// Since you are not reusing $person1, $person2 and $person3 beyond the initialization
// phase, then let's keep things cleaner.
$data[] = [
'name' => 'person1',
'note' => []
];
$data[] = [
'name' => 'person2',
'note' => []
];
$data[] = [
'name' => 'person3',
'note' => []
];
/**
* In this function signature, the & means that the argument is passed by reference.
* That make it possible for the function to change the value of the argument.
*/
function insertNumRandom(&$theData) {
// The foreach() also needs to use $student by reference so that we can modify it
// by adding the random number to it.
foreach($theData as &$student) {
$student['note'][] = rand(0,10);
}
}
/**
* No need to pass $theData by reference because the function will not change its value.
*/
function showNotes($theData) {
// Here, the foreach() is using student by value because we do not need to change it's value.
foreach($theData as $student) {
echo implode($student['note'], ', ') . "\n";
}
}
// Inserting some random notes 3 times.
insertNumRandom($data);
insertNumRandom($data);
insertNumRandom($data);
showNotes($data); // To show the notes but it shows nothing.
?>
What I want to achieve?
"product_attributes": [
{
"title": "Color",
"records": [
{
"attribute_name": "black",
"mpr": "100"
},
{
"attribute_name": "green",
"mpr": "200"
}
]
},
{
"title": "RAM",
"records": [
{
"attribute_name": "16GB",
"mpr": "10"
}
]
},
{
"title": "RAM",///remove this whole obeject
"records": []
}
]
what I have tried: I fetch whole attributes from the DB and then compare it to product attribute and made this format now the problem is when I start traversing its comparing result from all attribute which creates an empty object every time my if() condition fails.
how can I remove empty object having empty records array and reindex my final array?
here is my code :
$allattributes = DB::table('product_attributes')->where('subcategory_id', $product->subcat_id)->get(['attribute_title']);
$valuesnew = DB::table('current_product_attribute_values')->where('product_id', $product->id)->get();
$emptybool=false;
// checking for empty attributes
if ($valuesnew->count() > 0) {
// first foreach for 3 value
foreach ($allattributes as $name) {
//echo $name->attribute_title;
$boo = false;
// 40 record loop
$records = array();
foreach ($valuesnew as $compare) {
// if attibute title are same
if ($compare->attribute_title == $name->attribute_title) {
if ($boo == false) {
$titledata = $name->attribute_title;
$holddata['title'] = $titledata;
$boo = true;
}
$records[] = array("attribute_name" => $compare->attribute_value, "mpr" => $compare->attribute_mrp);
}
}
$holddata['records'] = $records;
$final[] = $holddata;
}
} else {
$final = array();
}
what i have tried:
foreach($final as $k=>$arr){
//$final=array_filter($arr,'count');
if(array_filter($arr,'count') || array_values(array_filter($arr))){
unset($arr[$i]);
}
$i++;
}
print_r($final);//failed
TEST CASE:
Fetching all attributes from the subcategories of which product belongs to.
fetching all product attributes from product attribute table
then comparing the title of all attributes with product attributes when found the same record I have put this in inside the array. so I achieve color=>red, black this type of structure instead of color=>red, color=>black
now the test case is when all attributes have 4 attributes color, size, ram, processor, and product having only two color and ram at this case my loop give me empty record as with the last title I want to remove that object having an empty record.
thanks in advance :)
**NEW TRY: **
foreach($final as $k=>$arr){
foreach($arr as $key=>$value){
$count=count($value);
if($count==0){
echo '<pre>';
echo ' am empty object remove me ';
'<br>';
unset($arr[$index]);//failed how can i remove this whole object from the main array
}
}
Someone already posted using filter its definitely the solution for you. You don't need to have get the data from the database to use a collection.
collect($productAttributesArray).filter(function($product){
return !empty($product->records);
}
you could try to filter the collection for rows the doesn't have record.
$withRecordsOnly = collect($product_attributes)->filter(function ($item) {
return !empty($item->records);
});
$product_attributes is the same array you have foreached. what this do is convert the array to a collection and filter out all object with a non empty records.
I have a class which allows to retrieve an array according to the syntax "key.key2.key3".
For now, no problem. Problems occur when one of the keys is an object.
Because I have to check that the key is an array or an object
My script bug when I try to determine if type of key[key2] == array or if type of key->key2 == object. One of the two conditions may be false. (If script tests that key[key2] == array, and that key2 is an object, for example).
Is there a way to verify that key2 is an array or an object without doing key[key2] or key->key2 ?
Thanks.
You need to perform the test on the parent, before accessing the key.
Here is an example:
function findValue($a, $s) {
$keys = explode(".", $s);
foreach ($keys as $key) {
if (is_object($a)) {
$a = $a->$key;
} else if (is_array($a)) {
$a = $a[$key];
} else { // unexpected
return null;
}
}
return $a;
}
// Sample data: mix of object and array:
$arr = [
"key1" => (object) [
"key2" => [
"key3" => 42
]
]
];
echo findValue($arr, "key1.key2.key3"); // 42
What about is_array()?
Docs here