JSON Output from readdir - php

i am a little bit confused.
I have a folder with some pdf Documents and this code:
$files = array();
$dir = opendir('c:/dateien/');
while ($file = readdir($dir)) {
$dateiinfo = pathinfo($dir."/".$file);
$string = $dateiinfo['filename'];
$array = explode("_", $string);
if ($dateiinfo['extension'] == "pdf") {
$files[] = $array;
}
}
echo json_encode($files);
This is my Output Result
[["Titel","2014-01-13","2014-01-14"],["Titel","2014-01-15","2014-01-15"]]
But i want to use it in fullcalendar. I need title: Titel and start: 2014-01-13 and so on.
Has anynone an idea to solve my problem?
The file name is like this title_start_end.pdf
Thanks.

Maybe something like this:
...
$files[] = array(
'title' => $array[0],
'start' => $array[1],
'end' => $array[2]
);
...

Related

How to display images(.jpg) only?

Array ( [0] => assets/image/man.jpg [1] => assets/image/violin.jpg [2] => assets/image/test.txt )
The data from data base is like above.It contain images and txt.how can i display only images.
$ar = ['assets/image/man.jpg','assets/image/violin.jpg','assets/image/test.txt'];
$allowed = ['jpg']; //your image extensions
$img_ar = [];
foreach($ar as $img){
$ext = pathinfo($img,PATHINFO_EXTENSION);
if(in_array($ext,$allowed)){
$img_ar[] = $img;
}
}
print_r($img_ar);
$array= Array ( [0] => assets/image/man.jpg [1] => assets/image/violin.jpg [2] => assets/image/test.txt )
$m_array = preg_grep('/^.jpg\s.*/', $array);
$m_array contains matched elements of array.
For more detail have look at this thread search a php array for partial string match
For this you can directly filter it when you are querying like
field like '%.jpg'
If you don't want to do that and manipulate the array you can use array_filter like,
$array= Array ('assets/image/man.jpg', 'assets/image/violin.jpg', 'assets/image/test.txt');
$output = array_filter($array, function($arr) {
if (strpos($arr, '.jpg') == true){
return $arr;
}
});
$output array contains only the entries which having the .jpg string.
Here am using strpos to check .jpg exists or not.
you maybe use substr($str, -4) == '.jpg' to check the last 4characters.
If you are using PHP 5+ (which I hope you are on 7.0+), use SplFileInfo() class
$spl = new SplFileInfo($fileName);
if ($spl->getExtension() == 'jpg') {
//image
}
Use foreach loop and get an extension of the file and display.
foreach($array_result as $result){
//$array_result is array data
//condition is checking the file that if it is an image or not
$allowed = array('gif','png' ,'jpg');
$filename = $result;
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if(in_array($ext, $allowed) ) {
echo '<img src="'.$result.'" alt="" /> ';
}
}
This should do the trick:
$images = array();
$images_exts = array('.jpg','.png');
foreach($db_array as $key => $value)
{
foreach($images_exts as $ext)
{
if (strpos($value,$ext))
{
$images[] = $value;
}
}
}
Here is an example https://3v4l.org/8W3Be
And here is another way, whatever you like the most:
$images = array();
$images_exts = array('jpg','png');
foreach($input as $value)
{
if(in_array(#end(explode('.', $value)), $images_exts))
{
$images[] = $value;
}
}
Here is an example https://3v4l.org/b0njd
Why do you check it when you want write it on page?
You can:
1. split assets/image/man.jpg with '/'
2. get last one,
3. split last one with '.'
4. get extension and if it was 'jpg' write it to page.
<?php
$error = array();
$file_extArr = explode(".", $file_name);
$file_extEnd = end($file_extArr);
$file_ext = strtolower($file_extEnd);
$validateImage = array("png", "jpg", "jpeg", "gif");
if (!in_array($file_ext, $validateImage)) {
$error[] = "wrong format image";
}
if (!empty($error)) {
return;
}
?>
<?php
$data = Array (
'assets/image/man.jpg ',
'assets/image/violin.jpg ',
'assets/image/test.txt ',
);
$arrDara = array();
foreach ($data as $value) {
$fileName = explode('/', $value);
$arrDara[] = end($fileName);
}
print_r($arrDara);
?>
Just loop your array and explode every sting. the last index is what all you need.

Phalcon Query super slow inside large loop

I'm using Phalcon 3.0.4. I made a foreach on each file inside my folder. Currently I have just 4000 files. I did a findFirst to check if the filename already exist in MySQL (I have 100 000 rows in my table). But when I use findFirst, the response is super slow (I have to wait 20 minutes to get a response). Here is my code :
$dir = new FilesystemIterator("files/path/to/my/files/");
foreach ($dir as $file) {
if ($file->getExtension() == 'json') {
$filename = $file->getFilename();
$explode_filename = explode("_", $filename);
$date = $explode_filename[0];
$unformatted_date = DateTime::createFromFormat("Ymd-His", $date);
$date_server = $unformatted_date->format("Y-m-d H:i:s");
$timestamp_app = $explode_filename[2];
$date_app = date("Y-m-d H:i:s", $timestamp_app/1000);
echo $date_server;
$json_data = json_decode(file_get_contents($file), true);
$scan = Scans::findFirst(array(
"name = :name:",
"bind" => array("name" => $filename)
));
if (!$scan) {
...
}
}
}
I tried to make my query with the QueryBuilder PHQL but I have the same result:
$scan = $this->modelsManager->createBuilder()
->from("Scans")
->where("name = :name:", ["name" => $filename])
->limit(1)
->getQuery()
->execute();
If I remove the findFirst or queryBuilder the response is ~30ms but with the findFirst it will takes ~20 minutes... How can I do to increase the performance of the search in my table ?
By changing your code to better performing one:
$dir = new FilesystemIterator("files/path/to/my/files/");
$fileNames = [];
foreach ($dir as $file) {
if ($file->getExtension() == 'json') {
$filename = $file->getFilename();
$explode_filename = explode("_", $filename);
$date = $explode_filename[0];
$unformatted_date = DateTime::createFromFormat("Ymd-His", $date);
$date_server = $unformatted_date->format("Y-m-d H:i:s");
$timestamp_app = $explode_filename[2];
$date_app = date("Y-m-d H:i:s", $timestamp_app/1000);
echo $date_server;
$json_data = json_decode(file_get_contents($file), true);
// save the above data to some arrays
$fileNames[] = $fileName;
}
}
$scans = Scans::find([
'columns' => 'check only columns you need, otherwise you will have full models with hydration',
'conditions' => 'name IN ({fileNames:array})',
'group' => 'name',
'bind' => [
'fileNames' => $fileNames
]
]);
foreach($fileNames as $fileName) {
$filteredScans = $scans->filter(function($scan) use ($fileName) {
return $scan->name == $fileName;
}
if(!$filteredScans) {
// do here whatever
}
}
This solution can be memory heavy though, then you could include here some paginations like do some limit like proper for and do 100-10000 rows at once depending how much RAM you have.
create index on Scans.name
use group by Scans.name (if not uniq)
set some columns then be use

How to make a tree from a flat array - php

I am trying to represent the whole array returned from Amazon S3 bucket in a tree structure one can browse.
The array example is following
$files[0] = 'container/798/';
$files[1] = 'container/798/logo.png';
$files[2] = 'container/798/test folder/';
$files[3] = 'container/798/test folder/another folder/';
$files[4] = 'container/798/test folder/another folder/again test/';
$files[5] = 'container/798/test folder/another folder/test me/';
$files[6] = 'container/798/test two/';
$files[7] = 'container/798/test two/logo2.png';
and this is what i am trying to achieve
http://i.stack.imgur.com/HBjvE.png
so far i have only achieved differing the files and folder but not on different level with parent-child relation. The above mentioned array resides in $keys['files']. The code is following
$keys = json_decode($result,true);
$folders = array();
$files = array();
$i =0;
foreach ($keys['files'] as $key){
if(endsWith($key, "/")){
$exploded = explode('container/'.$_SESSION['id_user'].'/',$key);
if(!empty($exploded[1]))
$folders[$i]['name'] = substr($exploded[1],0,-1);
}
else{
$exploded = explode('container/'.$_SESSION['id_user'].'/',$key);
$files[$i]['name'] = $exploded[1];
$files[$i]['size'] = "";
$files[$i]['date'] = "";
$files[$i]['preview_icon'] = "";
$files[$i]['dimensions'] = "";
$files[$i]['url'] = "";
}
$i++;
}
This is code just to show i am trying but its not complete or accurate. I don't know how to approach a logic that can give me the hierarchy i am showing the picture. Any help would be greatly appreciated.
I don't know if this is the 'correct' way to do this, but if you want to make a recursive structure, then the easy way is to use a recursive function:
$root = array('name'=>'/', 'children' => array(), 'href'=>'');
function store_file($filename, &$parent){
if(empty($filename)) return;
$matches = array();
if(preg_match('|^([^/]+)/(.*)$|', $filename, $matches)){
$nextdir = $matches[1];
if(!isset($parent['children'][$nextdir])){
$parent['children'][$nextdir] = array('name' => $nextdir,
'children' => array(),
'href' => $parent['href'] . '/' . $nextdir);
}
store_file($matches[2], $parent['children'][$nextdir]);
} else {
$parent['children'][$filename] = array('name' => $filename,
'size' => '...',
'href' => $parent['href'] . '/' . $filename);
}
}
foreach($files as $file){
store_file($file, $root);
}
Now, every element of root['children'] is an associative array that hash either information about a file or its own children array.

CSV file to flat array with materialized path

I have CSV file which contains a list of files and directories:
Depth;Directory;
0;bin
1;basename
1;bash
1;cat
1;cgclassify
1;cgcreate
0;etc
1;aliases
1;audit
2;auditd.conf
2;audit.rules
0;home
....
Each line depends on the above one (for the depth param)
I would like to create an array like this one in order to store it into my MongoDB collection with Materialized Paths
$directories = array(
array('_id' => null,
'name' => "auditd.conf",
'path' => "etc,audit,auditd.conf"),
array(....)
);
I don't know how to process...
Any ideas?
Edit 1:
I'm not really working with directories - it's an example, so I cannot use FileSystems functions or FileIterators.
Edit 2:
From this CSV file, I'm able to create a JSON nested array:
function nestedarray($row){
list($id, $depth, $cmd) = $row;
$arr = &$tree_map;
while($depth--) {
end($arr );
$arr = &$arr [key($arr )];
}
$arr [$cmd] = null;
}
But i'm not sure it's the best way to proceed...
This should do the trick, I think (it worked in my test, at least, with your data). Note that this code doesn't do much error checking and expects the input data to be in proper order (i.e. starting with level 0 and no holes).
<?php
$input = explode("\n",file_get_contents($argv[1]));
array_shift($input);
$data = array();
foreach($input as $dir)
{
if(count($parts = str_getcsv($dir, ';')) < 2)
{
continue;
}
if($parts[0] == 0)
{
$last = array('_id' => null,
'name' => $parts[1],
'path' => $parts[1]);
$levels = array($last);
$data[] = $last;
}
else
{
$last = array('id' => null,
'name' => $parts[1],
'path' => $levels[$parts[0] - 1]['path'] . ',' . $parts[1]);
$levels[$parts[0]] = $last;
$data[] = $last;
}
}
print_r($data);
?>
The "best" way to go would be to not store your data in CSV format, as it's the Wrong Tool For The Job.
That said, here you go:
<?php
$lines = file('/path/to/your/csv_file.csv');
$directories = array();
$path = array();
$lastDepth = NULL;
foreach ($lines as $line) {
list($depth, $dir) = str_getcsv($line, ';');
// Skip headers and such
if (!ctype_digit($depth)) {
continue;
}
if ($depth == $lastDepth) {
// If this depth is the same as the last, pop the last directory
// we added off the stack
array_pop($path);
} else if ($depth == 0) {
// At depth 0, reset the path
$path = array();
}
// Push the current directory onto the path stack
$path[] = $dir;
$directories[] = array(
'_id' => NULL,
'name' => $dir,
'path' => implode(',', $path)
);
$lastDepth = $depth;
}
var_dump($directories);
Edit:
For what it's worth, once you have the desired nested structure in PHP, it would probably be a good idea to use json_encode(), serialize(), or some other format to store it to disk again, and get rid of the CSV file. Then you can just use json_decode() or unserialize() to get it back in PHP array format whenever you need it again.

How to extract data from csv file in PHP

I have a csv file which looks like this
$lines[0] = "text, with commas", "another text", 123, "text",5;
$lines[1] = "some without commas", "another text", 123, "text";
$lines[2] = "some text with commas or no",, 123, "text";
And I would like to have a table:
$t[0] = array("text, with commas", "another text", "123", "text","5");
$t[1] = array("some without commas", "another text", "123", "text");
$t[2] = array("some text, with comma,s or no", NULL , "123", "text");
If I use split($lines[0],",") I'll get "text" ,"with commas" ...
Is there any elegant way to do it?
You can use fgetcsv to parse a CSV file without having to worry about parsing it yourself.
Example from PHP Manual:
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
In addition to Matt's suggestion, you can also use SplFileObject to read in the file:
$file = new SplFileObject("data.csv");
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl(',', '"', '\\'); // this is the default anyway though
foreach ($file as $row) {
list ($fruit, $quantity) = $row;
// Do something with values
}
source: http://de.php.net/manual/en/splfileobject.setcsvcontrol.php
you can read the data using the following function.
function readCSV() {
$csv = array_map('str_getcsv', file('data.csv'));
array_shift($csv); //remove headers
}
http://www.pearlbells.co.uk/how-to-sort-a1a2-z9z10aa1aa2-az9az10-using-php/
here is also a simple method to get read csv file.
$sfp = fopen('/path/to/source.csv','r');
$dfp = fopen('/path/to/destination.csv','w');
while ($row = fgetcsv($sfp,10000,",","")) {
$goodstuff = "";
$goodstuff = str_replace("¦",",",$row[2]);
$goodstuff .= "\n";
fwrite($dfp,$goodstuff);
}
fclose($sfp);
fclose($dfp);
Maybe my code solves your problem:
// Parse all content from csv file and generate array from line.
function csv_content_parser($content) {
foreach (explode("\n", $content) as $line) {
// Generator saves state and can be resumed when the next value is required.
yield str_getcsv($line);
}
}
// Get content from csv file.
$content = file_get_contents('your_file.csv');
// Create one array from csv file's lines.
$data = array();
foreach (csv_content_parser($content) as $fields) {
array_push($data, $fields);
}
In result you have an array with all values from csv.
It would be something like:
Array
(
[0] => Array
(
[0] => text, with commas
[1] => another text
[2] => 123
[3] => text
[4] => 5
)
[1] => Array
(
[0] => some without commas
[1] => another text
[2] => 123
[3] => text
)
[2] => Array
(
[0] => some text, with comma,s or no
[1] => NULL
[2] => 123
[3] => text
)
)
Suppose you have a create a function for same things, Then it should look like
function csvtoarray($filename='', $delimiter){
if(!file_exists($filename) || !is_readable($filename)) return FALSE;
$header = NULL;
$data = array();
if (($handle = fopen($filename, 'r')) !== FALSE ) {
while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
{
if(!$header){
$header = $row;
}else{
$data[] = array_combine($header, $row);
}
}
fclose($handle);
}
if(file_exists($filename)) #unlink($filename);
return $data;
}
$data = csvtoarray('file.csv', ',');
print_r($data);
You could use something like https://github.com/htmlburger/carbon-csv that allows column mapping:
$csv = new \Carbon_CSV\CsvFile('path-to-file/filename.csv');
$csv->set_column_names([
0 => 'first_name',
1 => 'last_name',
2 => 'company_name',
3 => 'address',
]);
foreach ($csv as $row) {
print_r($row);
}
The result of the below code would be something like:
Array
(
[0] => Array
(
[first_name] => John
[last_name] => Doe
[company_name] => Simple Company Name
[address] => Street Name, 1234, City Name, Country Name
)
[1] => Array
(
[first_name] => Jane
[last_name] => Doe
[company_name] => Nice Company Name
[address] => Street Name, 5678, City Name, Country Name
)
)
Another library that does the same thing(and much more) is http://csv.thephpleague.com/9.0/reader/
When you want to keep the index (first line) for multidimensional result array, you can use:
$delim = ';';
$csvFile = file($csv_file);
$firstline = str_getcsv($csvFile[0], $delim);
$data = array();
foreach ($csvFile as $line) {
$line = str_getcsv($line, $delim);
$data[] = array_combine($firstline, $line);
}
I've built an application to extract data from a CSV file , this php application was used to show a daily quote for users.
The full project on github: 365-quotes-php-csv.
Also this is the class Code for the application i've built
<?php
/*
Main Class
please note :
1- the CSV file must be comma separated (,) and each line must End with (;).
2- Feel free to edit the all.CSV file and add all of your 366 New Quotes.
3- don't change any thing specially the CSV file Location.
---------------------------------------------------------------------------
RISS.WORK all copy rights reserved 2018
please Don't Remove
Github/RissWork
Email : info#riss.work
*/
class Quote{
//properties
private $_quote,$_allQuotes;
private static $_instance = null;
//Constructor
private function __construct(){
//Day Count
$dayCount = date(z);
if($this->readCsvAndGetQuote($dayCount)){
return $this->getQuote();
}else{
echo 'Error Cannot open the .CSV File';
}
}
//Methods
//get Instance
public function getInstance(){
if(!isset(self::$_instance)){
self::$_instance = new Quote();
}
return self::$_instance;
}//end of get Instance
//get daily Quote
public function getQuote(){
return $this->_quote;
}//end of get Quote
//Read CSV
private function readCsvAndGetQuote($dayCount = 1 ){
if(($handel = fopen("csv/all.csv" , "r")) !== false){
$this->_allQuotes = fgetcsv($handel,1000000,';');
$this->_quote = explode(',',$this->_allQuotes[$dayCount]);
return true;
}
return false;
}//end of read CSV
}//end of Class
Return a php mapping array with the column of interests :
public function extractCSVDatas($file_uri) {
$AliasToSystemPathMappingArray = [];
if (($handle = fopen($file_uri, "r")) !== FALSE) {
$csv = array_map('str_getcsv', file($file_uri));
//remove header and choose columns among the list:
foreach((array_slice($csv,1)) as $line) {
list($id, $alias, $systemPath) = explode(';',$line[0]);
$AliasToSystemPathMappingArray[] = [$alias, $systemPath];
}
fclose($handle);
}
return $AliasToSystemPathMappingArray;
}
/**
* #return mixed[]
*/
public function csvToArray(string $delimiter, string $filename = ''): array
{
$data = [];
if (file_exists($filename) && is_readable($filename)) {
$header = null;
if (($handle = fopen($filename, 'r')) !== false) {
while (($row = fgetcsv($handle, 1000, $delimiter)) !== false) {
if (!$header) {
$header = $row;
} else {
$data[] = array_combine($header, $row);
}
}
fclose($handle);
}
}
return $data;
}
And why must it be simple when it can be complicated?
Joke aside, here is a quick and easy solution using the PHP function str_getcsv()
Here is an example:
function parse_csv( $filename_or_text, $delimiter=',', $enclosure='"', $linebreak="\n" )
{
$return = array();
if(false !== ($csv = (filter_var($filename_or_text, FILTER_VALIDATE_URL) ? file_get_contents($filename_or_text) : $filename_or_text)))
{
$csv = trim($csv);
$csv = mb_convert_encoding($csv, 'UTF-16LE');
foreach(str_getcsv($csv, $linebreak, $enclosure) as $row){
$col = str_getcsv($row, $delimiter, $enclosure);
$col = array_map('trim', $col);
$return[] = $col;
}
}
else
{
throw new \Exception('Can not open the file.');
$return = false;
}
return $return;
}
Imagine a situation where you need a function that works with both URL and comma delimited text. This is exactly the function that works like that. Just simply insert a CSV URL or comma separated text and it work nicely.
Just created a function that extracts data from .csv file or csv formatted text and then parses it for more convenient usage (presuming the first line is the columns). Works with however many rows/columns you'd like/have, just simply point the function to the file location/string and it will return the results!
function csvParse($input, $callback = false){
$results = [];
$raw_array = (is_file($input)) ? array_map('str_getcsv', file($input)) : array_map('str_getcsv', explode("\n", $input));
$array = array_splice($raw_array, 1, count($raw_array));
foreach($raw_array[0] as $c) $columns[] = $c;
foreach($array as $key0 => $val0)
foreach($val0 as $key1 => $val1)
$results[$key0][$columns[$key1]] = $val1;
if(is_callable($callback)) call_user_func_array($callback, array($results));
else return $results;
}
# Either One Would Work
$input = "dir/file.csv";
$input = "name,age,occupation,city\nCrimin4L,24,Programmer,New York\nMrAwesome,20,Gamer,Los Angeles";
# Usage #1
$array = csvParse($input);
var_export($array);
# Usage #2
csvParse($input, function($array){
var_export($array);
});
Input:
name,age,occupation,city
Crimin4L,24,Programmer,New York
MrAwesome,20,Gamer,Los Angeles
Array Output:
array (
0 =>
array (
'name' => 'Crimin4L',
'age' => '24',
'occupation' => 'programmer',
'city' => 'New York',
),
1 =>
array (
'name' => 'MrAwesome',
'age' => '20',
'occupation' => 'gamer',
'city' => 'Los Angeles',
),
)
Live Demo: https://ideone.com/Sa1aMO

Categories