Can someone help me out? I cannot see it. The function below is not returning the array. The print_r($list)(above the return) prints the array on the screen. But the print_r($files)returns an empty array....
function listFolderFiles($dir){
$ffs = scandir($dir);
$i = 0;
$list = array();
foreach ( $ffs as $ff ){
if ( $ff != '.' && $ff != '..' ){
if ( strlen($ff)>=5 ) {
if ( substr($ff, -4) == '.mp4' ) {
$value = $dir.'/'.$ff;
$list[] = $value;
}
}
if( is_dir($dir.'/'.$ff) )
listFolderFiles($dir.'/'.$ff);
}
}
print_r($list); // Returns the full array with values
return $list;
}
$files = listFolderFiles($_POST['path']);
print_r($files) // Returns an empty array..... :(:(
Your recursion call doesn't handle the returned array:
listFolderFiles($dir.'/'.$ff);
You need to merge the array here:
$list = array_merge($list, listFolderFiles($dir.'/'.$ff) );
Related
I have dynamic multidimensional array that contain directory, sub-directory and file names in a project folder, key indicating a sub-directory name and value indicating file names, if a key equal to number indicating only file and then if a key hasn't any value indicating there is no file at all in a directory. The array look like this :
Array
(
[0] => index.php
[src] => Array
(
[src2] => Array
(
[src3] => Array
(
[0] => test_src3.php
)
[0] => Array
(
[0] => test_src2.php
)
)
[0] => test_src.php
)
[src_test] => Array
(
[New Folder] => Array
(
)
[src_test2] => Array
(
[New Folder] => Array
(
)
[src_test3] => Array
(
)
)
)
[1] => test.php
)
The number of dimensions might be change based on sub directories that found in a folder path inputted by user (this program is used by a person in their local).
How could i fetch those array elements so that the result would be like this :
array(
[0] => src/src2/src3/
[1] => src_test/New Folder/
[2] => src_test/src_test2/New Folder/
[3] => src_test/src_test2/src_test3/
)
By the way i have a function to achieve this :
<?php
// Get specific element where the first index is 1 instead of 0
function getAtPos($tmpArray,$pos) {
$keys = array_keys($tmpArray);
return array($keys[$pos-1] => $tmpArray[$keys[$pos-1]]);
}
// Get all Keys that has String type only
function getKeyStr(array $mixed, $numbIdx){
$results = [];
$tmp = array_keys($mixed);
$ii = 0;
for ($i=1; $i <= $numbIdx; $i++) {
$keyArr = getAtPos($tmp, $i);
if (is_string($keyArr[$ii])) {
$results[] = $keyArr[$ii];
}
$ii++;
}
return $results;
}
function getKeyPaths(array $tree, $glue = '/', $return_array = true){
$paths = "";
$result = [];
foreach ($tree as $key => &$mixed) {
if (is_array($mixed) && !is_int($key)) {
$path = $key . $glue;
$retArrFalse = false;
$jlhMixed = count($mixed);
$getKeyStr = getKeyStr($mixed, $jlhMixed);
$jlhKeyStr = count($getKeyStr);
if ($jlhKeyStr < 2) {
$repeat = getKeyPaths($mixed, $glue, $retArrFalse);
$paths .= $path . $repeat;
if ($return_array) {
$paths .= "|";
}
}elseif($jlhKeyStr > 1) {
for ($i=0; $i < $jlhKeyStr; $i++) {
$idxAsso = $getKeyStr[$i];
$jlhKeySub = count($mixed[$idxAsso]);
$path2 = $idxAsso . $glue;
if ($jlhKeySub > 0) {
$paths .= $path . $path2 . getKeyPaths($mixed[$idxAsso], $glue, $retArrFalse);
if ($return_array) {
$paths .= "|";
}
}else{
$paths .= $path . $path2;
if ($return_array) {
$paths .= "|";
}
} // END of if else
} // END of for loop
} // END of elseif
}
} // END of foreach
if ($return_array) {
return explode("|", trim($paths, "|"));
}
return $paths;
}
the above function does not result like what i expected:
Array
(
[0] => src/src2/src3/
[1] => src_test/New Folder/
[2] => src_test/src_test2/New Folder/src_test3/
)
How do i achieve this ?
Any help would be appreciated !
UPDATE
I have modified my function trying to solve this:
<?php
// To get spesific element on dynamic associative array
function getAtPos($tmpArray,$pos) { // $pos is an index order starting with 1 instead of 0
$keys = array_keys($tmpArray);
return array($keys[$pos-1] => $tmpArray[$keys[$pos-1]]);
}
// Get key string type (associative) only in the given array
function getKeyStr(array $mixed, $numbIdx){
$results = [];
$tmp = array_keys($mixed); // change key to element (as array number).
$ii = 0;
for ($i=1; $i <= $numbIdx; $i++) {
$keyArr = getAtPos($tmp, $i);
if (is_string($keyArr[$ii])) {
$results[] = $keyArr[$ii];
}
$ii++;
}
return $results; // Return all second dimension sub-keys of the given array (parent)
}
// EDITED !
function getKeyPaths2(array $tree, $glue = '/', $return_array = true, $goToIfElse = false, $saveSameParent = []){
$paths = "";
$result = [];
$iFor = 0;
foreach ($tree as $key => &$mixed) {
if (is_array($mixed) && !is_int($key)) {
$path = $key . $glue;
$retArrFalse = false;
$jlhMixed = count($mixed);
$getKeyStr = getKeyStr($mixed, $jlhMixed); // Contain sub-keys of the second dimension of the parent
$jlhKeyStr = count($getKeyStr); // Count number of sub-keys of second dimension of parent
if ($goToIfElse !== false) {
$jlhKeyStr = $goToIfElse;
$iFor++;
unset($mixed);
$mixed = $tree;
$jlhMixed = count($mixed);
$getKeyStr = getKeyStr($mixed, $jlhMixed); // Contain sub-keys of the second dimension of the
$jlhKeyStr = count($getKeyStr); // Count number of sub-keys of second dimension of parent
}
if ($jlhKeyStr < 2) {
$repeat = getKeyPaths2($mixed, $glue, $retArrFalse);
$paths .= $path . $repeat;
if (!$return_array && $jlhKeyStr < 1) {
$paths .= "|";
}
}elseif($jlhKeyStr > 1) {
for ($i=$iFor; $i < $jlhKeyStr; $i++) {
$idxAsso = $getKeyStr[$i];
$jlhKeySub = count($mixed[$idxAsso]);
$path2 = $idxAsso . $glue;
if ($jlhKeySub > 0) {
$paths .= $path . $path2;
// TEST
$pecah = explode("|", $paths);
$saveSameParent[0] = end($pecah);
if ($return_array) {
$paths .= "|";
}
$paths .= $path . $path2 . getKeyPaths2($mixed[$idxAsso], $glue, $retArrFalse, $jlhKeyStr, $saveSameParent);
if ($return_array) {
$paths .= "|";
}
}else{
if ($goToIfElse !== false) {
$paths .= $path;
$paths .= "|";
$paths .= $saveSameParent[0] . $path2;
$paths .= "|";
}else{
$paths .= $path . $path2;
}
if ($return_array || $goToIfElse !== false) {
$paths .= "|";
}
} // END of if else
} // END of for loop
} // END of elseif
}
} // END of foreach
if ($return_array) {
return explode("|", trim($paths, "|"));
}
return $paths;
}
But this only works with my example array that i showed above.
If the given array like this, this would not work:
<?php
$tree = [];
$tree[0] = "index.php";
$tree["src"]["src2"]["src3"][0] = "test_src3.php";
$tree["src"]["src2"][0][0] = "test_src2.php";
$tree["src"][0] = "test_src.php";
$tree["src_test"]["New Folder"] = array();
$tree["src_test"]["src_test2"]["New Folder"] = array();
$tree["src_test"]["src_test2"]["src_test3.1"] = array();
$tree["src_test"]["src_test2"]["src_test3.2"] = array();
$tree["src_test"]["src_test2"]["src_test3.1"]["src_test3.1.1"] = array();
$tree["src_test"]["src_test2"]["src_test3.2"]["src_test3.2.1"]["src_test3.2.2"]["src_test3.2.3"] = array("test_src4.php", "test_src5.php");
The result would be :
Array
(
[0] => src/src2/src3/
[1] => src_test/New Folder/
[2] => src_test/src_test2/
[3] => src_test/src_test2/New Folder/src_test3.1/New Folder/src_test3.1/src_test3.1.1/src_test3.1.1/
[4] => New Folder/src_test3.2/New Folder/src_test3.2/src_test3.2.1/src_test3.2.1/src_test3.2.2/src_test3.2.3/
[5] => src_test3.1/src_test3.2/src_test3.1/src_test3.2/src_test3.2.1/src_test3.2.1/src_test3.2.2/src_test3.2.3/
)
I have an array:
$arr1 = [1,2,2,3,3,3];
Is there any method by which I can delete a duplicate value once like,
some_function($arr1,3);
which gives me the ouput $arr1 = [1,2,2,3,3]
As per the comment, check if there are more than one of the element you're searching for, then find and remove one of them.
function remove_one_duplicate( $arr, $target ) {
if( count( array_keys( $arr, $target ) ) > 1 ) {
unset( $arr[array_search( $target, $arr )] );
}
return $arr;
}
This should work...
function removeduplicate($myarray,$needle) {
if (($nmatches = count($matches = array_keys($myarray,$needle))) >= 2) {
for ($i=0; $i<$nmatches; $i++) {
if ($matches[$i+1] == (1+$matches[$i])) {
array_splice($myarray,$matches[$i],1);
break;
}
}
}
return $myarray;
}
To use the function...
$arr1 = [1,2,2,3,3,3,4,7,3,3];
$newarray = removeduplicate($arr1,3)
print_r($newarray);
EDITED:
If you want the function to modify your original array directly, you can do it (the function will return true if a character has been removed or false if not)...
function removeduplicate(&$myarray,$needle) {
if (($nmatches = count($matches = array_keys($myarray,$needle))) >= 2) {
for ($i=0; $i<$nmatches; $i++) {
if ($matches[$i+1] == (1+$matches[$i])) {
array_splice($myarray,$matches[$i],1);
return true;
}
}
}
return false;
}
So, now you can do...
$arr1 = [1,2,2,2,2,2,3,3,3,4,2,2];
removeduplicate($arr1,2);
print_r($arr1);
This function will copy the array skipping only the second instance of the specified element.
function removeOnce($array, $elem) {
$found = 0;
$result = [];
foreach ($array as $x) {
if ($x == $elem && (++$found) == 2) {
continue;
}
$result[] = $x;
}
return $result;
}
I'm iterating through a $_POST to write each item into a text file. It's working, but despite having used 'strlen' to avoid blank lines, I'm still getting some. Can anyone tell me why? Here's my code:
$entries = "";
$filename = "test.txt";
foreach($_POST as $value) {
if( is_array( $value ) ) {
foreach( $value as $subvalue ) {
if (strlen($subvalue) > 5) {
$entries .= $subvalue . PHP_EOL;
}
}
}
}
file_put_contents($filename, $entries);
Try below code for your solution:
$entries = "";
$filename = "test.txt";
foreach($_POST as $value) {
if( is_array( $value ) ) {
foreach( $value as $subvalue ) {
if (strlen(trim($subvalue)) > 5) {
$entries .= $subvalue . PHP_EOL;
}
}
}
}
file_put_contents($filename, $entries);
I have to do a php script who browse a directory with sub-directory.
For each subdirectory (and maybe sub-subdirectory), I have to get filename and his parents directories.
Do you have a simple solution to do this please?
Thanks
Since I've had to create the same functionality for a website of mine too, I'll post my function as reference.
function recursiveFileSearch($path, $searchmask = "*") {
$path = rtrim($path, '/');
$files = array();
if(is_array($searchmask)) {
for($i = 0; $i < count($searchmask); $i++) {
$files = array_merge($files, glob($path.'/'.$searchmask[$i]));
}
sort($files);
} else {
$files = glob($path.'/'.$searchmask);
}
$dirs = glob($path.'/*', GLOB_ONLYDIR);
foreach($dirs as $dir) {
if(is_dir($dir)) {
$files = array_merge($files, recursiveFileSearch($dir, $searchmask));
}
}
sort($files);
return $files;
}
I am not 100% sure what you are asking, but if you take a look at the scandir documentation the first comment has a very useful recursive scanning function.
<?php
function dirToArray($dir) {
$result = array();
$cdir = scandir($dir);
foreach ($cdir as $key => $value)
{
if (!in_array($value,array(".","..")))
{
if (is_dir($dir . DIRECTORY_SEPARATOR . $value))
{
$result[$value] = dirToArray($dir . DIRECTORY_SEPARATOR . $value);
}
else
{
$result[] = $value;
}
}
}
return $result;
}
?>
The results will have the following format.
Array
(
[subdir1] => Array
(
[0] => file1.txt
[subsubdir] => Array
(
[0] => file2.txt
[1] => file3.txt
)
)
[subdir2] => Array
(
[0] => file4.txt
}
)
I am trying to display a folder tree. Its working all good. Below is the code.
$fileData = fillArrayWithFileNodes( new DirectoryIterator( $dir ) );
function fillArrayWithFileNodes( DirectoryIterator $dir )
{
$data = array();
foreach ( $dir as $node )
{
if ( $node->isDir() && !$node->isDot() )
{
$data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
}
else if ( $node->isFile() )
{
$data[] = $node->getFilename();
}
}
return $data;
}
But i have a new requirement. I want to have it in a class, so that i can use it this way.
$tree = new folderTree();
$structure = $tree->display('testdir',2); //2 is the level of subfolders
So i have wrapped everything in a class in the below way.
class folderTree {
function display($dir,$level='') {
$fileData = fillArrayWithFileNodes( new DirectoryIterator( $dir ) );
function fillArrayWithFileNodes( DirectoryIterator $dir )
{
$data = array();
foreach ( $dir as $node )
{
if ( $node->isDir() && !$node->isDot() )
{
$data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
}
else if ( $node->isFile() )
{
$data[] = $node->getFilename();
}
}
return $data;
}
}
}
But i am really stuck in how to use the level.
What is level ?
-folder
-childfolder (level1)
file1
file2
-subchildfolder (level2)
file1
file2
You can copy the logic from below code:
<?php
function getFiles(RecursiveDirectoryIterator $rdi, $depth=0) {
if (!is_object($rdi))
return;
for ($rdi->rewind();$rdi->valid();$rdi->next()) {
if ($rdi->isDot())
continue;
if ($rdi->isDir() || $rdi->isFile()) {
for ($i = 0; $i<=$depth;++$i)
echo ' ';
echo $rdi->current().'<br />';
if ($rdi->hasChildren())
getFiles($rdi->getChildren(),1+$depth);
}
}
}
$depth = 2;
getFiles(new RecursiveDirectoryIterator('.'), $depth);
?>