public static function sortBy($array, $sortByKeys, $sorters, $orders = [])
	{
		if( is_string($sortByKeys) )
		{
			$sortByKeys = explode('.', $sortByKeys);
		}

		$sortByKeys = array_values((array)$sortByKeys);
		$sorters = array_values((array)$sorters);

		uasort($array, function($a, $b) use ($sortByKeys, $sorters, $orders) {

			$return = 0;

			foreach( $sortByKeys as $key => $sortBy ) 
			{
				// call callback or get attribute
				if( is_callable($sortBy) )
				{
					$aSort = call_user_func($sortBy, $a);
					$bSort = call_user_func($sortBy, $b);
				}
				else 
				{
					$aSort = u\def($a, $sortBy);
					$bSort = u\def($b, $sortBy);
				}

				$method = isset($sorters[$key]) ? $sorters[$key] : $sorters[ ( count($sorters) - 1 ) ];

				// make sure Sort class from pisc\arrr namespace is used
				if( is_string($method) && substr($method, 0, 4) === 'Sort' ) $method = __NAMESPACE__ .'\\' . $method;

				$order = u\def($orders, $key, 'desc');

				// call compare function
				$return = call_user_func($method, $aSort, $bSort);

				// reverse return value
				if( $order !== 'desc' )
				{
					$return *= -1;
				}

				// return if the items compared are not the same
				if( $return !== 0 )
				{
					return $return;
				}
			}

			return 0;
		});

		return $array;
	}