Invalid arguments passed in implode() - php

So I have a CSV file that I'm trying to make into a table.
I gave up on the import GUI after too many errors, and am trying to accomplish the import through a php file.
//create table with KNOWN values
mysql_query("CREATE TABLE uri_faculty
(
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
id INT(15),
lname VARCHAR(50),
fname VARCHAR(50),
mi VARCHAR(3),
Spc_Title VARCHAR(50),
title VARCHAR(50),
deptid INT(5),
dept VARCHAR(50),
degree1 VARCHAR(10),
earned1 INT(4),
school1 VARCHAR(75),
degree2 VARCHAR(10),
earned2 INT(4),
school2 VARCHAR(75),
degree3 VARCHAR(10),
earned3 INT(4),
school3 VARCHAR(75),
degree4 VARCHAR(10),
earned4 INT(4),
school4 VARCHAR(75),
degree5 VARCHAR(10),
earned5 INT(4),
school5 VARCHAR(75),
degree6 VARCHAR(10),
earned6 INT(4),
school6 VARCHAR(75)
)");
//Get CSV file
$getfile = 'faculty_delim2.csv';
$csvfopen = fopen($getfile, "r");
//loop to fill csvget with arrays
for($i=0;!feof($csvfopen);$i++){
$array = fgetcsv($csvfopen);
$insert = implode("','", $array);
//to exclude the first 2 lines (titles of document)
if($i>=1){
//values to be inserted into SQL are displayed
//echo var_dump($array[$i])." <br> ";
$sqlval = $insert;
// var_dump($sqlval);
//the while loop will constantly place values into the database until the file is finished
mysql_query("INSERT INTO uri_faculty (id,lname,fname,mi,Spc_Title,title,deptid,dept,
degree1,earned1,school1,
degree2,earned2,school2,
degree3,earned3,school3,
degree4,earned4,school4,
degree5,earned5,school5,
degree6,earned6,school6,) VALUES ('$sqlval')
");
}
}
fclose($csvfopen);
echo "complete";
?>
I keep getting an error saying that implode is receiving incorrect parameters, yet every bit of documentation I've found says that I am correct.
I changed the permissions of the file, and it is in the right place.

Instead of this:
for($i=0;!feof($csvfopen);$i++){
$array = fgetcsv($csvfopen);
I would write this:
while ($array = fgetcsv($csvfopen)) {
The loop will automatically finish when there are no more rows to read. Your error is probably an edge case, where the file still thinks it is not at feof but in spite of that, there are no more rows, and fgetcsv returns false.
By the way, two other issues:
You will run into another error soon:
. . . degree6,earned6,school6,) VALUES . . .
You must not put a comma after the last column. Write this instead:
. . . degree6,earned6,school6) VALUES . .
You are wide open to SQL injection issues. What happens when one of your CSV fields contains an apostrophe? You should learn how to use PDO with query parameters. Or failing that, use escaping:
$insert = implode("','", array_map('mysql_real_escape_string', $array));
Finally, you should consider skipping fgetcsv and use LOAD DATA INFILE. Then all your CSV issues, and escaping issues just go away.
mysql_query("LOAD DATA LOCAL INFILE 'faculty_delim2.csv' INTO TABLE uri_faculty IGNORE 2 LINES");

Related

How to use textfile to create SQL table entries?

I have a text file that looks like this:
WPG GRIFFON, WIREHAIRED
AFG HOUND, AFGHAN
IBI HOUND, IBIZAN
WOF HOUND, IRISH WOLF
OTT HOUND, OTTER
PHA HOUND, PHAROAH
DER HOUND, SCOTTISH DEER
JIN JINDO
...
and I am trying to rewrite this line of code so it says the names of the dogs
$link = mysqli_connect($servername, $username, $password, $db) or die(mysqli_error($link));
mysqli_query($link, "CREATE TABLE IF NOT EXISTS `description` (`descID` int(10) NOT NULL AUTO_INCREMENT, `desc` text NOT NULL, PRIMARY KEY (`descID`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
mysqli_query($link, "INSERT INTO description (descID, desc) VALUES(1, 'description 1'),(2, 'description 2'),(3, 'description 3'),(4, 'description 4');");
However, I always get an error and it crashes the webpage, because I can't get the file to be read and saved.
$handle = #fopen("names.txt", "r");
while (!feof($handle)) // Loop til end of file.
{
$buffer = fgets($handle, 4096);
$sql = "INSERT INTO data_table ...."
mysql_query($sql,$conn) or die(mysql_error());
}
Do you need to use INSERT statements? There are two other very viable options (a little out of the box, maybe):
LOAD DATA: SQL that loads pre-built CSV data into a table. See the MySQL manual and this SO thread
Example usage (from the linked SO thread):
LOAD DATA INFILE 'path/file.csv'
INTO TABLE tbl_name
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
(column1, column2, column3);
mysqlimport: If you have access to the MySql shell, you can use this to import a physical CSV to the db. See the MySQL manual or this post from a random google click

Creating a database table using a CSV file by making PDO calls

I have been trying to create a database by using the first row of a CSV file, however I keep getting an error about my PDO syntax. Apparently something is going wrong with varchar(250) in the $columns variable:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'varchar(250))' at line 1
The code is below:
<?
/********************************************************************************/
// Parameters: filename.csv table_name
$argv = 'seo_domains.csv seo_domains';
if($argv[1]) { $file = $argv[1]; }
else {
echo "Please provide a file name\n"; exit;
}
if($argv[2]) { $table = $argv[2]; }
else {
$table = pathinfo($file);
$table = 'seo_domains';
}
/********************************************************************************/
// Get the first row to create the column headings
$fp = fopen('seo_domains.csv', 'r');
$frow = fgetcsv($fp);
$ccount = 0;
foreach($frow as $column) {
$ccount++;
if($columns) $columns .= ', ';
$columns .= "$column varchar(250)";
}
$qry = $dbcon->prepare("CREATE TABLE if not exists $table ($columns);");
$qry->execute();
/********************************************************************************/
// Import the data into the newly created table.
$file = $file;
$qry = $dbcon->prepare("load data infile '$file' into table $table fields terminated by ',' ignore 1 lines");
$qry->execute();
?>
I changed the $fp fopen to a static value instead of using $file because apparently the guy who coded the code mentioned above, did not mention how to format the $argv variable. Yes, I already tried formatting according to his "Parameters" comment on the first line but still, no avail. I also statically changed the $table variable to 'seo_domains' since the $argv variable is not being split properly. Instead of re-coding the above code, I am wondering if anyone has any thoughts as to why my database would be resulting in the described error. Any help is appreciated. Just trying to create a table based on first row of the CSV file provided. Upon creation I would like to continue to insert all the row values below row 1 in the CSV, per usual.
try:
CREATE TABLE if not exists seo_domains (Domain varchar(250), Server varchar(250), IP varchar(250), Username varchar(250), Password varchar(250), Nameserver varchar(250), NameCheap varchar(250), GA varchar(250), WMT varchar(250), SB varchar(250), GAW varchar(250), notes varchar(250), BlankField varchar(250), id INT KEY NOT NULL AUTO_INCREMENT varchar(250));
key is a reserved word in SQL. See image below
As you may find that some of the column names in CSV could be reserved words you will need to escape them. In MySQL backticks are used. ie `key`

Repeat PHP code

I have this code that I would like to know if there is an easier way to have it repeated. I have about 60 of these and I will always be adding more so it would be nice if someone could help me figure out a loop or something so that I won't have to manually add each one. Each of these is making a link to a download, so I am guessing I will probably have to use the variable name as the file name. The file name 01 Intro.mp3 is what tells where the download is, so I am guessing to make this work I would also have to change that to the variable name.
Here is the code I use to get the variable names.
while ($row = mysqli_fetch_array($resultstwo))
{
extract($row);
}
Here is the code that I would like to be repeated. I included two of them.
<?php
if ($intro ==1) {
$strKey = createKey();
mysqli_query($resDB,"INSERT INTO downloads (downloadkey, file, expires) VALUES ('{$strKey}', '01 Intro.mp3', '".(time()+(60*60))."')");
echo "<a href='download.php?key=$strKey'>Intro</a>";
}
?>
<?php
if ($fightingfires ==1) {
$strKey = createKey();
mysqli_query($resDB,"INSERT INTO downloads (downloadkey, file, expires) VALUES ('{$strKey}', '02 Fighting Fires.mp3', '".(time()+(60*60))."')");
echo "<a href='download.php?key=$strKey'>Fighting Fires</a>";
}
?>
I would suggest having some variables within the database if not already included, such as:
id,caption,filename
--------------------
1,Intro,01 Intro.mp3
2,Fighting Fires,02 Fighting Fires.mp3
Here is the SQL query for creating this table:
CREATE TABLE `music` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`caption` varchar(32),
`filename` varchar(32),
PRIMARY KEY (`id`),
UNIQUE KEY `uc_filename` (`filename`)
);
As well as some test data that you can also insert.
INSERT INTO `music`(`caption`,`filename`) VALUES('Intro','01 Intro.mp3'),('Fighting Fires','02 Fighting Fires.mp3');
Assuming the user table follows the current format:
id,username,intro,fightingfires
-------------------------------
1,michael,1,NULL
2,dave,NULL,NULL
I believe that it should be altered to show this instead:
id,username,music_id
--------------------
1,michael,1,
2,dave,NULL
The structure of this table can be written as:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32),
`music_id` int(11),
PRIMARY KEY (`id`),
KEY `music_id` (`music_id`),
CONSTRAINT `users_music_id_ibfk_1` FOREIGN KEY (`music_id`) REFERENCES `music` (`id`) ON DELETE CASCADE
);
Now when a music row is deleted from the music table, any users wishing to download that music will also be removed.
Try to query the database like this now:
$resultstwo=$mysqli->query("SELECT `music_id` FROM `users` WHERE `username`='michael'");
Change the username based on which user is logged in, but I imagine you have that under control.
Then you can manage the data better like this:
while ($row = mysqli_fetch_array($resultstwo)) {
$strKey = createKey();
mysqli_query($resDB,"INSERT INTO downloads (downloadkey, file, expires) VALUES ('{$strKey}', '".$row['filename']."', '".(time()+(60*60))."')");
echo "<a href='download.php?key=$strKey'>".$row['caption']."</a>";
break;
}
Then you can better manage downloading of music by adding or deleting columns from the table above.
I don't understand completely what you want to do, but I assume the following:
You're reading from a table which contains filenames, and for each file you want to create the entry in the table downloads, as well as output the HTML link to the download.
Here's how you could do it, but it looks like you need to change your table structure for the files to something like the following:
id track_no filename
In that case, you could do everything directly in the first loop:
<?php
while($row = mysqli_fetch_array($resultstwo))
{
$strKey = createKey();
mysqli_query($resDB,
"INSERT INTO downloads (downloadkey, file, expires)
VALUES(
$strKey,
$row['track_no']." ".$row['filename'],
(time()+(60*60))
)");
echo "$row['filename']";
}
If that doesn't answer your question, you should tell us more about your table containing the files.
Building on other answers, here's how to do the loop and hit the database only once.
$query = "INSERT INTO downloads (downloadkey, file, expires) VALUES ";
while ($row = mysql_fetch_array($resultstwo)) {
$strKey = createKey();
$time = time()+(60*60);
$query .= "('{$strKey}', '{$row['filename']}', {$time}),";
echo "<a href='download.php?key=$strKey'>{$row['caption']}</a>";
}
$query = substr ( $query, 0, -1 ); // Remove the last comma.
mysql_query ( resDB, $query );
The end result of the query will be something like:
INSERT INTO downloads (downloadkey, file, expires) VALUES
('adfsdfgsdgs', 'Bladerunner.avi', 12345678),
('dfghfyadfsg', 'How_I_met_your_mother.avi', 12345678),
('34t34t3t', 'Simpson_the_movie.avi', 12345678),
('taert43te', '{$row['filename']}', 12345678),
('at43t3t', '{$row['filename']}', 12345678),
This will insert all the values into mysql using this one query only.
How about:
function f($condition, $filename, $prettyname)
{
if ($condition)
{
$strKey = createKey();
mysqli_query($resDB,"INSERT INTO downloads (downloadkey, file, expires) VALUES ('{$strKey}', '$filename', '".(time()+(60*60))."')");
echo "<a href='download.php?key=$strKey'>$prettyname</a>";
}
}
And then simply recover the values from the database, a file or just an array as you see fit.

How to get just inserted row from MySql to a php variable?

I'm using Zend Framework and MySql to create my web-application. My SQL-code is the following at the moment:
public static function newTestResult($testId, $accountId, $score, $deviation, $averageTime)
{
try
{
$db = self::conn();
$statement = "INSERT INTO test_results(test_id, test_person_id, score, standard_deviation, average_answer_time, created_at)
VALUES(" . $testId . ", " . $accountId . ", " . $score . ", " . $deviation . ", " . $averageTime . ", NOW())";
$db->query($statement);
$db->closeConnection();
}
catch(Zend_Db_Exception $e)
{
error_log($e->getMessage());
}
}
Now what I'm asking is: How can I get the just inserted row to a variable in PHP? I would want to get my hands on the id-value what MySql is creating automatically for the row.
Here is my table code:
CREATE TABLE test_results(
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
test_id int UNSIGNED NOT NULL,
test_person_id int UNSIGNED NOT NULL,
score float UNSIGNED NOT NULL,
standard_deviation float UNSIGNED NOT NULL,
average_answer_time float UNSIGNED NOT NULL,
removed boolean NOT NULL DEFAULT 0,
created_at datetime) CHARACTER SET utf8 COLLATE utf8_general_ci;
Take a look at the MySQL function "LAST_INSERT_ID()"
See also this forum for more detail on the methods available.
http://forums.phpfreaks.com/topic/188084-get-last-mysql-id-using-zend-frameworks/
In "plain" PHP, I usually use the mysql_ functions. The mysql_insert_id() function returns the key of the last row inserted. I'm not advocating this over using the Zend way, just giving context:
mysql_query("INSERT INTO ... query");
$id = mysql_insert_id();
Then reference that ID in writing other queries related to that inserted row.
This should give you the last insert id from the last query made.
$db->lastInsertId()
try this:
$query="SELECT id FROM test_results WHERE test_id=$testId";
$id=$db->query($query);
I assume this is what you're looking for, otherwise you can change the WHERE condition to whatever you need.
From the MySQL manual: "If you insert a record into a table that contains an AUTO_INCREMENT column, you can obtain the value stored into that column by calling the mysql_insert_id() function." This refers to the C function.
In the PHP manual, you are suggested to use the PDO function instead. http://php.net/manual/en/function.mysql-insert-id.php PDO::lastInsertId
And apparently, "The insert() method on Zend_Db_Table will return the value of the last insert id." http://osdir.com/ml/php.zend.framework.db/2007-04/msg00055.html
To get last two records from any table you can use the following query
SELECT * FROM aa WHERE ID IN(
(SELECT COUNT(*) FROM aa),
(SELECT COUNT(*) FROM aa)-1
)

MySQL/PHP - inserting an extra row on INSERT statement

I am working on a small PHP + MySQL application. I have run into an issue where one of my insert statements seems to cause MySQL to add an additional somewhat blank row after each insert. Here's my setup:
I have a function that does the insert:
function addFacCertification($facultyID,$month,$year,$completed,$certificatesent,$confirmationtodean,$comments)
{
//echo "$facultyID<br>$month<br>$year<br>$completed<br>$certificatesent<br>$confirmationtodean<br>$comments";
$today = getdate();
$month = $today["mon"];
$date = $today["mday"];
$year = $today["year"];
$curdate = "$year" ."-". "$month" . "-" . "$date";
$sql = mysql_query("INSERT INTO facultycertification (facultyID,cmonth, cyear, completed, certificatesent, confirmationtodean, comments, certifiedon)
VALUES ('$facultyID', '$month', '$year', '$completed', '$certificatesent', '$confirmationtodean','$comments', '$curdate')");
return $sql;
}
Function call:
$sqlresults = addFacCertification($_POST["facultyID"], $_POST["month"], $_POST["year"], $_POST["completed"], $_POST["csent"],
$_POST["ctodean"], $_POST["comments"]);
Problem is, every time this is run - I get an extra row in my table: (See second row below) Image is here:
Any ideas why? Here is the table structure:
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
facultyID INT NOT NULL,
cmonth INT NOT NULL,
cyear INT NOT NULL,
completed INT NOT NULL,
certificatesent INT NOT NULL,
confirmationtodean INT NOT NULL,
comments TEXT,
certifiedon DATE,
FOREIGN KEY (facultyID) REFERENCES faculty(id)
I would imagine that your code is somehow being executed twice. I'd suggest the following (in this order) to debug the issue:
Uncomment that echo inside the function and see if it echos out twice (i.e. you're calling the function twice)
If you're running this via a web request tail the web server log to see if the request is being made twice
Enable general logging or enable profiling on the MySQL server to see what SQL queries are actually run against the server
You could have something like a MySQL trigger on the db doing this if you didn't set it up yourself but I think this is unlikely.

Categories