PHP inserting value only once - php

I am trying to add categories in a database. Things is the script is reading the categories from a product list, therefore there are duplicate values as it'd be like reading
PRODUCT NAME - DETAIL 1 - DETAIL 2 - CATEGORY
Rinse and repeat.
I have my code down and the insert works but it stops at the first product's category value as if I put it out of my foreach loop.
<?php
$filecsv = 'pricelist.csv';
$rows = file($filecsv);
foreach($rows as $row){
$c1 = explode('|', $row);
if($c1['6'] == "not available"){
unset($c1);
continue;
}
//echo '<pre>'.print_r($c1[9], true).'</pre>';
$bool = Db::getInstance()->executeS("SELECT CASE WHEN EXISTS (SELECT * FROM b2b_category WHERE name_b2bcategory IN ('".$c1[9]."') ) THEN true ELSE false end");
foreach($bool[0] as $keyB => $valueB){
$verify = $valueB;
$count = 0;
if($valueB != 1){
Db::getInstance()->execute("INSERT INTO b2b_category (id_b2bcategory, name_b2bcategory, position_b2bcategory, active_b2bcategory) VALUES (".$count.", '".$c1[9]."', '0', '0')");
$count++;
//echo '<pre>'.print_r($valueB, true).'</pre>';
}
}
}
?>
I also want to point out my $c1 variable has multiple arrays. It's not one multi-dimensional array.
So it's like
Array {
etc
}
Array {
etc
}
Array {
etc
}
Array {
etc
}
Array {
etc
}

Since you're using MySQL, you can use on duplicate key update clause:
Db::getInstance()->execute(
"INSERT INTO b2b_category (id_b2bcategory, name_b2bcategory, position_b2bcategory, active_b2bcategory)
VALUES (".$count.", '".$c1[9]."', '0', '0')
on duplicate key update name_b2bcategory = '".$c1[9]."'"
);
You can also use a select count(1) instead of when exists:
$cnt = Db::getInstance()->executeS("SELECT count(1) FROM b2b_category WHERE name_b2bcategory IN = '".$c1[9]."'");
if($cnt[0] == 0) {
Db::getInstance()->execute("INSERT INTO b2b_category (id_b2bcategory, name_b2bcategory, position_b2bcategory, active_b2bcategory) VALUES (".$count.", '".$c1[9]."', '0', '0')");
$count++;
}

I fixed it by using this function and using my same .csv file as a multi-dimensional array. Before I couldn't operate with it due to my output being a fake array, it was recognized as string if anything. With this I could easily operate on the sub-arrays through the standard array PHP functions shortly after.
<?php
function csv_to_multidimension_array($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 ) {
$data[] = $row;
}
fclose($handle);
}
return $data;
}

Related

How to use recursive function to produce a 1-D array in PHP that contains a hierarchical comment reply system?

I have 2 tables. Table 'comments' contains all the comments with cid ,comment as fields. and another table 'reply' which consists of cid and rpid which stores which comment is the reply of which comment.
function array_gen($c, $array, $total, $conn, $f) {
$array[] = $c;
$sql = "SELECT rpid FROM reply WHERE cmid = '$c';";
$st = $conn->query($sql);
$st->setFetchMode(PDO::FETCH_ASSOC);
$rpid = $st->fetchAll();
$count = $st -> rowCount();
if ($count > 0) {
foreach ($rpid as $r) {
$array = array_gen($r['rpid'], $array, $total, $conn, $f);
}
}
else {
echo $c;
return $array;
}
while ($f <= $total) {
if (! in_array($f, $array)) {
$array = array_gen($f, $array, $total, $conn, $f);
}
$f++;
}
return $array;
}
I tried out a function with parameters total number of comments ($total), first comment ($c), empty array ($array), a flag variable $f initialised to value of $c and a PDO connection variable $conn.
It works perfectly upto 2 level of comment-reply. But when it comes to 3rd level i.e, a reply is given to another reply, it starts misbehaving. Function return is not working properly inside foreach loop.

Sorting An Array of Objects Based on Multiple Parameters

I'm trying to make an agenda of panelists for an event company - their site is made with PHP. They already have a CSV file which lists the panelist. I wrote some code so that they can just upload their CSV to their server and have it render as an table.
The csv is set up more or less like this:
Panel, Name, Last Name, Title, Company, Moderator
tuesday, John, Doe, Partner, Acme,1
tuesday, Jane, "O Reily", Partner, SkyNet,0
tuesday, Samatha, Klein, CEO, Sea World,0
tuesday, Bill, Clarke, Head of Marketing, TNT,0
wednesday, Mohammed, Algarisi, Managing Director, Cheesy Photos,1
wednesday, Tim, Draper, Founding and Managing Partner, Draper Associates,0
Anyhow, they want the panelists to be sorted alphabetically by last name, with the moderator displaying first. I'm having trouble doing this in PHP.
I'm not so used to PHP code so I'm sure I must be missing stuff, should I have set this up differently? What's the best way to sort it?
Here's basically what I did-
First I made a Panelist class:
class Panelist {
function __construct($panel, $name, $lastname, $title, $company, $moderator){
$this -> panel = $panel;
$this -> name = $name;
$this -> lastname = $lastname;
$this -> title = $title;
$this -> company = $company;
$this -> moderator = $moderator;
}
}
Then an empty array where we will store our Panelist objects
$panelists =array();
$row = 1;
//accesses our csv file from which we will get the data for the objects
if(($handle = fopen("agenda.csv", "r")) !== FALSE) {
//loops through the csv file by row
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
//skips the header (first) row
if($row == 1) {$row++; continue;}
//instanciates a Panelist object for every row in the csv file
$name = new Panelist($data[0], $data[1], $data[2], $data[3], $data[4], data[5] );
//adds object to our $panelist array
array_push($panelists, $name);
}
Then I have an output function that recieves two arguments:
1. $arr - the array where the objects are stored
2. $panelName - the name of the panel to output
function outputSpeakers($arr, $panelName){
// loops through objects in $arr
foreach($arr as $obj){
//only outputs objects with a panel value matching $panelName:
if($obj->panel == $panelName){
$name = $obj->name;
$lastname = $obj->lastname;
$title = $obj->title;
$company= $obj->company;
//lots of condition formatting stuff here that's not important such as...
if($obj->moderator == '1'){
//if the moderator is "TBA" - don't output title or company:
if($name == ' TBA'){
//format this way
} //else ...
}
}
}
}
?>
Then, in my agenda.php file I include the above class file and do:
<div class="panel-list">
<? outputSpeakers($panelist, "tuesday"); ?>
</div>
Thanks! :-)
You are getting there.
In brief, you can try this:
if ($obj->panel == $panelName) {
$result[$obj->{'last name'}] = $obj;
}
ksort($result);
But I would use a different way to create the agenda object.
<?php
class Panelist {
private $_agenda = null;
public function put($csv) {
if (!file_exists($csv)) {
return false;
}
if (($handle = fopen($csv, "r")) !== FALSE) {
$row = 1;
$count = 0;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if ($row == 1) {
$label = $data;
$count = count($data);
} else {
if (count($data) == $count) {
for($i = 0; $i < $count; $i++) {
$agenda[$row][trim(strtolower($label[$i]))] = trim(strtolower($data[$i]));
}
}
}
$row++;
}
fclose($handle);
$this->_agenda = json_decode(json_encode($agenda));
return $this;
}
}
public function get($label, $value) {
$result = [];
if (!property_exists($this, '_agenda')) {
return false;
}
foreach ($this->_agenda as $item) {
// loop through agenda for match values by label
if (!empty($item->{$label}) && !empty($item->{'last name'}) && $item->{$label} == $value) {
// arrange $result key with last name;
$result[$item->{'last name'}] = $item;
}
}
// sort $result by key with ascending order
ksort($result);
return $result;
}
}
$panelist = new Panelist;
if ($agenda = $panelist->put("agenda.csv")->get('panel', 'tuesday')) {
foreach ($agenda as $item) {
echo $item->name . '<br>';
}
}
OUTPUT:
bill
john
samatha
jane

Incrementing the value in multidimensional array in php

I couldn't understand the multidimensional array in PHP properly. I have a CSV file having two columns as shown below:
I am trying to create an array of array, in which each key is a cataegory. However, the value of each key is an array. In this array, each key is company and value is the count of the product. See below the code:
<?php
//array contains value
function contains_value($my_array, $value_search){
foreach ($my_array as $key => $value) {
if ($value === $value_search)
return true;
}
return false;
}
//array contains key
function contains_key($my_array, $key_search){
foreach ($my_array as $key => $value) {
if ($key === $key_search)
return true;
}
return false;
}
$handle = fopen("product_list.csv", "r");
$products = array();
if ($handle) {
while (($line = fgets($handle)) !== false) {
$product = explode(",", $line);
$category = $product[0];
$company = $product[1];
if (contains_key($products, $category)) {
if (contains_value($products, $company)) {
//increase the count of category by 1
$products[$category][$company] = $products[$category][$company] + 1;
} else {
//append new company with count 1
array_push($products[$category], array(
$company,
1
));
}
} else {
//initialize new company with count 1
$products[$category] = array(
$company,
1
);
}
}
fclose($handle);
}
var_dump($products);
?>
I noticed that the var_dump($products) is not showing correction information. I am expecting following kind of result:
I haven't enough reputation to reply, but I think he need counts.
To complete the answer of Alive to Die, more something like this:
if (!array_key_exists($category, $products)) {
products[$category] = [];
}
if (!array_key_exists($company, $products[$category])) {
products[$category][$company] = 0;
}
++$results[$cataegory][$company];
But cleaner ;)
Edit:
If I remember well, his first idea was this:
$products[$category][] = $company;
The code is shorter. Maybe you can combine the two ideas.

Getting data from mysql and creating a csv file issue

I want to extract some data and create a csv file. This is how my attributes table looks like. you can see it in the picture:
HERE
This is my code, what i tried:
$select = mysql_query("select * from attributes");
$final ="";
$i = 0;
while($row = mysql_fetch_array($select)) {
$id_produs = $row['id_produs'];
$n_attr = $row['nume_attr'];
$val = $row['val_attr'];
$final .= $id_produs . "%%" . $val . "%%";
$csv_array_attributes[$i] = $final;
$i++;
}
This is the part when i create the CSV file:
$file = fopen("attributes.csv", "w+");
foreach ($csv_array_attributes as $line) {
fputcsv($file, explode('%%', $line), "^", "`");
}
fclose($file);
AND this would be the wanted result: HERE. So, the nume_attr should be the header for every column in the csv and the val_attr should be the values for every nume_attr (see the image).
I tried many ways but I don't get this result from the image. I have to mention that my table "attributes" has more than 74000 rows.
This is the table structure:
CREATE TABLE `attributes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_produs` text NOT NULL,
`nume_attr` text NOT NULL,
`val_attr` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=673912 DEFAULT CHARSET=latin1;
/*Try following code */
$select = mysql_query("select * from attributes");
$i = 0;
$csv_array_attributes[$i]=array('sku','manufacturer_article','manufacturer');
$i++;
while($row = mysql_fetch_array($select)) {
$csv_array_attributes[$i] =array('sku'=>$row['id_produs'],'manufacturer_article'=>$row['nume_attr'],'manufacturer'=>$row['val_attr']);
$i++;
}
$file = fopen("attributes.csv", "w+");
foreach ($csv_array_attributes as $line) {
fputcsv($file,$line);
}
fclose($file);
Let's assume speed isn't the issue here and neither is concurrency, i.e. you just want the result now no matter how good, bad or ugly the solution is ;-)
First query all the attribute names via SELECT DISTINCT nume_attr FROM attributes
Store those names as keys of an array with empty string values, i.e. you should have an array like
$template = array(
'Manufacturer Article' => '',
'Manufacturer' => '',
...
)
Make a variable that stores the currently processed id_produs (start with false).
Make a variable that stores the current "csv"-record ( again start with false )
Query all records ordered by id_produs and iteratore over the result.
If the current record has a different id_produs than the "currently processed" write out the current "csv"-array and start anew with the template array created in the first step and the current id_produs as ...the current id_produs. For each record write the val_attr value to the key nume_attr in the csv array.
You will have to check/write the last record after the iteration.
/* try following code,and reply if it will helpful to you or not */
$select = mysql_query("select * from attributes");
$i = 0;
$i++;
while($row = mysql_fetch_array($select)) {
$csv_array_attributes[$row['id_produs']][$row['nume_attr']] =$row['val_attr'];
$i++;
}
$arraytempheader=array();
$arraytemp=array();
$arraytempheader[0]="";
$j=1;
foreach ($csv_array_attributes as $Colname=>$alline) {
if($j!=1)
{
foreach($arraytempheader as $key=>$val)
{
if($key!=$j && $key!=0)
$arraytemp[$Colname][$key]="";
}
}
foreach ($alline as $keyline=>$valline)
{
$arraytempheader[$j]=$keyline;
$arraytemp[$Colname][$j]=$valline;
$j++;
}
}
$file = fopen("attributes.csv", "w+");
fputcsv($file,$arraytempheader);
foreach ($arraytemp as $Colname=>$alline) {
$finalArray=array();
$finalArray[]=$Colname;
$finalArray=array_merge($finalArray,$alline);
fputcsv($file,$finalArray);
}
fclose($file);
Try to fix this in other way.
Here you select the attributes and store them into array
$select = mysql_query("select * from attributes");
$rezultat=array();
while($row = mysql_fetch_array($select)) {
$id_produs = $row['id_produs'];
$n_attr = $row['nume_attr'];
$val = $row['val_attr'];
//$final .= $id_produs . "%%" . $val . "%%";
$rezultat[] = array('id'=>$id_produs,'attr'=>$val);
}
And here you write them to the file.
$file = fopen("attributes.csv", "w+");
foreach ($rezultat as $line) {
fputcsv($file, $line, "^", "`");
}
fclose($file);

Checking while loop key exists in seperate array

Having checked a variety of questions but not being able to find quite what I need, I am at a bit of a loss.
I am trying to chose the columns from MySQL I want exported to CSV by parsing the column names and adding the valid column names to a $colnames array, then adding those values as headers to the CSV and then only displaying the relevant data from the database through a while loop.
I have looked at the following in particular having been guided there from other questions: How to get all the key in multi-dimensional array in php
Here is the code:
function query_to_csv($query, $filename, $attachment = false, $headers = true, $specs_off = false) {
if($attachment) {
// send response headers to the browser
header( 'Content-Type: text/csv; charset=UTF-8' );
header( 'Content-Disposition: attachment;filename='.$filename);
$fp = fopen('php://output', 'w');
} else {
$fp = fopen($filename, 'w');
}
$result = mysql_query($query) or die( mysql_error() );
if($headers) {
// output header row (if at least one row exists)
$row = mysql_fetch_assoc($result);
if($row) {
// PRODUCTS TABLE SPECIFIC - get rid of specs_ and free_ columns so have nicer data set for user
if($specs_off) {
$columnames = array_keys($row);
$colnames = array();
//$colnames = array_keys($row);
foreach($columnames as $key => $value) {
if((substr_count($value, "spec_") < 1) && (substr_count($value, "free_") < 1)) {
array_push($colnames, $value);
}
}
}
else {
$colnames = array_keys($row);
}
// add in additional columns if exporting client data
if($table == 'clients') {array_push($colnames, "products", "last_order_date");}
//write the colnames to the csv file
fputcsv($fp, $colnames);
// reset pointer back to beginning
mysql_data_seek($result, 0);
}
} // done with the headers etc, now lets get on with the data
// clear out and create the $row_data array
$row_data = array();
// run through the row array adding values to row_data as we go
while($row = mysql_fetch_assoc($result)) {
// create the array_keys_multi from https://stackoverflow.com/questions/11234852/how-to-get-all-the-key-in-multi-dimensional-array-in-php/11234924#11234924
function array_keys_multi(array $array) {
$keys = array();
foreach ($array as $key => $value) {
$keys[] = $key;
if (is_array($array[$key])) {
$keys = array_merge($keys, array_keys_multi($array[$key]));
}
}
return $keys;
}
// run the function on the $row array
array_keys_multi($row);
// now use the $keys array
foreach($keys as $key => $value) {
// check if the value is in the colnames array and if so push the data on to the $row_data array ready for export to CSV
if(in_array($value, $colnames)) {
array_push($row_data, $row[$value]);
}
}
// now we are ready to write the CSV
fputcsv($fp, $row_data);
}
fclose($fp);
exit;
} // end of query_to_csv
// Write the sql statement
$sql = "SELECT * FROM ".$table." ";
if(isset($where_1_col)) { $sql .= " WHERE `".$where_1_col."` = '".$where_1_val."'"; }
if(isset($where_2_col)) { $sql .= " AND `".$where_2_col."` = '".$where_2_val."'"; }
if(isset($where_3_col)) { $sql .= " AND `".$where_3_col."` = '".$where_3_val."'"; }
if(isset($where_4_col)) { $sql .= " AND `".$where_4_col."` = '".$where_4_val."'"; }
if(isset($order_by_col)) { $sql .= " ORDER BY `".$order_by_col."` ". strtoupper($order_by_dir) ." "; }
// output as an attachment
query_to_csv($sql, $table."_export.csv", true, true, true);
All I am getting is a huge export of the chosen column names repeated as many times as there are values from the initial query. I don't know how to get the values in.
Any suggestions on where I am going wrong or how I can undertake this more neatly are welcomed.
It seems that you just append the new row data to $row_data but never clear that array.
array_push($row_data, $row[$value]);
What I did to fix it:
Move
// clear out and create the $row_data array
$row_data = array();
into the while loop.
Change
// clear out and create the $row_data array
$row_data = array();
while($row = mysql_fetch_assoc($result)) {
...
}
To
while($row = mysql_fetch_assoc($result)) {
// clear out and create the $row_data array
$row_data = array();
...
}
Note:
You are using $table everywhere but never define it. Like here if($table == 'clients')
If it is a global var you need to add global $table or a parameter to your function, too.
Edit:
As mentioned in my comment on your question you could just use array_keys() to get the keys.
php.net/manual/de/function.array-keys.php
And then change
array_keys_multi($row);
to
$keys = array_keys($row);
After that you can remove array_keys_multi()
Further you could move that part in front of your while-loop because you only need to calculate the column names you need once and not in every iteration.

Categories