I have a very complex array which contains many other very complex nested arrays. I want to break up some of the inside array groups into separate variables outside of the main variable for readability, however I'm not sure what the correct syntax is for having a list of multiple arrays in a single variable.
Wrapping the list of arrays in an array while declaring the variable isn't an option, as the variable will be inserted inside the wrapper array later on in the $array variable, so the list of arrays need to be on their own and not inside an array in the $sub_arrays variable.
<?php
$sub_arrays = array(), array(), array(); // syntax error
$array = array(
'template' => array(
array(
array(),
array(
array(),
// syntax error
$sub_arrays,
// this works, but need to be declared outside
// array(), array(), array(),
array(),
)
),
),
);
print_r($array);
https://3v4l.org/2EvRA
Alternatively, separating some of the sub arrays into another .php file and using include() and return would also be an option instead of the variable? But I'm not sure about the syntax of that either.
Separation would be good not just for readability, but in case a particular group of arrays need to be reused in another instance as well.
The data is a WordPress block editor (Gutenberg) template with a lot of nested group and column blocks inside other blocks. https://developer.wordpress.org/block-editor/developers/block-api/block-templates/#nested-templates
Is this even possible to do in PHP?
New Answer:
Based on the comments below I think I understand the problem. I can think of two solutions to this.
First solution:
The first one is the easy one, but you need PHP 7.4+ for it to work.
You can use a new feature called the slant operator (...) where by you can "unpack" one array into another. Here is the example:
<?php
$sub_arrays = [array("middle" => "array"), array(), array("external"=>"array")];
$array = array(
'template' => array(
array(
array(),
array(
array('first'=>"array"),
...$sub_arrays, // use it here
array('last'=>"array")
)
),
),
);
print_r($array);
Live demo: https://3v4l.org/s4Q8u
Second solution: This is a bit more complex that the first one. It involves wrapping the array into a function and dynamically creating the parent array of $sub_arrays. See this:
<?php
$sub_arrays = [array("middle" => "array"), array(), array("external"=>"array")];
function create_array($sub) {
$parent_array[] = array('first'=>"array");
foreach($sub as $s)
{
$parent_array[] = $s;
}
$parent_array[] = array('last'=>"array");
$array = array(
'template' => array(
array(
array(),
$parent_array
),
),
);
return $array;
}
print_r(create_array($sub_arrays));
Live demo: https://3v4l.org/1Vahd
I hope this helps.
Old Answer:
Your questions leaves out a lot of details to understand why you are trying to do this.
For example:
Wrapping the list of arrays in an array while declaring the variable
isn't an option,
how is $sub_array inserted in $array, at what stage, are they inside a class or a function?
In any case, from what I understood, I think list is what you are looking for.
See this example:
<?php
list($a, $b) = [array('example' => 'test'), array('another' => 'array')];
var_dump($a, $b);
you can also use list for nested arrays like so:
list($a, list($b, $c)) = [array('example' => 'test'), array(array('another' => 'array'), array('I am nested'=>'array'))];
var_dump($a, $b, $c);
Could you try this:
<?php
$sub_arrays = array(array(), array(), array()); // no syntax error
$array = array(
'template' => array(
array(
array(),
array(
array_merge(
array(array()),
$sub_arrays),
array(),
)
),
),
);
print_r($array);
To make it work, you have to merge your "outsider" array with the existing one. The existing one must be encapsulated in an array
Im not sure what you are asking for, but if it is how to create array variables and use them later, then here is an example. I took the WordPress example you linked in the comments. This is the template arrays broken down into sections. The structure seems to follow a pattern, hopefully this clarifies it.
$templateTop = array(
'core/paragraph' => array(
'placeholder' => 'Add a root-level paragraph',
)
);
$column1 = array(
'core/column',
array(),
array(
array(
'core/image',
array()
),
)
);
$column2 = array(
'core/column',
array(),
array(
array(
'core/paragraph',
array(
'placeholder' => 'Add a inner paragraph'
)
),
)
);
$templateColumns = array(
'core/columns',
array(),
array(
$column1, $column2
)
);
$template = array(
$templateTop, $templateColumns
);
You may prefer the shorter array syntax available since PHP 5.4
<?php
$arr1 = ['a', 'b', 'c']; // >= 5.4
$arr2 = array('a', 'b', 'c'); // < 5.4
See here for information about short syntax and arrays in general: https://www.php.net/manual/en/language.types.array.php
Using the short syntax your nested array may look like this:
<?php
$arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
The example above is a two dimensional nested array. The outer array has three elements which are arrays itself.
In order to include / require an array (or any other value) from another PHP file just do it like so $returnValue = require('./other_file.php').
In other_file.php something like this will work:
<?php
return [
[
[1, 2, 3],
[4, 5, 6],
],
[
[9, 8, 7],
[6, 5, 4],
],
];
Hope this helps.
I'm going to attempt to simplify the problem, and define some variables as follows
$firstArray = $a;
$subArrays = [$i, $j, $k];
$lastArray = $z;
where $a, $i, $j, $k, and $z are all arrays
I believe what you are trying to achieve is
$result = [$a, $i, $j, $k, $z]
without referencing the variables $a, $i, $j, $k, or $z
This can be achieved using array_merge(), providing that the arrays are not associative with duplicate keys
$result = array_merge([$firstArray], $subArrays, [$lastArray]);
Which is equivalent to
$result = array_merge([$a], [$i, $j, $k], [$z]);
By wrapping the $firstArray and $lastArray in arrays of their own, this puts them at the same level of nesting as the $subArrays before combining them all into one array
Applying this all to your original problem, and using the longer syntax, results in
$sub_arrays = array(array(), array(), array()); // Wrapped
$array = array(
'template' => array(
array(
array(),
array_merge(
array(array()), // Wrapped
$sub_arrays,
array(array()), // Wrapped
),
),
),
);
I'm following this tutorial but have been struggling to understand a step in the insert_row() method. Here is the method in full:
// Adds new row to table
public function insert_row($data, $type='') {
global $wpdb;
// set defaults
$data = wp_parse_args( $data, $this->get_column_defaults());
do_action('add_pre_insert_' . $type, $data);
// initialise column format array
$column_formats = $this->get_columns();
// force fields to lower case
$data = array_change_key_case($data);
// remove unknown columns
$data = array_intersect_key($data, $column_formats);
// reorder $column_formats to match the order of columns in $data
$data_keys = array_keys($data);
$column_formats = array_merge(array_flip($data_keys), $column_formats);
$wpdb->insert($this->table_name, $data, $column_formats);
do_action('add_post_insert_'.$type, $wpdb->insert_id, $data);
return $wpdb->insert_id;
}
I cannot understand why the author assigns array_keys($data) to $data_keys then calls array_flip($data_keys) on the next line. What is happening there?
As I understand it, the keys of $data and array_flip($data_keys) are exactly the same. Though the values of array_flip($data_keys) would be 0,1,2,3,4,... But why? Wouldn't $column_formats overwrite those values anyway?
Ok,
So array_keys gets the keys of an array, so if you have this array
['one'=>'foo', 'two'=>'bar']
You get this from array keys:
[ 0 => 'one', 1=>'two']
Now if you flip that you get
['one' => 0, 'two' => 1]
AS to why, I have no idea. I would have to look deeper into the code and I would need some actual data that is used here.
You can test it with this bit of code (FYI I did this first bit in my head):
$a=['one'=>'foo', 'two'=>'bar'];
var_export($a);
$a = array_keys($a);
var_export($a);
$a = array_flip($a);
var_export($a);
Outputs:
array (
'one' => 'foo',
'two' => 'bar',
)array (
0 => 'one',
1 => 'two',
)array (
'one' => 0,
'two' => 1,
)
You can test it here
Once you add array_merge in any keys that exist will be replaced. Now if it was me just from a conceptual point, assuming you don't want those number in there if a key is missing, I would have used array_fill_keys instead of array_flip
$a=['one'=>'foo', 'two'=>'bar'];
var_export($a);
$a = array_keys($a);
var_export($a);
$a = array_fill_keys($a, '');
var_export($a);
Outputs
array (
'one' => 'foo',
'two' => 'bar',
)array (
0 => 'one',
1 => 'two',
)array (
'one' => '',
'two' => '',
)
As you can see the last array has just an empty string for the value, the previous way if an item is missing you get the number as the left over value. This way you would get an empty string as the left over value.
See it here
But like I said there is no way to know what their intent was without knowing what the data is that this works on. I am just "assuming" here (to make my point)
I have an array like this:
$a = array(
'key1' => 'value1',
'key2' => 'value2',
'key3' => array(
'key4' => 'value4',
'key5' => array(
'key6' => 'value6'
)
)
);
as you can see there are inner arrays inside $a
Now, I have a list of keys, example:
key1
key4
key6
I need a script that search if those key exists, and if exists change their values.
I Need to change their values with base64_encode($value_of_the_key)
so Maybe a callback that get the current value and convert it using base64_encode() function.
COuld someone help me?
I'm tring to see the current php functions but it seems there is not ones that do this thing.
THanks
EDIT:
Using the follow code i can get the keys in the callback....but the problem is:
How can i modify the values directly in the array? I Mean.... ok ... i get key and value, but how to change the value in the original array? ($a)
$a = array(
'key1' => 'value1',
'key2' => 'value2',
'key3' => array(
'key4' => 'value4',
'key5' => array(
'key6' => 'value6'
)
)
);
function test($item, $key)
{
echo "$key. $item<br />\n";
}
array_walk_recursive($a, 'test');
array_walk_recursive() with callback supplied should help. More info here.
I have two arrays
they look like
$a1 = array(
array('num' => 1, 'name' => 'one'),
array('num' => 2, 'name' => 'two'),
array('num' => 3, 'name' => 'three'),
array('num' => 4, 'name' => 'four'),
array('num' => 5, 'name' => 'five')
)
$a2 = array(3,4,5,6,7,8);
I want to end up with an array that looks like
$a3 = array(3,4,5);
so basically where $a1[$i]['num'] is in $a2
I know I could do
$a3 = array();
foreach($a1 as $num)
if(array_search($num['num'], $a2))
$a3[] = $num['num'];
But that seems like a lot of un-needed iterations.
Is there a better way?
Ah Snap...
I just realized I asked this question the wrong way around, I want to end up with an array that looks like
$a3 array(
array('num' => 3, 'name' => 'three'),
array('num' => 4, 'name' => 'four'),
array('num' => 5, 'name' => 'five')
)
You could extract the relevant informations (the 'num' items) from $a1 :
$a1_bis = array();
foreach ($a1 as $a) {
$a1_bis[] = $a['num'];
}
And, then, use array_intersect() to find what is both in $a1_bis and $a2 :
$result = array_intersect($a1_bis, $a2);
var_dump($result);
Which would get you :
array
2 => int 3
3 => int 4
4 => int 5
With this solution :
you are going through $a1 only once
you trust PHP on using a good algorithm to find the intersection between the two arrays (and/or consider that a function developed in C will probably be faster than any equivalent you could code in pure-PHP)
EDIT after the comment : well, considering the result you want, now, I would go with another approach.
First, I would use array_flip() to flip the $a2 array, to allow faster access to its elements (accessing by key is way faster than finding a value) :
$a2_hash = array_flip($a2); // To speed things up :
// accessing by key is way faster than finding
// an item in an array by value
Then, I would use array_filter() to apply a filter to $a1, keeping the items for which num is in the $a2_hash flipped-array :
$result = array_filter($a1, function ($item) use ($a2_hash) {
if (isset($a2_hash[ $item['num'] ])) {
return true;
}
return false;
});
var_dump($result);
Note : I used an anonymous function, which only exist with PHP >= 5.3 ; if you are using PHP < 5.3, this code can be re-worked to suppress the closure.
With that, I get the array you want :
array
2 =>
array
'num' => int 3
'name' => string 'three' (length=5)
3 =>
array
'num' => int 4
'name' => string 'four' (length=4)
4 =>
array
'num' => int 5
'name' => string 'five' (length=4)
Note the keys are not corresponding to anything useful -- if you want them removed, just use the array_values() function on that $result :
$final_result = array_values($result);
But that's probably not necessary :-)
I need to sort an array by its keys based on the order of the values in another array.
Simple example:
$sort_array = array( 'key1', 'key2' );
$array_that_needs_sorting = array( 'key2' => 'value2', 'key1' => 'value1' );
After sorting, the array should be:
array( 'key1' => 'value1', 'key2' => 'value2' );
If you know the $sort_array keys are all present in the array that needs to be sorted, you can do this:
$sorted = array_merge(array_flip($keys), $unsorted);
where $keys is $sort_array and $unsorted is $array_that_needs_sorting.
You might take a look at Sort an Array by keys based on another Array?. It should give you an idea on how to accomplish that.
array_merge(array_combine($sort_array, array_fill(0, count($sort_array), null))
, $array_that_needs_sorting);