I have several files uploaded with a form that is processed by a PHP script. There are several "categories" that I need to have handles separate ways. In other words, I need some of the files in the $_FILES array to be stored someplace, and some others stored in other places.
So what I need is all files (array keys) that are not $_FILES['filename_form'] to be stored / used separably.
The reason why I need this is because the amount of files being uploaded are dynamic, but always either $_FILES['filename_type1'] or $_FILES['filename_type2_*] where * is a number that increments when more files are input from the form (dynamically)
Might be a very simple solution, either I'm too tired or maybe I've been staring too much at the code, but all I know is I need a solution before tomorrow morning, so it's time sensitive =P
Appreciate all the help I can get.
Thank you!
$files = array();
$filenames = array();
foreach($_FILES as $name => $fileInfo)
{
if($name != 'filename_form')
{
$files[$name] = $fileInfo;
$filenames[] = $name;
}
}
How about:
foreach ( $_FILES as $key => $value )
if ( preg_match ( '/type2/', $key ) )
// do something with the type2
else if ( preg_match ( '/type1/', $key ) )
// do something with these
<?php
foreach ($_FILES as $key => $value) {
$a = explode('_', $key);
$defaultDir = 'myDefaultDirOrPathOrWhatever';
if ($a[1] == 'type2') {
$defaultDir = 'myOtherDirWhenMultipleFiles';
$incrementPassed = $a[2];
}
if (isset($incrementPassed)) unset($incrementPassed);
}
Here is an alternate way
$keys = array_keys($thearray);
$filteredArray = array_filter($keys, 'fiterKeys');
function filterKeys($item) {
if($item != 'valuetocheck') return true;
else return false;
}
$type1_files = array(); // Array of files of first type
$type2_files = array(); // Array of files of second type
$underfined_files = array(); // Array of files of unnormal type (who knows :-P)
foreach($_FILES as $name => $value){
if($name == 'type1'){
$type1_files[] = $value;
}
elseif($name == 'type2'){
$type2_files[] = $value;
}
else{
$undefined_files[] = $value;
}
}
After foreach you'll have your files devided into arrays, which you can process later as you wish
<?php
$files = array();
foreach ($_FILES as $filename => $fileinfo) {
if (strpos($filename, 'form') !== false) {
$files[$name] = $fileinfo;
unset($_FILES[$name]);
}
}
?>
Fastest method I can think of, should be faster then any of the previous answers.
Related
I create a function for remove child dirs on arrays structure. USer for error or mistake, has put on scenario, subdirs child of a parent dir already in config list.
/dir_a/subdir_a
/dir_b/subdir_a/subdir_a
/dir_b/subdir_a/subdir_b
/dir_b/
/dir_c/subdir_a/
...
Code
$local_pre_order = array_unique($local_sync);
asort($local_pre_order);
$local_order = array();
foreach ($local_pre_order as $value)
{
$repeat = false;
foreach ($local_pre_order as $value2)
{
$pos = strpos($value,$value2);
if (($pos !== false ) && ($value != $value2) && ($pos == 0)) {
$repeat = true;
break;
}
}
if (!$repeat) {
$local_order[] = $value;
}
}
Sort OK
/dir_a/subdir_a
/dir_b/
/dir_c/subdir_a/
I think it's a no good programing. Work but not fine. IMHO. Any ideas for best code?
Sorting is the way to go. Note that when sorted, all the child subdirs will be immediatelly after their parents. So it's just a matter of avoiding adding subdirs if the last added dir has a common prefix with it.
PHP isn't my first language, so please don't mind this non-idiomatic code.
$local_sync = [
"/dir_a/subdir_a",
"/dir_b/subdir_a/subdir_a",
"/dir_b/subdir_a/subdir_b",
"/dir_b/",
"/dir_c/subdir_a/"
];
$copy = $local_sync;
asort($copy);
$output = array();
foreach ($copy as $value)
if (strpos($value, end($output)) !== 0)
$output[] = $value;
print_r($output)
It's best not to rely on the array's structure, don't rely on the array being sorted or a comparison between the current path and the previous. What you want to do is use dirname () to get each path's directory name, and search the output array for each path, only adding the path to the output array if it's not already in the output array.
Like so...
$directory_paths = array (
'/dir_a/subdir_a',
'/dir_b/subdir_a/subdir_a',
'/dir_b/subdir_a/subdir_b',
'/dir_b/',
'/dir_c/subdir_a/'
);
$sorted_paths = $directory_paths;
asort ($sorted_paths);
$output = array ();
foreach ($sorted_paths as $key => $path) {
$directory = $path;
$levels = substr_count (trim ($path, '/'), '/') - 1;
for ($i = 0; $i < $levels; $i++) {
$directory = dirname ($directory);
}
if (in_array ($directory, $sorted_paths)) {
$output[$key] = $path;
}
}
ksort ($output);
$output = array_values ($output);
echo print_r ($output, true);
I have this array $filelist
Array ( [0] => . [1] => .. [2] => .DS_Store [3] => 11-96.eml [4] => 11-97.eml )
Which is a list of all files in a particular directory... Sometimes there is no .DS_Store file, sometimes there is, sometimes there are 2 eml files, sometimes there are as many as 6. I'm trying to loop through and find the first array position a .eml file exists so that I can work out how many file are eml and where to start referencing the array.. I have tried...
function firstFileInList($filelist) {
$x = 0;
foreach ($filelist as $value) {
if(strpos($filelist, ".eml") == false) {
$x = $x + 1;
//break;
}
}
return $x;
}
This returns 5, if I include the break it returns 1 and I was expecting to get 4.
Please could somebody point me in the right direction or even if there is a completely better way to do this then I would be more than grateful to see that...
Thanks Paul,
break exists every PHP loop directly when it is called, even if there are other elements. Use continue to get to the next element.
Based on your question
I'm trying to loop through and find the first array position a .eml file exists
function firstFileInList($filelist) {
foreach($filelist as $k => $v)
if(strpos($v, ".eml") !== false)
return $k;
return false;
}
The best way to grab a key from an array in a foreach is to define the key before it starts. Try updating your code with this:
function firstFileInList($filelist) {
$x = false;
foreach ($filelist as $key => $value) {
if(strpos($value, ".eml") == false) {
$x = $key;
break;
}
}
return $x;
}
What this does is set $x to the actual key instead of a number that you increment like you would in a for() loop. $key will always be the array key, so in this example 0, 1, 2, 3, 4.
function firstFileInList($filelist) {
$key=false;
foreach ($filelist as $key=>$value) {
if(strpos($value, ".eml") !==false){
break;
}
}
return $key;
}
In case there is no match you get false.
The problem lies here:
foreach ($filelist as $value) {
if(strpos($filelist, ".eml") == false) {
Note that, for the foreach loop as you have written, it takes each element of the $filelist array, and puts it into the $value variable. Maybe you don't have warnings turned on in PHP, but when I tried your code, I got the following:
Warning: strpos() expects parameter 1 to be string, array given in test/a.php on line 6
What you want is
foreach ($filelist as $value) {
if(strpos($value, ".eml") == false) {
$x = $x + 1;
}
}
Note $value in the second line.
function RetrieveAllPages() {
$dir = '../pages';
$root = scandir($dir);
$result = array();
foreach($root as $value){
if($value === '.' || $value === '..') {
continue;
}
if(is_file("$dir/$value")) {
$result[]="$dir/$value";
continue;
}
foreach(find_all_files("$dir/$value") as $value){
$result[]=array('filename' => $value,);
}
}
print_r ($result);
var_dump($result);
return $result;
}
<?php
//echo'<select>';
foreach (RetrieveAllPages() as $value){
//echo "<option value='".$value['rolename']."'>".$value['rolename']."</option>";
echo'<input type="checkbox" value='.$value['result'].' name='.$value['result'].'/>';
}
//echo'</select>';
?>
getting this kind of error in php the code is above i have research and cant find any source that fits solution..any suggestion or idea is appreaciated
UPDATE
function RetrieveAllPages() {
$result = array();
$dir = "../pages";
$dh = opendir($dir);
while (false !== ($filename = readdir($dh))) {
$files[] = $filename;
}
print_r ($result);
var_dump($result);
return $result;
}
result is Array ( ) array(0) { }
if you don't want to list files recursively you can use this.
function RetrieveAllPages() {
$dir = '../pages';
$root = scandir($dir);
$result = array();
foreach($root as $value){
if($value === '.' || $value === '..') {
continue;
}
if(is_file("$dir/$value")) {
$result[]="$dir/$value";
}
//Note: removed the recursive call
}
print_r ($result);
var_dump($result);
return $result;
}
//echo'<select>';
foreach (RetrieveAllPages() as $value){
//echo "<option value='".$value['rolename']."'>".$value['rolename']."</option>";
// Note $value contains the filename!!!
echo'<input type="checkbox" value='.$value.' name='.$value.'/>' ;
}
//echo'</select>';
Here is another method which is much shorter! uses array_filter and anonymous function.
$all_files = array_filter(scandir('../pages'),function($v){return(!($v === '.' || $v === '..'));});
foreach ($all_files as $value){
echo'<input type="checkbox" value='.$value.' name='.$value.'/>' . $value .'<br/>';
}
You are getting an Illegal offset error because of the way you have defined the function RetrieveAllPages(). From the code, it basically scans a root folder for files and directories. If it encounters a directory, it tries to find all the files in that directory and pushes them into the result array which you return.
If you notice the output when you print the result array it would look something like this (just an example):
Array ( [0] => foo.jpg [1] => bar.txt [2] => Array ( [filename] => Testfile.pdf ) )
Now that you have an idea of what your function returns, let's get back to the echo statement:
foreach (RetrieveAllPages() as $value){
//Here the $value could be either string of the form root/foo etc or
echo $value; //String of file directly found in root directory
//It would be of the form of an array where you would get file names by doing something like:
echo $value[0]['filename']; //from the nested array
}
In any case, you are not using the string offset result anywhere in the array that you create in RetrieveAllPages(). The only string offset you use is filename. That is probably why you get this error when you try to create checkboxes out of these values. The way you handle this two kinds of values in your returned array is completely upto you.
Sidenote - The way you save your values, it's pretty likely that your function will return a nested array. One workaround could be if you, come across a directory instead of a file just prefix the string to the file names found in that directory instead of creating nested arrays with the prefix filename. It would greatly simplify your echo statements where you create the HTML checkboxes.
Like I said, the implementation is upto you and depends on what you are trying to achieve ultimately. Hope it gets you started in the right direction.
I'm working on the following but have become stumped as to how to get this to output.
I have the following which scans the directory contents, then gets the info and saves it as an array:
//SCAN THE DIRECTORY
$directories = scandir($dir);
$directinfo = array();
foreach($directories as $directory){
if ($directory === '.' or $directory === '..') continue;
if(!stat($dir.'/'.$directory)){
} else {
$filestat = stat($dir.'/'.$directory);
$directinfo[] = array(
'name' => $directory,
'modtime' => $filestat['mtime'],
'size' => $filestat['size']
);
}
}
When trying to output it however, I'm just getting single letters with a lot of breaks. Im obviously missing something here with the output loop.
foreach($directinfo as $dirInfo){
foreach($dirInfo as $drInfo){
for ($x=0; $x<=2; $x++) {
<span>"".$drInfo[$x]."<br/></span>";
}
}
}
Help is greatly appreciated. :)
You have already did everything just remove your for loop.
and try to do the following-
foreach($directinfo as $dirInfo){
foreach($dirInfo as $key=>$drInfo){
echo "<span>".$key."=>".$drInfo."<br/></span>";
}
}
I think your dealing with a 2d array, but treating it like a 3d array.
what does
foreach($directinfo as $dirInfo){
foreach($dirInfo as $drInfo){
var_dump($drInfo);
}
}
give you?
You're building a single array, dirInfo.
Php foreach takes the array first;
foreach($dirInfo as $info) {
echo "<span>" . $info['name'] . "</span>";
}
Try this function. It will return you list of all files with path.
// to list the directory structure with all sub folders and files
function getFilesList($dir)
{
$result = array();
$root = scandir($dir);
foreach($root as $value) {
if($value === '.' || $value === '..') {
continue;
}
if(is_file("$dir$value")) {
$result[] = "$dir$value";
continue;
}
if(is_dir("$dir$value")) {
$result[] = "$dir$value/";
}
foreach(getFilesList("$dir$value/") as $value)
{
$result[] = $value;
}
}
return $result;
}
Take the following code into consideration:
$files = array('1.js', '1.css', '2.js', '2.css', '3.js', '3.png');
$extensions = array();
foreach ($files as $file)
{
$extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
if (empty($extensions[$extension]) === true)
{
$extensions[$extension] = 0;
}
++$extensions[$extension];
}
arsort($extensions); // array('js' => 3, 'css' => 2, 'png' => 1)
$common_extension = key($extensions); // js
The code seems to work as I want it to (I still need to check what happens in case there is a draw, but that's irrelevant for this question). I'm looking for a more efficient (and compact way) of rewriting the above snippet, the closest I've got so far is:
$files = array('1.js', '1.css', '2.js', '2.css', '3.js', '3.png');
$extensions = array_count_values(array_map('strtolower', preg_replace('~^.*[.](.*)$~', '$1', $files)));
arsort($extensions, SORT_NUMERIC);
$common_extension = key($extensions);
But this loops through the array 3 times and that preg_replace() is not bulletproof... Any ideas?
I would do something like this:
<?php
function getCommon($array, $result = array()) {
foreach ($array as $k => $v) { $array[$k] = strtolower(pathinfo($v, PATHINFO_EXTENSION)); }
$ext = array_count_values($array); arsort($ext,SORT_NUMERIC);
$k = array_keys($ext); $k0 = $k[0];
if ($ext[$k0] > $ext[$k[1]]) { $result[] = $k0; }
else { foreach ($ext as $k => $v) { if ($v == $ext[$k0]) { $result[] = $k; } } }
return $result;
}
$files = array('1.js', '2.js', '3.png', '4.css');
print_R($files);
print_R(getCommon($files));
$files2 = array('1.js', '2.js', '3.png', '4.png', '5.css');
print_R($files2);
print_R(getCommon($files2));
?>
This will return an array, where values will be common extensions, even if they are many.
Note: Don't use regex when your job basic PHP functions can do - regex is too resource-consuming compared to php built-in functions.
I have thought about this question for quite some time now and I think your first snippet is pretty much the answer to it. It is not like shorter code is faster code. That code is pretty fast and scaling linearly to greater arrays. It is pretty much a complexity of O(n) plus the sorting algorithm arsort (i have no clue what method it is using, but i expect it to be faster than a self written one). The only thing I can offer is this little function containing your snippets and a little tweak in the case the extension is not in the array.
function count_ext($array){
$ret = array();
foreach($array as $ext){
$ext = strtolower(pathinfo($ext, PATHINFO_EXTENSION));
if( !isset($ret[$ext]) ) $ret[$ext] = 0;
$ret[$ext]++;
}
arsort($ret);
return $ret;
}
I don't know how many elements your arrays have and how time-critical your use case is, but this method will do well.