A PHP array can have arrays for its elements. And those arrays can have arrays and so on and so forth. Is there a way to find out the maximum nesting that exists in a PHP array? An example would be a function that returns 1 if the initial array does not have arrays as elements, 2 if at least one element is an array, and so on.
20 Answers
Here's another alternative that avoids the problem Kent Fredric pointed out. It gives print_r() the task of checking for infinite recursion (which it does well) and uses the indentation in the output to find the depth of the array.
function array_depth($array) {
$max_indentation = 1;
$array_str = print_r($array, true);
$lines = explode("\n", $array_str);
foreach ($lines as $line) {
$indentation = (strlen($line) - strlen(ltrim($line))) / 4;
if ($indentation > $max_indentation) {
$max_indentation = $indentation;
}
}
return ceil(($max_indentation - 1) / 2) + 1;
}

- 172,675
- 36
- 177
- 197
-
31that's... actually quite clever. – Nathan Strong Nov 05 '08 at 17:15
-
3This function should return int instead of float (that comes from ceil). – Bell Nov 18 '15 at 03:47
This should do it:
<?php
function array_depth(array $array) {
$max_depth = 1;
foreach ($array as $value) {
if (is_array($value)) {
$depth = array_depth($value) + 1;
if ($depth > $max_depth) {
$max_depth = $depth;
}
}
}
return $max_depth;
}
?>
Edit: Tested it very quickly and it appears to work.

- 20,122
- 3
- 38
- 60

- 172,675
- 36
- 177
- 197
Beware of the examples that just do it recursively.
Php can create arrays with references to other places in that array, and can contain objects with likewise recursive referencing, and any purely recursive algorithm could be considered in such a case a DANGEROUSLY naive one, in that it will overflow stack depth recursing, and never terminate.
( well, it will terminate when it exceeds stack depth, and at that point your program will fatally terminate, not what I think you want )
In past, I have tried serialise -> replacing reference markers with strings -> deserialise for my needs, ( Often debugging backtraces with loads of recursive references in them ) which seems to work OK, you get holes everywhere, but it works for that task.
For your task, if you find your array/structure has recursive references cropping up in it, you may want to take a look at the user contributed comments here: http://php.net/manual/en/language.references.spot.php
and then somehow find a way to count the depth of a recursive path.
You may need to get out your CS books on algorithms and hit up these babies:
( Sorry for being so brief, but delving into graph theory is a bit more than suited for this format ;) )

- 22,212
- 11
- 70
- 132

- 56,416
- 14
- 107
- 150
After taking a little bit of inspiration here and after finding this RecursiveIteratorIterator thing in PHP Documentation, I came to this solution.
You should use this one, pretty neat :
function getArrayDepth($array) {
$depth = 0;
$iteIte = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach ($iteIte as $ite) {
$d = $iteIte->getDepth();
$depth = $d > $depth ? $d : $depth;
}
return $depth;
}
Works on both PHP5 and PHP7, hope this helps.

- 2,456
- 2
- 22
- 28
-
Unfortunately with testing this function returns one less, so with an array with depth 5 it returns `4`. – Martin May 07 '21 at 17:07
-
1Start counting from 0 is a normal behaviour in programming. If it triggers you, just add +1 to the result or change $depth to be equal to 1. – TwystO May 09 '21 at 09:30
-
Also this function does not work well with empty arrays or arrays that have keys but no values. – Martin May 09 '21 at 16:32
-
What do you mean by "does not work" ? Let me know which issue you encounter please. Works well here : http://sandbox.onlinephpfunctions.com/code/1afa7b74363e9c2d7df75b34055cb98ccc3941fb – TwystO May 10 '21 at 15:34
-
http://sandbox.onlinephpfunctions.com/code/de8685318a8aec49ae390948491e1e390bfa30c6 – Martin May 10 '21 at 15:50
-
Of course your code can't work as you haven't declared any array. Look carrefully at the warnings retruned when you push the "Execute code" button. – TwystO May 10 '21 at 16:52
-
` Warning: Undefined variable $array in [...][...] on line 3 Warning: Trying to access array offset on value of type null in [...][...] on line 3 Warning: Trying to access array offset on value of type null in [...][...] on line 3 Warning: Undefined variable $array in [...][...] on line 6 Fatal error: Uncaught TypeError: ArrayIterator::__construct(): Argument #1 ($array) must be of type array, null given in [...][...]:6 Stack trace: #0 [...][...](6): ArrayIterator->__construct(NULL) #1 {main} thrown in [...][...] on line 6 ` – TwystO May 10 '21 at 16:53
-
Great solution - the `->getDepth()` method was exactly what I was looking for. Thanks! – Rounin Jul 21 '23 at 13:26
-
1
Hi This is an alternative solution.
/*** IN mixed (any value),OUT (string)maxDepth ***/
/*** Retorna la profundidad maxima de un array ***/
function getArrayMaxDepth($input){
if( ! canVarLoop($input) ) { return "0"; }
$arrayiter = new RecursiveArrayIterator($input);
$iteriter = new RecursiveIteratorIterator($arrayiter);
foreach ($iteriter as $value) {
//getDepth() start is 0, I use 0 for not iterable values
$d = $iteriter->getDepth() + 1;
$result[] = "$d";
}
return max( $result );
}
/*** IN mixed (any value),OUT (bool)true/false, CHECK if can be used by foreach ***/
/*** Revisa si puede ser iterado con foreach ***/
function canVarLoop($input) {
return (is_array($input) || $input instanceof Traversable) ? true : false;
}

- 173
- 1
- 5
-
Simple since it doesn't use any hacks and lets PHP deal with it: http://php.net/RecursiveIteratorIterator.getDepth – SeanDowney Dec 05 '13 at 20:32
I had just worked out an answer to this question when I noticed this post. Here was my solution. I haven't tried this on a ton of different array sizes, but it was faster than the 2008 answer for the data I was working with ~30 pieces depth >4.
function deepness(array $arr){
$exploded = explode(',', json_encode($arr, JSON_FORCE_OBJECT)."\n\n");
$longest = 0;
foreach($exploded as $row){
$longest = (substr_count($row, ':')>$longest)?
substr_count($row, ':'):$longest;
}
return $longest;
}
Warning: this doesn't handle any edge cases. If you need a robust solution look elsewhere, but for the simple case I found this to be pretty fast.

- 6,040
- 3
- 33
- 42
-
Please note that the options param was not added until php 5.3, so you should convert $arr to an stdClass object if you need to use this answer with 5.2. – fncomp Oct 28 '10 at 21:06
-
1There is a big flaw with this approach. Having any colons in your array's text will return false positives. Thus ['x'=>'a:b:c'] will return a depth of 4. – Dieter Gribnitz May 22 '14 at 12:08
-
Good point, I put in a warning. I wrote this 4yrs ago and had totally forgotten about it. FWIW it was pretty fast under PHP 4.x I have no idea if this is still even remotely sane. – fncomp May 23 '14 at 18:11
Another (better) modification to the function from Jeremy Ruten:
function array_depth($array, $childrenkey = "_no_children_")
{
if (!empty($array[$childrenkey]))
{
$array = $array[$childrenkey];
}
$max_depth = 1;
foreach ($array as $value)
{
if (is_array($value))
{
$depth = array_depth($value, $childrenkey) + 1;
if ($depth > $max_depth)
{
$max_depth = $depth;
}
}
}
return $max_depth;
}
Adding a default value to $childrenkey allows the function to work for simple array with no keys for child elements, i.e. it will work for simple multi-dimensional arrays.
This function can now be called using:
$my_array_depth = array_depth($my_array, 'the_key_name_storing_child_elements');
or
$my_array_depth = array_depth($my_array);
when $my_array doesn't have any specific key for storing its child elements.

- 853
- 8
- 15
-
1Use '&' for variables to avoid copying them. I think it will improve your code's performance. For instance "foreach ($array as &$value)" – Mehran Oct 28 '12 at 12:20
-
Thanks for the suggestion. It's just that changing the parameter from pass-by-value to pass-by-reference (using "&") might need an overall modification to the code. For example, the **$max_depth** or **$depth** variable should also be passed during recursive call using "&" and the "return" statement should be discarded. The code would be a lot different from what Jeremy Ruten suggested. :) – Amir Syafrudin Oct 28 '12 at 15:10
-
Not really, all you need to do is to insert two ampersands. One in 'foreach' statement (as I mentioned before) and one other before the function parameter 'array_depth(&$array, '. I believe that suffices without anymore changes. – Mehran Oct 28 '12 at 17:19
-
I don't think I follow your logic. How is adding two ampersands will improve the performance of the function? Please elaborate more on this matter. I especially don't get the part about adding an ampersand inside the foreach. – Amir Syafrudin Oct 29 '12 at 02:26
-
1The two mentioned ampersands will prevent PHP from copying the array each time it is passed / iterated. When you are iterating an array in a foreach as `foreach ($arr as $key => $value)` each `$value` extracted is not the the same element in the original array but a copy of it. But when you write `foreach ($arr as $key => &$value)` the `$value` will be the exact element from the array and changing it will result in changing the original array. In your case it will prevent PHP from copying each array's element and thus improving the performance. – Mehran Oct 29 '12 at 14:54
-
Thanks for keeping up with me. :) Now I understand what you're trying to say about _avoid copying_ the array $value. I'm part of those programmers who use ampersands only if I want to modify the original variable. I've never actually use the ampersands to improve performance like you suggested. One question remains though, how much performance improvements are we talking about here? – Amir Syafrudin Oct 30 '12 at 06:56
-
To have an understanding on the amount of performance improvement, you need to think of how many copying do you avoid by using references. In your case it's a lot. In worst case scenario, for arrays (in fact it's more like a tree) with depth D and branching factor of B, you will be avoiding copying of `sum(sum(B^dd | dd=0~d) | d=D~0)` variables! – Mehran Nov 02 '12 at 08:24
-
I agree that it is a lot. I don't really understand your math notation but I think I get it. I'm imagining all the child copies the function will be creating before the _first_ function call (that starts the recursive function) terminates. I'll keep your suggestion in mind. Hopefully it will come in handy in my future projects. Thanks. – Amir Syafrudin Nov 02 '12 at 11:15
-
1Just a comment on using references. I could be wrong but I remember reading in some book a couple of years ago that php does not copy a variable until a change has been made to it. Thus there should not be a giant number of copies made but it would still act like a reference until one of the variables have a change made to it. Since no keys are modified and only read this should not cause any performance issues. As I said, I could be wrong on this but if someone knows if this is correct can you please verify? If I find a post on this I will confirm if this is true. – Dieter Gribnitz May 22 '14 at 12:25
Here's my slightly modified version of jeremy Ruten's function
// you never know if a future version of PHP will have this in core
if (!function_exists('array_depth')) {
function array_depth($array) {
// some functions that usually return an array occasionally return false
if (!is_array($array)) {
return 0;
}
$max_indentation = 1;
// PHP_EOL in case we're running on Windows
$lines = explode(PHP_EOL, print_r($array, true));
foreach ($lines as $line) {
$indentation = (strlen($line) - strlen(ltrim($line))) / 4;
$max_indentation = max($max_indentation, $indentation);
}
return ceil(($max_indentation - 1) / 2) + 1;
}
}
Things like print array_depth($GLOBALS)
won't error due to the recursion, but you may not get the result you expected.

- 15,135
- 7
- 67
- 64
An old question, yet remain relevant to this date. :)
Might as well contribute a minor modification to the answer from Jeremy Ruten.
function array_depth($array, $childrenkey)
{
$max_depth = 1;
if (!empty($array[$childrenkey]))
{
foreach ($array[$childrenkey] as $value)
{
if (is_array($value))
{
$depth = array_depth($value, $childrenkey) + 1;
if ($depth > $max_depth)
{
$max_depth = $depth;
}
}
}
}
return $max_depth;
}
I added a second parameter called $childrenkey because I store the child elements in a specific key.
An example of the function call is:
$my_array_depth = array_depth($my_array, 'the_key_name_storing_child_elements');

- 21
- 1
This one seems to work fine for me
<?php
function array_depth(array $array)
{
$depth = 1;
foreach ($array as $value) {
if (is_array($value)) {
$depth += array_depth($value);
break;
}
}
return $depth;
}

- 29
- 1
-
1This doesn't play nice when one of the later children of array is a deeper array then one of its antecedent siblings. – Bramus Feb 28 '19 at 09:30
function createDeepArray(){
static $depth;
$depth++;
$a = array();
if($depth <= 10000){
$a[] = createDeepArray();
}
return $a;
}
$deepArray = createDeepArray();
function deepness(array $arr){
$exploded = explode(',', json_encode($arr, JSON_FORCE_OBJECT)."\n\n");
$longest = 0;
foreach($exploded as $row){
$longest = (substr_count($row, ':')>$longest)?
substr_count($row, ':'):$longest;
}
return $longest;
}
function array_depth($arr)
{
if (!is_array($arr)) { return 0; }
$arr = json_encode($arr);
$varsum = 0; $depth = 0;
for ($i=0;$i<strlen($arr);$i++)
{
$varsum += intval($arr[$i] == '[') - intval($arr[$i] == ']');
if ($varsum > $depth) { $depth = $varsum; }
}
return $depth;
}
echo 'deepness():', "\n";
$start_time = microtime(TRUE);
$start_memory = memory_get_usage();
var_dump(deepness($deepArray));
$end_time = microtime(TRUE);
$end_memory = memory_get_usage();
echo 'Memory: ', ($end_memory - $start_memory), "\n";
echo 'Time: ', ($end_time - $start_time), "\n";
echo "\n";
echo 'array_depth():', "\n";
$start_time = microtime(TRUE);
$start_memory = memory_get_usage();
var_dump(array_depth($deepArray));
$end_time = microtime(TRUE);
$end_memory = memory_get_usage();
echo 'Memory: ', ($end_memory - $start_memory), "\n";
echo 'Time: ', ($end_time - $start_time), "\n";
The function proposed by Josh was definitely faster:
$ for i in `seq 1 10`; do php test.php; echo '-------------------------';done
deepness():
int(10000)
Memory: 164
Time: 0.0079939365386963
array_depth():
int(10001)
Memory: 0
Time: 0.043087005615234
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0076408386230469
array_depth():
int(10001)
Memory: 0
Time: 0.042832851409912
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0080249309539795
array_depth():
int(10001)
Memory: 0
Time: 0.042320966720581
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0076301097869873
array_depth():
int(10001)
Memory: 0
Time: 0.041887998580933
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0079131126403809
array_depth():
int(10001)
Memory: 0
Time: 0.04217004776001
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0078539848327637
array_depth():
int(10001)
Memory: 0
Time: 0.04179310798645
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0080208778381348
array_depth():
int(10001)
Memory: 0
Time: 0.04272198677063
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0077919960021973
array_depth():
int(10001)
Memory: 0
Time: 0.041619062423706
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0080950260162354
array_depth():
int(10001)
Memory: 0
Time: 0.042663097381592
-------------------------
deepness():
int(10000)
Memory: 164
Time: 0.0076849460601807
array_depth():
int(10001)
Memory: 0
Time: 0.042278051376343

- 287
- 3
- 11
I think this would solve the recursion problem, and also give the depth without relying on other php functions like serialize or print_r (which is risky at best and can lead to intractable bugs):
function array_depth(&$array) {
$max_depth = 1;
$array['__compute_array_depth_flag_ZXCNADJHHDKAQP'] = 1;
foreach ($array as $value) {
if (is_array($value) &&
!isset($value['__compute_array_depth_flag_ZXCNADJHHDKAQP'])) {
$depth = array_depth($value) + 1;
if ($depth > $max_depth) {
$max_depth = $depth;
}
}
}
unset($array['__compute_array_depth_flag_ZXCNADJHHDKAQP']);
return $max_depth;
}

- 11
- 1
I don't think there's anything built in. A simple recursive function could easily find out though.

- 8,776
- 2
- 23
- 16
-
Hmm. It seems like that would be a common thing that would be built in, but I just went over the array functions for the second time and it looks like you are right. – Thomas Owens Nov 04 '08 at 18:49
// very simple and clean approach
function array_depth($a) {
static $depth = 0;
if(!is_array($a)) {
return $depth;
}else{
$depth++;
array_map("array_depth", $a);
return $depth;
}
}
print "depth:" . array_depth(array('k9' => 'dog')); // return 1

- 11
- 1
-
@user699082 - if you have a problem with this post, don't scrawl your complaints all over the answer. Use the comments instead. – Kev Apr 08 '11 at 17:39
-
fail with deep X, in this case, deep = 2 -> `$Q = ARRAY(1, 2, 3, ARRAY(), ARRAY(), ARRAY()); echo array_depth($Q);` – Stackoverflow Jul 30 '21 at 13:43
I believe the problem highlighted by Kent Frederic is crucial. The answer suggested by yjerem and Asim are vulnerable to this problem.
The approaches by indentation suggested by yjerem again, and dave1010 are not stable enough to me because it relies on the number of spaces that represent an indentation with the print_r function. It might vary with time/server/platform.
The approach suggested by JoshN might be correct, but I think mine is faster :
function array_depth($arr)
{
if (!is_array($arr)) { return 0; }
$arr = json_encode($arr);
$varsum = 0; $depth = 0;
for ($i=0;$i<strlen($arr);$i++)
{
$varsum += intval($arr[$i] == '[') - intval($arr[$i] == ']');
if ($varsum > $depth) { $depth = $varsum; }
}
return $depth;
}
Post a message if you undertake any testing comparing the different methods. J

- 7,591
- 5
- 47
- 80
-
thanks @Jonathan H, your code run fine for me, only... ¿is really "confirmed/secure"? My question is becouse this soution depend of ``sintax of function json_encode()`` and... maybe is dangerous depend of sintaxis? – Stackoverflow Jul 30 '21 at 14:02
in my solution, I evaluate dimension of ARRAY(), not contents/values:
function Dim_Ar($A, $i){
if(!is_array($A))return 0;
$t[] = 1;
foreach($A AS $e)if(is_array($e))$t[] = Dim_Ar($e, ++ $i) + 1;
return max($t);
}
$Q = ARRAY(); // dimension one
$Q = ARRAY(1); // dimension one
$Q = ARRAY(ARRAY(ARRAY()), ARRAY(1, 1, 1)); // dimension is two
$Q = ARRAY(ARRAY()); // dimension is two
$Q = ARRAY(1, 1, 1, ARRAY(), ARRAY(), ARRAY(1)); // dimension is two
$Q = ARRAY(1, 2, 3, ARRAY(ARRAY(1, 1, 1))); // dimension is two
$Q = ARRAY(ARRAY(ARRAY()), ARRAY()); // dimension is three
$Q = ARRAY(ARRAY(ARRAY()), ARRAY()); // dimension three
$Q = ARRAY(ARRAY(ARRAY()), ARRAY(ARRAY())); // dimension is three
$Q = ARRAY('1', '2', '3', ARRAY('Q', 'W'), ARRAY('Q', 'W'), ARRAY('Q', 'W'), ARRAY('Q', 'W'), 'pol, y juan', 'sam, y som', '1', '2', 'OPTIONS1' => ARRAY('1', '2', '9'), 'OOO' => ARRAY('1', '2', '9'), 'OPTIONS3' => ARRAY('1', '2', '9', '1', '2', '9', '1', '2', '9', '1', '2', '9', '1', '2', '9'), '3', ARRAY('Q', 'W'), 'OPTIONS2' => ARRAY('1', '2'));
$Q = ARRAY('1', '2', '3', '', ARRAY('Q, sam', 'W', '', '0'), 'ppppppol, y juan', 'sam, y som', '1', '2', 'OPTIONS1' => ARRAY('1', '2', 'ss, zz'), '3', 'PP' => ARRAY('Q', 'WWW', 'Q', 'BMW'), ARRAY('Q', 'YYWW'), 'OPTIONS2' => ARRAY('1', '2', '9'), ARRAY('1', '2', '3'), '33', '33', '33', ARRAY('1', '2', '3', ARRAY(1, 2)));
echo Dim_Ar($Q, 0);
for me is speed, and low complex

- 449
- 5
- 13
I believe you forgot to filter '[' and ']' or ',' and ':' and the data type of the array's key(s) and value(s). Here's an update of your array_depth plus a bonus array_sort_by_depth.
function array_depth($arr){
if (is_array($arr)) {
array_walk($arr,
function($val, $key) use(&$arr) {
if ((! is_string($val)) && (! is_array($val))) {
$val = json_encode($val, JSON_FORCE_OBJECT);
}
if (is_string($val)) {
$arr[$key] = preg_replace('/[:,]+/', '', $val);
}
}
);
$json_strings = explode(',', json_encode($arr, JSON_FORCE_OBJECT));
$max_depth = 0;
foreach ($json_strings as $json_string){
var_dump($json_string); echo "<br/>";
$json_string = preg_replace('/[^:]{1}/', '', $json_string);
var_dump($json_string); echo "<br/><br/>";
$depth = strlen($json_string);
if ($depth > $max_depth) {
$max_depth = $depth;
}
}
return $max_depth;
}
return FALSE;
}
function array_sort_by_depth(&$arr_val, $reverse = FALSE) {
if ( is_array($arr_val)) {
$temp_arr = array();
$result_arr = array();
foreach ($arr_val as $key => $val) {
$temp_arr[$key] = array_depth($val);
}
if (is_bool($reverse) && $reverse == TRUE) {
arsort($temp_arr);
}
else {
asort($temp_arr);
}
foreach ($temp_arr as $key => $val) {
$result_arr[$key] = $arr_val[$key];
}
$arr_val = $result_arr;
return TRUE;
}
return FALSE;
}
Feel free to improve the code :D!

- 11
- 2
I would use the following code:
function maxDepth($array) {
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array), \RecursiveIteratorIterator::CHILD_FIRST);
$iterator->rewind();
$maxDepth = 0;
foreach ($iterator as $k => $v) {
$depth = $iterator->getDepth();
if ($depth > $maxDepth) {
$maxDepth = $depth;
}
}
return $maxDepth;
}

- 6,671
- 13
- 75
- 136
//Get the dimension or depth of an array
function array_depth($arr)
{
if (!is_array($arr)) return 0;
if (empty($arr)) return 1;
return max(array_map(__FUNCTION__,$arr))+1;
}

- 7,276
- 1
- 9
- 17
-
fail with deep X and values empty: `$Q = ARRAY(1, 2, 3, ARRAY()); echo array_depth($Q);` – Stackoverflow Jul 30 '21 at 13:40
-
The result is 2 and that's fine. The accepted solution from @Paige Ruten delivers that too. – jspit Aug 03 '21 at 09:59