PHP function to create string chunks of increasing lengths ("fd6eg3" => "f", "fd", "fd6", "fd6eg3")

Viewed 48

tl;dr: To store files under a path determined by their hash, I need a single function to get the following with level=3 and hash='fd6eg3': f/fd/fd6/fd6eg3

I am looking for a way to create chunks (of a given string) of increasing lengths, from the beginning of the string. Also, I want to limit the number of produced chunks.

The goal is to store a file named fd6eg3 under (with a number of chunks set to 3):

  • A directory named fd6.
  • Which is the child of a directory named fd.
  • Which is the child of a directory named f.

So the final path would be: f/fd/fd6/fd6eg3

The closest I got is getting the "directory part" (f/fd/fd6/) using the following function:

function computePathForHash(string $hash, int $level): string
{
    if ($level <= 0) {
        return '';
    } else {
        return computePathForHash($hash, $level - 1)
            . mb_substr($hash, 0, $level)
            . DIRECTORY_SEPARATOR
        ;
    }
}
echo computePathForHash('fd6eg3', 3);

Which output is resumed in this table:

level Returned
0 ""
1 "f/"
2 "f/fd/"
3 "f/fd/fd6/"

But I fail to add the "file part" ($hash) to the end.

I would like to avoid passing a third parameter such as $initial_level that would store the originally asked level against I could compare current $level to decide when to add $hash.

Considering the low value of $level (shouldn't be higher than 10 in my use case) I don't think there are arguments against recursion. I find recursion simpler to read/understand but if it's impossible in recursion I'll go with something else (or use 2 functions, one for directory part, the other to concatenate it with file part).

1 Answers

I think recursion is great in the right circumstances, but a straightforward for loop can do this and hopefully more maintainable.

Just loop up to the level and add the start chunk of the hash each time, then add the full hash on the return...

function computePathForHash(string $hash, int $level): string
{
    $output = '';
    for ( $i = 1; $i <= $level; $i++ )  {
        $output .= mb_substr($hash, 0, $i) . DIRECTORY_SEPARATOR;
    }
    
    return $output . $hash;
}
Related