Skip to content

Instantly share code, notes, and snippets.

@mcaskill
Last active January 3, 2024 10:15
  • Star 91 You must be signed in to star a gist
  • Fork 26 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save mcaskill/baaee44487653e1afc0d to your computer and use it in GitHub Desktop.
PHP : Groups an array by a given key

array_group_by

(PHP 5 >= 5.4)
array_group_by — Groups an array by a given key.

Description

array|null array_group_by( array $array, mixed $key1 [, mixed $... ] )

Groups an array into arrays by a given $key, or set of keys, shared between all array members.

Based on Jake Zatecky's array_group_by() function.

This fork offers:

  • $key parameter can be a closure

Parameters

  • $array — The array to have grouping performed on.

  • $key — The key to group or split by. Can be a string, an integer, a float, or a callback. If the key is NULL, the iterated element is skipped. If the key is a callback, it must return a valid key from the array.

    string|int callback ( mixed $item )

  • ... — Additional keys for grouping the next set of sub-arrays.

Return Values

Returns a multidimensional array, with each dimension containing elements grouped by the passed key(s).

Errors/Exceptions

If $key is not one of the accepted types E_USER_ERROR will be thrown and NULL returned.

Examples

Example #1 array_group_by() example

$records = [
	[
		"state"  => "IN",
		"city"   => "Indianapolis",
		"object" => "School bus"
	],
	[
		"state"  => "IN",
		"city"   => "Indianapolis",
		"object" => "Manhole"
	],
	[
		"state"  => "IN",
		"city"   => "Plainfield",
		"object" => "Basketball"
	],
	[
		"state"  => "CA",
		"city"   => "San Diego",
		"object" => "Light bulb"
	],
	[
		"state"  => "CA",
		"city"   => "Mountain View",
		"object" => "Space pen"
	]
];

$grouped = array_group_by( $records, "state", "city" );

The above example will output:

Array
(
	[IN] => Array
		(
			[Indianapolis] => Array
				(
					[0] => Array
						(
							[state] => IN
							[city] => Indianapolis
							[object] => School bus
						)

					[1] => Array
						(
							[state] => IN
							[city] => Indianapolis
							[object] => Manhole
						)

				)

			[Plainfield] => Array
				(
					[0] => Array
						(
							[state] => IN
							[city] => Plainfield
							[object] => Basketball
						)

				)

		)

	[CA] => Array
		(
			[San Diego] => Array
				(
					[0] => Array
						(
							[state] => CA
							[city] => San Diego
							[object] => Light bulb
						)

				)

			[Mountain View] => Array
				(
					[0] => Array
						(
							[state] => CA
							[city] => Mountain View
							[object] => Space pen
						)

				)

		)
)

Installation

With Composer

$ composer require mcaskill/php-array-group-by

Without Composer

Why are you not using composer? Download Function.Array-Group-By.php from the gist and save the file into your project path somewhere.

{
"name": "mcaskill/php-array-group-by",
"description": "Groups an array by a given key.",
"license": "MIT",
"authors": [
{
"name": "Chauncey McAskill",
"email": "chauncey@mcaskill.ca",
"homepage": "https://github.com/mcaskill"
}
],
"keywords": [
"function"
],
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"require": {
"php": ">=5.4.0"
},
"autoload": {
"files": ["Function.Array-Group-By.php"]
}
}
<?php
if (!function_exists('array_group_by')) {
/**
* Groups an array by a given key.
*
* Groups an array into arrays by a given key, or set of keys, shared between all array members.
*
* Based on {@author Jake Zatecky}'s {@link https://github.com/jakezatecky/array_group_by array_group_by()} function.
* This variant allows $key to be closures.
*
* @param array $array The array to have grouping performed on.
* @param mixed $key,... The key to group or split by. Can be a _string_,
* an _integer_, a _float_, or a _callable_.
*
* If the key is a callback, it must return
* a valid key from the array.
*
* If the key is _NULL_, the iterated element is skipped.
*
* ```
* string|int callback ( mixed $item )
* ```
*
* @return array|null Returns a multidimensional array or `null` if `$key` is invalid.
*/
function array_group_by(array $array, $key)
{
if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key) ) {
trigger_error('array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR);
return null;
}
$func = (!is_string($key) && is_callable($key) ? $key : null);
$_key = $key;
// Load the new array, splitting by the target key
$grouped = [];
foreach ($array as $value) {
$key = null;
if (is_callable($func)) {
$key = call_user_func($func, $value);
} elseif (is_object($value) && property_exists($value, $_key)) {
$key = $value->{$_key};
} elseif (isset($value[$_key])) {
$key = $value[$_key];
}
if ($key === null) {
continue;
}
$grouped[$key][] = $value;
}
// Recursively build a nested grouping if more parameters are supplied
// Each grouped array value is grouped according to the next sequential key
if (func_num_args() > 2) {
$args = func_get_args();
foreach ($grouped as $key => $value) {
$params = array_merge([ $value ], array_slice($args, 2, func_num_args()));
$grouped[$key] = call_user_func_array('array_group_by', $params);
}
}
return $grouped;
}
}
@drupler
Copy link

drupler commented Mar 5, 2018

Awesome. Thanks :)

@iamshahid
Copy link

This is so awesome, I was just about to write my own code and then found yours! Fantastic job and works out of the box. I even used with WordPress too.

@ronaldaraujo
Copy link

Wow! Thanks!

@King-ZeuS
Copy link

Very useful utility. Thanks the code.

@ilmoralito
Copy link

Thanks for sharing. Using it in joomla

@bastman69
Copy link

Thanks

@x2chi
Copy link

x2chi commented May 3, 2018

Thanks~!!!

@Julianhm9612
Copy link

Good work! And work fine, thanks!!!!!! :D

@Dusty4848
Copy link

Perfect, thanks

@AxelPariss
Copy link

So awesome !!!

@renopaslah
Copy link

Terimaskaih.

@jeff1326
Copy link

@mcaskill Can you merge my fork ? This will allow to group by on a value that may be null in an object :)

@mcaskill
Copy link
Author

mcaskill commented Jan 3, 2019

Hi @jeff1326, I've merged your changes. Cheers!

@djidji01
Copy link

Fantastic! Be blessed Boss!

@isanjaymaurya
Copy link

isanjaymaurya commented May 2, 2019

how to use this in laravel i am getting below error:

ErrorException (E_WARNING)
call_user_func_array() expects parameter 1 to be a valid callback, function 'array_group_by' not found or invalid function name

anyone have any idea?

@edysantosa
Copy link

edysantosa commented Jun 17, 2019

@isanjaymaurya

how to use this in laravel i am getting below error:

ErrorException (E_WARNING)
call_user_func_array() expects parameter 1 to be a valid callback, function 'array_group_by' not found or invalid function name

anyone have any idea?

This may be a very late answer, but if you want to use this as a static method you should modify line 64 into
$grouped[$key] = call_user_func_array(['self', 'array_group_by'], $params);

@zetseat
Copy link

zetseat commented Aug 29, 2019

This saved my day! Thank you!

@Drmzindec
Copy link

Awesome function, thank you.

@Mrxchaoz
Copy link

for those who're using this script on OOP , change the call_user_func_array('array_group_by',$params) to : call_user_func_array(['self','array_group_by'],$param) or
call_user_func_array(array('self','array_group_by'),$param)

@kconde2
Copy link

kconde2 commented May 3, 2020

Thanks

@marcosfreitas
Copy link

marcosfreitas commented Jul 2, 2022

Thank you!

It seems to work perfectly on PHP 7. I'd implement it into a Helper class, so I needed to change the recursive line call to this one as I have static methods, and it keeps working 🎉:

call_user_func_array(['self','arrayGroupBy'], $params);

@ArulDeva56
Copy link

ArulDeva56 commented Dec 13, 2022

Laravel 9 Perfect Thanks
$assets = DB::table('assets')->select('*')->get()->toArray();
$grouped = array_group_by( $assets, "serial_number" );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment