Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In other words, you need to hash (or otherwise elaborate) an integer (<code>id</code>) so that it can be evenly spread on a target address space.</p> <p>One way is the one you're adopting. Say that you want to hold at most one thousand billion records, therefore the maximum number you manage is 999,999,999,999 or four levels.</p> <pre><code>function storeFile($id, $source_path) { GLOBAL $BASE_PATH; $seq = sprintf("%012d", $id); // Transforms 42 in 000000000042 $dir = str_split($seq, 3); // Transforms in { 000 000 000 042 } $file = array_pop($dir); // Get 042 which is the file name </code></pre> <p>Upon creation, <strong>we need to create intermediate directories if needed</strong> (<strong>EDIT</strong>: actually @Yoshi's solution is much better)</p> <pre><code> // Now build directory $path = $BASE_PATH; foreach($dir as $component) { $path .= "/$component"; if (!is_dir($path)) mkdir($path); } // The above can be replaced with mkdir(getPath($id), 0755, true); [@Yoshi] // Now $path exists and is /my/base/path/000/000/000 // $path/$file is my file name, 042 in $path rename($source_path, $dest_path = "$path/$file"); // Just to check. TRUE if everything was hunky dory; FALSE if something went bad. return file_exists($dest_path); </code></pre> <p>}</p> <p>Every time you <strong>store</strong> a file, you run the above and create the directory if needed.</p> <p>On recovery, you can just run</p> <pre><code> function getPath($id) { GLOBAL $BASE_PATH; return $BASE_PATH . implode('/', str_split(sprintf("%012d", $id), 3)); } </code></pre> <p>and directly get the filename.</p> <p><strong>UPDATE</strong>: '/' is Unix path separator (should work under Windows too), but you may want to replace it with your platform's directory separator.</p> <p>If you want to keep the file name (not always advisable since it is under the user's control, international characters might clash with file system encoding, and so on), you can do it like this. We now only need three levels, so a 3*3 path:</p> <pre><code>function storeFile($id, $source_path) { GLOBAL $BASE_PATH; $seq = sprintf("%09d", $id); // Transforms 42 in 00000042 $dir = str_split($seq, 3); // Transforms in { 000 000 042 } // Now build directory. 042 is last directory $path = $BASE_PATH; foreach($dir as $component) { $path .= "/$component"; if (!is_dir($path)) mkdir($path); } // Use name component of source file $file = basename($source_path); // $path/$file is my file name, 042 in $path rename($source_path, $dest_path = "$path/$file"); // Just to check. TRUE if everything was hunky dory; FALSE if something went bad. return file_exists($dest_path); } </code></pre> <p><code>getPath</code> stays the same, except that it will now require <code>09d</code> instead of <code>012d</code>. If you want to limit to two levels of size 3, reduce further to <code>06d</code>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload