I'm having a headache trying to figure this out.
My folder structure is as follows:
index.php
helpers:
API.php
helpers.php
assets:
products.csv
debug:
debug_info.txt
My index file looks as follows:
<?php
require_once 'helpers/API.php';
file_put_contents('debug/debug_info.txt', "New request started");
if (in_array($_GET['action'],array('insertOrder','updateOrder'))){
$date = date(DATE_RFC2822);
$api = new API();
file_put_contents('debug/debug_info.txt', "New: {$_GET['action']} at {$date}\n", FILE_APPEND | LOCK_EX);
file_put_contents('debug/debug_info.txt', "This is the product " . $api->getOrder());
}
API.php
<?php
class API {
private $order;
private $product_table;
function __construct(){
$this->order = $this->setOrder();
$this->product_table = $this->setProductTable();
}
public function setOrder(){return $this->readJSON();}
public function setProductTable(){return $this->readProductsCSV(__DIR__ . '/../assets/products.csv');}
public function getOrder(){return $this->order;}
public function getProductsTable(){return $this->product_table;}
private function readJSON(){
$stream = fopen('php://input', 'rb');
$json = stream_get_contents($stream);
fclose($stream);
return print_r(json_decode($json, true), true);
}
private function readProductsCSV($csv = '', $delimiter = ','){
if (!file_exists($csv) || !is_readable($csv)){
return "Someone f*cked up -_-";
}
$header = NULL;
$data = array();
if (($handle = fopen($csv, 'r')) !== false){
while (($row = fgetcsv($csv, 100, $delimiter)) !== false){
if (!$header)
$header = $row;
else if($row[0] != ''){
$row = array_merge(array_slice($row,0,2), array_filter(array_slice($row, 2)));
$sku = $row[0];
$data[$sku]['productCode'] = $row[1];
$data[$sku]['Description'] = $row[2];
}
}
fclose($handle);
}
array_change_key_case($data, CASE_LOWER);
return print_r($data, true);
}
}
When I use file_put_contents('debug/debug_info.txt', $api->getOrder()); I get the data correctly ( I have to comment all the product_table parts for it to work tho ).
But I can't get the CSV file no matter what I do.
I've ran file_exists() && is_readable ( and they passed ) but still nothing.
If I declare the function readProductsCSV in the index.php it works.. but it seems using it as a method bugs everything.
Could someone please help me?
Logic bugs:
if (($handle = fopen($csv, 'r')) !== false){
^---your csv file handle
while (($row = fgetcsv($csv, 100, $delimiter)) !== false){
^---your csv filename, which SHOULD be the handle
Since you're trying to use a string as a filehandle, you get a boolean false back from fgetcsv() for failure, that false terminates the while loop, and $data stays an empty array.
Related
I'm trying to make a translation module for my web project and i hit a wall. I written two functions, one for importing the CSV data and the other for changing, deleting and adding new data to the CSV file.
Everything works like a charm except the adding part. It adds the data to the CSV file but when i want to import it in the website via PHP it doesn't display the added values. (It see that their should be values but it gives empty results in return) the function i use for reading the csv file is:
// Load in CSV (File name, delimiter, Fixed array[key,value] (optional))
function load__CSV($filename='', $delimiter=';', $fixed = null){
if(!file_exists($filename) || !is_readable($filename)) {
return FALSE;
}
$header = NULL;
$data = array();
if (($handle = fopen($filename, 'r')) !== FALSE) {
while (($row = fgetcsv($handle, 100000, $delimiter)) !== FALSE) {
if (!$header) {
$header = $row;
} else {
$data[] = array_combine($header, $row);
}
}
fclose($handle);
}
if($fixed != null) {
foreach($data as $entry){
$set_csv[$entry[''.$fixed[0].'']] = $entry[''.$fixed[1].''];
}
} else {
$set_csv = $data;
}
return $set_csv;
}
The function i use to add, edit or remove CSV content is:
// Change csv
function update__csv($csv = 'csv/language.csv',$key = array(2,''),$values = array([3,''],[4,'']),$status = 'change') {
$input = fopen(BASE_URL.$csv, 'r');
$output = fopen(BASE_URL.'csv/temporary.csv', 'w');
while (false !== ($data = fgetcsv($input, 10000, ";"))) {
if ($data[$key[0]] == $key[1]) {
foreach ($values as $value) {
$data[$value[0]] = $value[1];
}
if ($status == 'change' || $status == 'new') {
fputcsv($output, $data, ";");
}
} else {
fputcsv($output, $data, ";");
}
}
if($status == 'new'){
fputcsv($output, $values, ";");
}
fclose( $input );
fclose( $output );
unlink(BASE_URL . $csv);
rename(BASE_URL . 'csv/temporary.csv', BASE_URL . $csv);
}
If i add new values to the CSV file and then open the CSV on my PC and safe it again (without changing a thing) to CSV with UTF-8 encoding then it works as expected and loads the correct data. If i open the CSV in Notepad++ i see this difference between manual added items and php added items:
I tried other encoding methods but that is kinda new for me so i think i did something wrong. Thank you in advance for helping me!
I did find the answer after some more debugging. One value of the array didn't contain a string but a true or false statement. This meant that it didn't add the data the right way into the CSV file.
I fixed it by adding strval() to every variable before putting it into an array.
began programming in PHP this week so total beginner here.
The code sample below is not complete but it gives you an idea of the issue.
If I keep only 2 properties in my class I am able to convert and display the JSON structure from my array, HOWEVER as I add more properties in the class nothing is returned/displayed/converted. Why is that? Thanks
NOte: I tried a few options from http://php.net/manual/en/json.constants.php
<?php
class myObject
{
public $Channel;
public $Program;
public $Episode;
public $Start;
public $End;
public $TZ;
}
$myBlackouts = array();
$row = 1;
if (($handle = fopen($file_name, 'r')) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ',')) !== FALSE)
{
//feed variables here
$myBlackout = new myObject;
$myBlackout->Channel = $Channel;
$myBlackout->Program = $Program;
$myBlackout->Episode = $Episode;
$myBlackout->Start = $StartEpoch;
$myBlackout->End = $EndEpoch;
$myBlackout->TZ = $TZ;
$myBlackouts[] = $myBlackout;
$row++;
}
fclose($handle);
}
echo 'Array lenght: '.count($myBlackouts)."\n"; //331 elements inside array
$myJSON = json_encode($myBlackouts); //convert array to JSON
echo $myJSON; // it will not display anything if I increase the number of properties in my class above
?>
Thanks
iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($input)); was the solution for my case.
I am trying to turn an input file in the form below into a series of objects that can be manipulated.
arabian_sea_area = {
1926 1927 1931 1932 1933 2029 2030
}
gulf_of_aden_sea_area = {
1925 2024 5285 5286
}
sdf
<?php
$all_areas = array();
if (($handle = fopen("area.txt", "r")) == False)
{
die("failed to open file\n");
}
while (($line = fgets($handle)) !== FALSE)
{
if (ctype_alpha($line[0]))
{
$line= explode(" ",$line);
// echo($line[0]."\n");
$area = $line[0];
$IDs = explode(" ", fgets($handle));
$IDs[0] = ltrim($IDs[0], ' '); // trying to remove tab from first ID
$all_areas[$area] = $IDs;
//array_push($all_areas, $temp);
}
}
//echo("a\n");
print_r($all_areas["arabian_sea_area"]);
//var_dump ($all_areas);
?>
The values print correctly in the commented out debug lines but fail to print anything for the var_dump at the end.
edit: I realize this was unclear, what I was trying to do was create a master "all_areas" array that linked to objects titled the first line (ie. arabian_sea_area etc.) and I could then get at the numerical Ids for each area algorithmically for a later script.
There are many issues with your code:
1-
if (ctype_alpha($line[0]))
{
$line= explode(" ",$line);
//echo($line[0]."\n");
$temp = $line[0];
$temp = new Area;
$temp->filler($line, $handle);
}
you are creating a $temp variable but you forgot to push it to your main array $all_areas. use array_push
2-
var_dump ($arabian_sea_area);
$arabian_sea_area does not exist.
Did you mean to print your main array $all_areas ?
3- Recommendation:
On errors (echo("failed to open file\n");) its recommended to use die("failed to open file\n"); instead of echo. as die will stop the rest of the script from executing.
-- UPDATE --
I edited your code in a way that should work fine:
class Area {
public $area_name;
public $IDs = array();
public function filler($line, $handle) {
$this->area_name = $line[0];
//echo($this->area_name."\n");
$this->IDs = explode(" ", fgets($handle));
//print_r($this->IDs);
}
}
$all_areas = array();
if (($handle = fopen("area.txt", "r")) == False)
{
die("failed to open file\n");
}
while (($line = fgets($handle)) !== FALSE)
{
if (ctype_alpha($line[0]))
{
$line= explode(" ",$line);
// echo($line[0]."\n");
$temp = $line[0];
$temp = new Area;
$temp->filler($line, $handle);
array_push($all_areas, $temp);
}
}
//echo("a\n");
var_dump ($all_areas);
You might wanna update it to remove / filter empty values.
im trying to create a php class that will transform an ini in to an array ie:
example.ini...
[helloworld]
testing=1234
the array should look like:
array {
"helloworld" = array {
"testing" = "1234"
}
}
my code fo far is this:
<?php
require_once "UseFullFunctions.inc.php";
class INI {
protected $Keys = array();
protected $Values = array();
public function __construct($FileName) {
if (!file_exists($FileName)){
throwException('File not found',$FileName);
}
$File = fopen($FileName, 'r');
$isIn = "";
while (($line = fgets($File)) !== false) {
if(!startswith($line,'#')){ // checks if the line is a comment
if(startswith($line,'[')){
$isIn = trim($line,'[]');
$this->Keys[$isIn] = '';
$this->Values[$isIn] = array();
} else {
if ($isIn != ""){
$vars = explode("=",$line);
$this->Values[$isIn][$vars[0]] = $vars[1];
}
}
}
}
var_dump($this->Values);
if (!feof($File)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($File);
}
public function getValues() {
return $this->Values;
}
}
?>
the other functions(starts with, throwexception) ive already tested and work fine but it still returns a blank array i think its stuffing up just after it checks if the line is a comment but it doesnt come up with an error messages so i cant be sure
just incase here is my starts with code:
function throwException($message = null,$code = null) {
throw new Exception($message,$code);
}
function startsWith($haystack, $needle)
{
return !strncmp($haystack, $needle, strlen($needle));
}
Take a look at parse_ini_file
http://uk3.php.net/parse_ini_file
i'm with some troubles figuring out how to read the CSV file that I upload, probably i'm missing something in my Controller code.
public function actionImport() {
$model = new Produtos;
$this->render('import', array('model' => $model) );
if( isset($_FILES['csv_file']) ) {
$handle = fopen($_FILES['csv_file']['tmp_name'], 'r');
if ($handle) {
while( ($line = fgetcsv($handle, 1000, ";")) != FALSE) {
$model->codigo = $line[0];
$model->nome = $line[1];
$model->descricao = $line[2];
$model->stock = $line[3];
$model->data_reposicao = $line[4];
$model->save();
}
}
fclose($handle);
}
}
This is only saving me the last line in the CSV... please some help!
Any help will be really appreciated.
Thank you
I think You missed the name of file, try $_FILES['csv_file']['tmp_name']
http://php.net/manual/en/features.file-upload.post-method.php for reference.
Also Yii does provide file handling, check http://www.yiiframework.com/doc/api/1.1/CUploadedFile for reference
Don't forget to check whether your data is successfully validated or not.
Insert this code between yours:
$model->data_reposicao = $line[4];
if (!$model->validate())
throw new Exception("Validation failed.");
$model->save();
So you can see what's going wrong.
$_FILES is an array, which contains ['element_name']-array. In your case $_FILES is an array of $_FILES['csv_file']['name'], $_FILES['csv_file']['type'], $_FILES['csv_file']['error'], $_FILES['csv_file']['size'] and $_FILES['csv_file']['tmp_name'].
So for short; $_FILES['csv_file'] is an array.
you are saving the same model instance again and again... that is why only the last line gets saved... you will have to create a new model for every line, i.e. in your while loop, add $model = new Produtos;
You need to initialise your model object every time when you need to insert your row into table. The code should be like:
public function actionImport() {
$model = new Produtos;
$this->render('import', array('model' => $model) );
if( isset($_FILES['csv_file']) ) {
$handle = fopen($_FILES['csv_file']['tmp_name'], 'r');
if ($handle) {
while( ($line = fgetcsv($handle, 1000, ";")) != FALSE) {
$modeln = new Produtos;
$modeln->codigo = $line[0];
$modeln->nome = $line[1];
$modeln->descricao = $line[2];
$modeln->stock = $line[3];
$modeln->data_reposicao = $line[4];
$modeln->save();
}
}
fclose($handle);
}
}
I know this is an old post, but I just came across this and just wanted to help someone who might be having the same issue (b/w issue is not with CSV or file upload)
Issue is with how Yii handles saving
You need to set isNewRecord attribute to true and primary key to NULL of model object before saving to save a new record everytime.
$model->PRIMARYKEYCOLUMN = NULL; //Replace PRIMARYKEYCOLUMN with the name of column
$model->isNewRecord = true;
$model->save();
You need to do above step whenever you are saving rows in loop.
$handle = fopen($_FILES['Userimportcsv']['tmp_name']['csv_file'], 'r');
if($handle) {
$row = 1;
while( ($line = fgetcsv($handle, 1000, ",")) != FALSE) {
if($row>1) {
$newModel = new Countries;
$newModel->countryName = $line[0];
$newModel->status = $line[1];
$newModel->save();
}
$row++;
}
}
fclose($handle);