Add some logic in array filing - php

I'm trying to fill an array and I want to add some logic in it so it won't give me back errors...
Here is the code:
$entries_mixes = array();
foreach ($entries_query->result_array() as $entry) {
$entries_mixes[] = array('title' => $entry['title'],
'body' => $entry['body'],
'author' => $entry['author'],
'date_time' => $entry['date_time'],
'id' => $entry['id'],
'mix_name' => $mix['name'],
'photo_name' =>$photo['name']
);
}
what I want to do is to be able to check if some of the variables exist before I put them into the array....
so for example if(isset($mix['name'])) then insert to array or else do nothing
The point is not having undeclared variables trying to be inserted to my array cause it gives back errors...thanks!

You can use the ? : ternary operator:
$entries_mixes[] = array(
'title' => (isset($entry['title']) ? $entry['title'] : null),
'author' => (isset($entry['author']) ? $entry['author'] : null),
...
alternatively, use empty() for the check

You could use the ternary operator so that if the variables don't exist, NULL is used as the value. But you actually want to omit certain keys from the array altogether in that case. So just set each key separately:
$entry[] = array();
...
if (isset($mix['name'])) {
$entry['mix_name'] = $mix['name'];
}
...
$entries_mixes[] = $entry;

The following will check if title doesn't exists in the entry array or if it's blank. If so, it'll skip the entry completely and continue to the next element in the loop.
$entries_mixes = array();
foreach ($entries_query->result_array() as $entry) {
if (empty($entry['title'])) {
continue;
}
$entries_mixes[] = array('title' => $entry['title'],
'body' => $entry['body'],
'author' => $entry['author'],
'date_time' => $entry['date_time'],
'id' => $entry['id'],
'mix_name' => $mix['name'],
'photo_name' =>$photo['name']
);
}

Related

Copying a multidimensional array

I get() an multidimensional array and store it inside the $products variable.
I need to Make a copy of that array to create it into a new Webshop because the export provided by the API does not work so I have created this script to copy the data:
foreach ($products as $id => $product) {
$copy = $products[$id];
$createdProducts = $apiSkylux->products->create(
array(
'id' => $copy['id'],
'createdAt' => $copy['createdAt'],
'updatedAt' => $copy['updatedAt'],
'isVisible' => $copy['isVisible'],
'visibility' => $copy['visibility'],
'data01' => $copy['data01'],
'data02' => $copy['data02'],
'data03' => $copy['data03'],
'url' => $copy['url'],
'title' => $copy['title'],
'fulltitle' => $copy['fulltitle'],
'description' => $copy['description'],
'content' => $copy['content'],
'set' => $copy['set'],
'brand' => $copy['brand'],
'categories' => $copy['categories'],
'deliverydate' => $copy['deliverydate'],
'image' => $copy['image'],
'images' => $copy['images'],
'relations' => $copy['relations'],
'reviews' => $copy['reviews'],
'type' => $copy['type'],
'attributes' => $copy['attributes'],
'supplier' => $copy['supplier'],
'tags' => $copy['tags'],
'variants' => $copy['variants'],
'movements' => $copy['movements'],
)
);
}
The copy is working. But i thought #2016 and all, can't this be achieved with less lines of code?
This is what I receive with var_dump of the first array:
var_dump($products[0]);
exit;
//result
array(28) {
["id"]=>
int(26136946)
//rest of array
So I can see the array has a number (28) , what does this represent?
I've tried several attempts, closest attempt was :
$copy = $products[$id];
$createProducts = $products;
$createdProducts = $apiSkylux->products->create($createProducts);
But then I also got an error : Invalid data input
Can I copy the data from the array easier then the method I am currently using?
array(
'id' => $copy['id'],
...
)
This can be reduced to simply:
$copy
Yes, reassigning every single key into a new array is the same as using the original array in the first place.
foreach($products as $id => $product){
$copy = $products[$id];
This can be reduced to:
foreach ($products as $product){
$copy = $product;
Obviously you could leave out $copy entirely and just use $product.
Bottom line:
foreach ($products as $product) {
$createdProducts = $apiSkylux->products->create($product);
}
What you do with $createdProducts I don't know; you don't seem to be doing anything with it inside the loop, so at best it'll hold the last product after the loop, so is probably superfluous.
Probably you could do:
array_map([$apiSkylux->products, 'create'], $products);
or
$createdProducts = array_map([$apiSkylux->products, 'create'], $products);
depending on whether you need the return values or not.
So I can see the array has a number (28) , what does this represent?
It means it's an array with 28 elements in it.
This doesn't make any sense. Simply use the $product variable within the loop. Done!

Remove deeply nested element from multi-dimensional array?

I need to remove an element form a deeply nested array of unknown structure (i.e. I do not know what the key sequence would be to address the element in order to unset it). The element I am removing however does have a consistent structure (stdObject), so I can search the entire multidimensional array to find it, but then it must be removed. Thoughts on how to accomplish this?
EDIT: This is the function I have right now trying to achieve this.
function _subqueue_filter_reference(&$where)
{
foreach ($where as $key => $value) {
if (is_array($value))
{
foreach ($value as $filter_key => $filter)
{
if (isset($filter['field']) && is_string($filter['field']) && $filter['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
{
unset($value[$filter_key]);
return TRUE;
}
}
return _subqueue_filter_reference($value);
}
}
return FALSE;
}
EDIT #2: Snipped of array structure from var_dump.
array (size=1)
1 =>
array (size=3)
'conditions' =>
array (size=5)
0 =>
array (size=3)
...
1 =>
array (size=3)
...
2 =>
array (size=3)
...
3 =>
array (size=3)
...
4 =>
array (size=3)
...
'args' =>
array (size=0)
empty
'type' => string 'AND' (length=3)
...so assuming that this entire structure is assigned to $array, the element I need to remove is $array[1]['conditions'][4] where that target is an array with three fields:
field
value
operator
...all of which are string values.
This is just a cursor problem.
function recursive_unset(&$array)
{
foreach ($array as $key => &$value) # See the added & here.
{
if(is_array($value))
{
if(isset($value['field']) && $value['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
{
unset($array[$key]);
}
recursive_unset($value);
}
}
}
Notes : you don't need to use is_string here, you can just make the comparison as you're comparing to a string and the value exists.
Don't use return unless you're sure there is only one occurrence of your value.
Edit :
Here is a complete example with an array similar to what you showed :
$test = array (
1 => array (
'conditions' =>
array (
0 => array ('field' => 'dont_care1', 'value' => 'test', 'operator' => 'whatever'),
1 => array ('field' => 'dont_care2', 'value' => 'test', 'operator' => 'whatever'),
2 => array ('field' => 'nodequeue_nodes_node__nodequeue_subqueue.reference', 'value' => 'test', 'operator' => 'whatever'),
3 => array ('field' => 'dont_care3', 'value' => 'test', 'operator' => 'whatever')
),
'args' => array (),
'type' => 'AND'
));
var_dump($test);
function recursive_unset(&$array)
{
foreach ($array as $key => &$value)
{
if(is_array($value))
{
if(isset($value['field']) && $value['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
{
unset($array[$key]);
}
recursive_unset($value);
}
}
}
recursive_unset($test);
var_dump($test);
One way to solve this was to extend your recursive function with a second parameter:
function _subqueue_filter_reference(&$where, $keyPath = array())
You'd still do the initial call the same way, but the internal call to itself would be this:
return _subqueue_filter_reference($value, array_merge($keyPath, array($key)));
This would provide you with the full path of keys to reach the current part of the array in the $keyPath variable. You can then use this in your unset. If you're feeling really dirty, you might even use eval for this as a valid shortcut, since the source of the input you'd give it would be fully within your control.
Edit: On another note, it may not be a good idea to delete items from the array while you're looping over it. I'm not sure how a foreach compiles but if you get weird errors you may want to separate your finding logic from the deleting logic.
I have arrived at a solution that is a spin-off of the function found at http://www.php.net/manual/en/function.array-search.php#79535 (array_search documentation).
Code:
function _subqueue_filter_reference($haystack,&$tree=array(),$index="")
{
// dpm($haystack);
if (is_array($haystack))
{
$result = array();
if (count($tree)==0)
{
$tree = array() + $haystack;
}
foreach($haystack as $k=>$current)
{
if (is_array($current))
{
if (isset($current['field']) && is_string($current['field']) && $current['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
{
eval("unset(\$tree{$index}[{$k}]);"); // unset all elements = empty array
}
_subqueue_filter_reference($current,$tree,$index."[$k]");
}
}
}
return $tree;
}
I hate having to use eval as it SCREAMS of a giant, gaping security hole, but it's pretty secure and the values being called in eval are generated explicitly by Drupal core and Views. I'm okay with using it for now.
Anyway, when I return the tree I simply replace the old array with the newly returned tree array. Works like a charm.

Add up values in an array in an array

I am trying to add up a specific variable (gq_numplayers) and display it. How can I do that if the arrays are in an array?
I am using GameQ (https://github.com/Austinb/GameQ/) if you don't understand what is going on.
EDIT:
var_dump ($results);
http://pastebin.com/BSeeWMEb
<?php
// Include the main class file
require '../GameQ.php';
// Define your servers,
// see list.php for all supported games and identifiers.
$servers = array(
array(
'id' => 'server 1',
'type' => 'css',
'host' => '216.52.148.30',
),
array(
'id' => 'server 2',
'type' => 'css',
'host' => '216.52.143.83',
),
array(
'id' => 'server 3',
'type' => 'teamspeak3',
'host' => 'voice.xenogamers.org:8730',
)
);
// Init the class, only need this once
$gq = new GameQ();
$gq->addServers($servers);
//optional settings
$gq->setOption('timeout', 3); // Seconds
$gq->setOption('debug', TRUE);
// You can optionally specify some output filters,
// these will be applied to the results obtained.
$gq->setFilter('normalise');
// Send requests, and parse the data
$results = $gq->requestData();
//make total
$total = array_sum(?!?!?!??!?!?);
echo $results['server 1']['gq_numplayers'];
?>
Just loop through the servers and add the number of players to a running total.
$num_players = 0;
foreach ($results as $server) {
$num_players += (int)$server['gq_numplayers'];
}
If you have $ArrayB inside $ArrayA, then you need a loop. Loop through $ArrayA with foreach like this:
foreach ($ArrayA as $item) {
}
Inside that loop, you need to add the code to operate on $item. So each time the loop iterates, $item will be the next item in the array! You can add them all up with a variable declared before entering the loop such as $counter.
But I am also noticing you indicated this:
echo $results['server 1']['gq_numplayers'];
That is NOT an array in an array. That is a single two-dimensional array. So my answer wouldn't even apply directly to it. You'd have to change the loop somewhat.
You could try adding it yourself via array_walk().
I'm not sure about the $results structure after the requestData() call but let's assume it looks like the sample array below:
<?php
$results= array(
array(
'something' => 'text',
'gq_numplayers' => 1,
),
array(
'something' => 'text',
'gq_numplayers' => 2,
),
array(
'something' => 'text',
'gq_numplayers' => 3,
),
);
$total=0;
array_walk($results,function($value,$key) use(&$total) {
$total+=(int)$value['gq_numplayers'];
});
print $total."\n";

If/Else Ternary Operator with Blank Else Statement Issue

Usually I can get away with using something like:
$a = ($condition)? array(1,2,3) : '';
But now I have a method that accepts a multidimensional array and I must pass or not pass one of the arrays conditionally.
$this->mymethod(
'myarrays'=> array(
array('key' => 'lang_code'),
array('key' => 'lang_description'),
array('key' => 'lang_direction'),
($mycondition==true)? array('key' => 'lang_export') : ),
)
);
Basically, the issue is with the last array passed. And more specifically the ELSE statement in the ternary If operator. It seems that I can't pass simply a blank space after the : and I can't pass anything else like FALSE or '' (empty string), because later on in the code the foreach that runs through this array gives errors.
My question is:
How to pass a parameter to a function/method based on a condition?
array_filter(array(
array('key' => 'lang_code'),
array('key' => 'lang_description'),
array('key' => 'lang_direction'),
$mycondition ? array('key' => 'lang_export') : null),
));
This will remove the null
Use:
$mycondition? array('key' => 'lang_export') : null
Now, you could simply run it through array_filter(..), to remove that NULL element.
Aim for readability, not for how can you type less. The ternary operator is great because in certain cases it increases readability. This is certainly not that case.
Be nice to the people reading your code later, including yourself.
Here is an example (comments are the thoughts of the future reader):
//OK, so here we have an array
$array = array(
array('key' => 'lang_code'),
array('key' => 'lang_description'),
array('key' => 'lang_direction'),
);
//So the array can have one more element based on this condition
if ($mycondition) {
$array[] = array('key' => 'lang_export');
}
//And then we pass this array to the method
$this->mymethod(array('myarrays' => $array));
You are free to use variables and don't have to write all your code in one statement (well, I must admit I thought that was cool earlier).
You could evaluate the condition before the function call, e.g. with a helper-function:
function evaluate_condition (array $mandatory, array $optional, $condition) {
if (true === $condition) {
$mandatory[] = $optional;
}
return $mandatory;
}
$this->mymethod(
'myarrays'=> $this->evaluate_condition(
array(
array('key' => 'lang_code'),
array('key' => 'lang_description'),
array('key' => 'lang_direction')
),
array('key' => 'lang_export'),
$mycondition
)
);

Need help about array

What do
$categories[$id] = array('name' => $name, 'children' => array());
and
$categories[$parentId]['children'][] = array('id' => $id, 'name' => $name);
mean?
Thanks a lot.
How should i format the output so i can learn the results that was returned?
You can format your code into tables by looping on the array using for or foreach. Read the docs for each if you don't have a grasp on looping.
2.What does
$categories[$id] = array('name' => $name, 'children' => array());
and
$categories[$parentId]['children'][] = array('id' => $id, 'name' => $name);
The first line assigns an associative array to another element of the $categories array. For instance if you wanted the name of the category with ID of 6 it would look like this:
$categories[6]['name']
The second line does something similar, except when you are working with an array in PHP, you can use the [] operator to automatically add another element to the array with the next available index.
What is the uses of .= ?
This is the concatenation assignment operator. The following two statements are equal:
$string1 .= $string2
$string1 = $string1 . $string2
These all have to do with nesting arrays.
first example:
$categories[$id] = array('name' => $name, 'children' => array());
$categories is an array, and you are setting the key id to contain another array, which contains name and another array. you could accomplish something similar with this:
$categories = array(
$id => array(
'name' => $name,
'children' => array()
)
)
The second one is setting the children array from the first example. when you have arrays inside of arrays, you can use multiple indexes. It is then setting an ID and Name in that array. here is a another way to look at example #2:
$categories = array(
$parentID => array(
'children' => array(
'id' = $id,
'name' => $name
)
)
)
note: my two ways of rewriting are functionally identical to what you posted, I'm just hoping this makes it easier to visualize what's going on.

Categories