You don’t need the site method, I think. You can use the “inner parts” of that function inside the original ` csv function.
this doesn’t seems to work
function csv(string $file, string $length, string $delimiter = ','): array {
$fh = fopen($file, $length, $delimiter);
$header_line = fgets($fh);
$header_line = str_replace("\xEF\xBB\xBF", '', $header_line);
$keys = str_getcsv($header_line);
$csv = [];
while ($row = fgetcsv($fh, $delimiter)) {
$csv[] = array_combine($keys, $row);
}
return $csv;
}
Could you please indicate what doesn’t work? Do you get an error? Or no result?
yes i get an error message: fopen(/content/folder/file.csv): failed to open stream: Undefined error: 0
The path is correct. I added line breaks into the animals csv file for testing purpose.
Here is the rest of the code:
$csv = csv($page->root() . '/file.csv', ',');
$kirby->impersonate('kirby');
foreach ($csv as $animal) {
$newPage = page('animals')->createChild([
'slug' => Str::slug($animal['title']),
'template' => 'animal',
'model' => 'animal',
'draft' => 0,
'num' => 0,
'content' => [
'id' => $animal['id'],
'title' => $animal['title'],
'text' => $animal['content']
]
])->changeStatus("listed", $i++);
};
I think this line is wrong an should be just
$fh = fopen($file, 'r');
Thanks a lot !
Is there is a way to download a picture into the created folder, from url contained in a specific image URL’s field of the csv?
I have a field into the csv named Image URL, with an image url as value.
So it could become a cover for the page?
thanks for the precious help
Yes, you could create a remote request to fetch the image, then save it into the page folder.
Hello @texnixe, I have quite a similar use case as the original question.
As a one time thing, I would like to create pages from a CSV programmatically. I have used the solution that you provided, however this line is throwing an “Undefined index: title” error:
'slug' => Str::slug($flag['title']),
Here is the code I have included in my flags.php template.
<?php
// the `csv` function can live in a plugin file or in the template where you want to create the children if its only a one time thing
function csv(string $file, string $delimiter = ','): array
{
$lines = file($file);
$lines[0] = str_replace("\xEF\xBB\xBF", '', $lines[0]);
$csv = array_map(function($d) use($delimiter) {
return str_getcsv($d, $delimiter);
}, $lines);
array_walk($csv, function(&$a) use ($csv) {
$a = array_combine($csv[0], $a);
});
array_shift($csv);
return $csv;
}
// Adapt this to your csv file name and the fields in your csv file:
// Example based on the guide example
$csv = csv($page->root() . '/flags.csv', ';');
$kirby->impersonate('kirby');
foreach ($csv as $flag) {
$newPage = page('flags')->createChild([
'slug' => Str::slug($flag['title']),
'template' => 'flag',
'content' => [
'title' => $flag['title'],
'colours' => $flag['colours'],
]
]);
};
?>
My CSV file definitely includes title, so I am not sure what could be causing this. Any help would be greatly appreciated
Use dump() to see what $csv returns.
The contents of the dump was:
Array
(
[0] => Array
(
[title,colours] => France,"blue, red"
)
[1] => Array
(
[title,colours] => Bahamas,yellow
)
)
You are using the wrong delimiter. You columns are separated by comma, not semicolon.
Thanks so much @texnixe, that solved it