K-FEZ
Because you care about what I think
Because you care about what I think
Aug 26th
Recently I completed a project in which I had to build an add-on for a marketing database application. The add-on needed to upload a spreadsheet (I decided to use CSV as it is the easiest to work with), find all duplicates (in both the database and the spreadsheet itself) and then insert all unique entries into the database. So, I stripped out all sensitive information and created these generic scripts to show you how to do it too.
There are two version of the script. The first version is simple, it uploads the CSV file and then imports it to the database. The other version displays analyzes the data from the file first and shows the user which entries are unique and which are duplicates, the user has to confirm this in order to import the data.
First we need to get the file from the user. In this case we will request the file through a simple HTML form, such as the one below.
<form enctype="multipart/form-data" action="importCSV.php" method="POST"> <p>Choose a file to upload : <input name="file" type="file" /></p> <p><input type="submit" value="Upload File" /></p> </form>
The file will be uploaded via the form and past to the importCSV.php script. Now, we want to verify that the file being passed to the server is a CSV file. If we don’t verify the file type, then the server might accept a file from a user with malicious intentions.
if($_FILES['file']['type'] != "application/vnd.ms-excel"){
die("This is not a CSV file.");
}
elseif(is_uploaded_file($_FILES['file']['tmp_name'])){
//Process 'file'
}
else{
die("You shouldn't be here");
}
The first if statement checks to see that the file is a CSV file. If it is not a CSV file, the process dies and reports an error. The elseif statement then checks that the file was uploaded via HTTP POST, if so the file will be processed. If the file was not uploaded via HTTP POST, then you will want to kill the process as you don’t know where the file came from.
NOTE: The name of the file input from the form is the same name as the $_FILES[''] variable.
Now that the file has been uploaded and verified we want to import it into the database. First, we need to connect to the database, then we need to get the information from the file and finally create an INSERT statement for each line of the CSV file.
//Connect to the database
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = 'password';
$dbname = 'petstore';
$link = mysql_connect($dbhost, $dbuser, $dbpass) or die('Error connecting to mysql server');
mysql_select_db($dbname);
//Process CSV file
$handle = fopen($_FILES['file']['tmp_name'], "r");
$data = fgetcsv($handle, 1000, ";"); //Remove if CSV file does not have column headings
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$att0 = mysql_real_escape_string($data[0]);
$att1 = mysql_real_escape_string($data[1]);
$att2 = mysql_real_escape_string($data[2]);
$att3 = mysql_real_escape_string($data[3]);
$sql = "INSERT INTO `tbl_name` (
`attribute0` ,
`attribute1` ,
`attribute2` ,
`attribute3`
)
VALUES ('" . $att0 . "', '" . $att1 . "', '" . $att2 . "', '" . $att3 . "')";
mysql_query($sql);
}
NOTE: You may need to change fgetcsv() parameters if you have a CSV file with lines longer than 1000 characters or if the value delimiter is not a semicolon.
NOTE: the first time fgetcsv() is called, the data is not used. This is because the first line of the file is the column headings. If your CSV file does not have column headings you should remove this line.
NOTE: The CSV file must be formatted identically every time in order for the script to be reusable.
Now to put the whole script together.
if($_FILES["file"]["type"] != "application/vnd.ms-excel"){
die("This is not a CSV file.");
}
elseif(is_uploaded_file($_FILES['file']['tmp_name'])){
//Connect to the database
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = 'password';
$dbname = 'petstore';
$link = mysql_connect($dbhost, $dbuser, $dbpass) or die('Error connecting to mysql server');
mysql_select_db($dbname);
//Process the CSV file
$handle = fopen($_FILES['file']['tmp_name'], "r");
$data = fgetcsv($handle, 1000, ";"); //Remove if CSV file does not have column headings
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$att0 = mysql_real_escape_string($data[0]);
$att1 = mysql_real_escape_string($data[1]);
$att2 = mysql_real_escape_string($data[2]);
$att3 = mysql_real_escape_string($data[3]);
$sql = "INSERT INTO `tbl_name` (
`attribute0` ,
`attribute1` ,
`attribute2` ,
`attribute3`
)
VALUES ('" . $att0 . "', '" . $att1 . "', '" . $att2 . "', '" . $att3 . "')";
mysql_query($sql);
}
mysql_close($link);
echo "CSV file successfully imported.";
}
else{
die("You shouldn't be here");
}
This simple upload script is also available for download here.
Most of the time we will need to first analyze the imported data in order to find duplicates or errors in the data. In order to do this we will have to first check each row, then report back to the user on all rows (indicating which rows have errors and which are good), then after user confirmation we will have to import the data.
First, I renamed the importCSV.php script to analyzeCSV.php. Then, I changed the file upload form’s action to analyzeCSV.php. Next, I removed the mysql_query() call and included a check to verify that the information is not already in the database. If the entry is unique, the insert statement is added to a session variable which holds all unique inserts. The script also adds each row of the CSV file to a table which indicates if the row is unique or not.
if($_FILES["file"]["type"] != "application/vnd.ms-excel"){
die("This is not a CSV file.");
}
elseif(is_uploaded_file($_FILES['file']['tmp_name'])){
session_start()
//Connect to the database
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = 'password';
$dbname = 'petstore';
$link = mysql_connect($dbhost, $dbuser, $dbpass) or die('Error connecting to mysql server');
mysql_select_db($dbname);
//Process the CSV file
$findings = "
<form method=\"post\" action=\"importCSV.php\">
<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">
<tr>
<td>Result</td>
<td>Attribute 0</td>
<td>Attribute 1</td>
<td>Attribute 2</td>
<td>Attribute 3</td>
</tr>";
$handle = fopen($_FILES['file']['tmp_name'], "r");
$data = fgetcsv($handle, 1000, ";"); //Remove if CSV file does not have column headings
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$att0 = mysql_real_escape_string($data[0]);
$att1 = mysql_real_escape_string($data[1]);
$att2 = mysql_real_escape_string($data[2]);
$att3 = mysql_real_escape_string($data[3]);
//Check if row is in database already
$sql = "SELECT *
FROM `tbl_name`
WHERE `attribute0` = '" . $att0 . "'"; //In this example attribute0 is the primary key
$result = mysql_query($sql);
$count = mysql_num_rows($result);
if($count > 0){
$findings = $findings . "
<tr>
<td bgcolor=\"#FF0000\">DB Duplicate</td>
<td>" . $att0 . "</td>
<td>" . $att1 . "</td>
<td>" . $att2 . "</td>
<td>" . $att3 . "</td>
</tr>";
}
//Row is unique
else{
//Add INSERT statement to INSERT queue
$_SESSION['insert'] = $_SESSION['insert'] . "INSERT INTO `tbl_name` (
`attribute0` ,
`attribute1` ,
`attribute2` ,
`attribute3`
)
VALUES ('" . $att0 . "', '" . $att1 . "', '" . $att2 . "', '" . $att3 . "');";
//Add row for row to findings table and mark unique
$findings = $findings . "
<tr>
<td bgcolor=\"#00FF00\"> </td>
<td>" . $att0 . "</td>
<td>" . $att1 . "</td>
<td>" . $att2 . "</td>
<td>" . $att3 . "</td>
</tr>";
}
}
mysql_close($link);
$findings = $findings . "
<tr>
<td colspan=\"5\"><div align=\"center\"><input type=\"submit\" value=\"Confirm\" /></div></td>
</tr>
</table>
</form>";
echo $findings;
}
else{
die("You shouldn't be here");
}
However, when I built my add-on I found that the CSV files being uploaded contained duplicates inside of the file, so we need to check that each row that isn’t already in the database isn’t in the queue to be added to the database.
//Check if row is already in INSERT queue
elseif(strpos($_SESSION['insert'], "'" . $att0 . "'") != false){
$findings = $findings . "
<tr>
<td bgcolor=\"#FF0000\">File Duplicate</td>
<td>" . $att0 . "</td>
<td>" . $att1 . "</td>
<td>" . $att2 . "</td>
<td>" . $att3 . "</td>
</tr>";
}
Now that all entries have been checked, and the findings have been reported back to the user. After user confirmation, the system must execute all the insert statements. This is done in a new script called importCSV.php which looks like this:
session_start();
//Make sure the insert query queue has been initialized
if(!isset($_SESSION['insert'])){
die("You shouldn't be here.");
}
//Connect to the database
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = 'password';
$dbname = 'petstore';
$link = mysql_connect($dbhost, $dbuser, $dbpass) or die('Error connecting to mysql server');
mysql_select_db($dbname);
$queries = explode(';', $_SESSION['insert']);
foreach($queries as $query){
if($query != ""){
mysql_query($query);
}
}
mysql_close($link);
echo "Done";
The session variable ‘insert’ is the insert statement queue. It is broken apart using explode() and the delimiter is a semicolon. Each query is then executed and the system reports when done.
NOTE: The importCSV.php (in both the simple case and the analyze case) does not do any sort of error handling if a query fails to execute.
You can download upload, analyze, import script files here.
That’s it, you are free to download and use these scripts however you like. Just remember to give credit where credit is due.
Once again here are the download links for the scripts:
Upload, Analyze, and Import CSV
If you have any questions, please submit them as comments on this page. This way other users can see your question and my answer.
Aug 19th
I’m a big supporter of the Android mobile platform, mainly because it is open source and unlike the iPhone, there is no application approval process. I’ve been slowly learning to develop for the platform by building my own game for the phone. Currently, I have a Droid Eris, which is one of the slowest Android phones you can have. Regardless of the speed of the phone, I still download a lot of apps and mess around with them. So I’ve compiled a list of 3 essential apps that no one with an Android phone should be without. These essential apps are not so much for fun, but rather they change the way you see and interact with your phone.
Although this keyboard is still in beta it trounces the built in Android keyboard. The keyboard doesn’t just look at what keys you might be trying to press, it also looks at the words you have written previously to predict what word you might want next. After using the keyboard for more than a month now, I barely have to type full words anymore, or even start a word, this is because SwiftKey learns how you type in order to predict the next word even better. The application even keeps track of how many keystrokes it has saved you.
You can download the SwiftKey keyboard for free from the market by scanning the QR code to the right or using one of the links below.
While the built in messaging service works great in Android, it lacks a few features and isn’t that visual appealing. ChompSMS offers a few extras that put it above and beyond other messaging clients on Android. First is the popup message window that shows you the text without having to actually enter the client, you can even reply to the text from here, or mark it unread for later. The interface resemebles that of the iPhone’s messaging service, with talk bubbles appearing from alternate sides of the screen. I’ve also noticed a performance increase since using this messaging service; I can load all my messages faster and it doesn’t lock up when I receive a phone call.
You can download ChompSMS for free from the market by scanning the QR code below or using one of the links below. There is also an ad-free version available for a small fee
This is without a doubt my favorite app. LauncherPro completely replaces your default user interface, in my case HTC Sense, with a sleek and fast new interface. You can customize the amount of home screens from 1-9 and create a home row that is at the bottom of every screen. The app includes nice sharp new icons for common tasks such as Gmail and your calendar. This is one app that I can’t even begin to describe fully, you just have to check out the video and try it out yourself.
You can use the QR code below to download this free interface. There is also a paid version that includes extra icons.
There are plenty of other great apps out there, but today I just felt like covering the essential apps. In the future I’ll share some great money management, exercise, news, and game apps (hopefully my own too) with you
Aug 17th
Did you hear? Google and Verizon are going to destroy the internet, and no one will ever again be able to read the news, check their email, blog, read Facebook, or…
The idea that my ISP might one day block me from looking at anything on the internet is ridiculous. Too many people are over reacting to the deal that Google and Verizon have put forth. No one is going to be blocking your precious porn sites or stopping you from pirating movies, except if you are on a mobile device. And that makes sense!
The “evil” corporate service providers have to shell out big bucks to set up towers and get better 3/4g coverage in your area. These towers don’t have unlimited bandwidth, in fact they are very limited compared to the fiber optic lines that are running through your neighborhood. Because of these limitations, the private companies that own the equipment have the right to decide how they are used. Just because we feel we are entitled to use their service however we want, doesn’t mean we are.
As for home services, the companies still have the right to control how their equipment is used. However, they should not be able to block any sort of content, only slow how it is accessed. Imagine this scenario; 40% of the people on your block are running some sort of P2P client all day (not an unreasonable assumption) and currently, these people are allowed to dedicate all of their bandwidth to the clients. So, now when 6:00PM rolls around and peak usage hours hit, your email is taking a while to load and the latest episode of Mad Men keeps pausing to buffer. It looks like your service is suffering because of the people on the block who are using all of their allotted bandwidth on an activity that has a 95% chance of being illegal. However, if those people were only allowed to use 25% of their bandwidth on P2P services, than no one on your block would have to suffer during peak hours.
Private service providers throttling speeds to different web services equates to
The real danger comes from the service providers not knowing when to stop swinging the ban hammer. However, thanks to a free market, there is competition and we, the consumers, have the right to switch providers as soon as we feel they have taken it too far.
Remember, with Verizon FiOS hitting near gigabit internet speeds, they are not trying to take the internet away, just make it more accessible and reliable for those not using it for illegal purposes.
Personally, I think too many people feel too entitled and that’s why people are opposed to to the Googlezon deal. However, there are some good arguments posed against the deal; such as the possibility of service providers blocking content from one political party.
In case you haven’t been on the internet lately, here’s a few links to fill you in on the story:
Aug 13th
Just thought I would highlight some great deals I got the other day.
First is Microsoft Office 2010 for $79.95, this package includes:
Check it out: http://www.microsoft.com/student/office/en-us/default.aspx
Also, you can get an upgrade to Windows 7 Professional Upgrade for only $30. I think you need at least Windows Vista Home Premium. The link to that deal is available here.
Aug 12th
I think I’ve found the framework for me. I’ve looked at various PHP frameworks before (CakePHP and Zend) but found them to be more confusing and slow down development time. However, I came across Symfony today and gave it a quick go. Simply put, this framework is awesome, here’s a few broad reasons why.
I was able to work my way through the Symfony tutorial in a matter of minutes. And, unlike my past experiences with PHP frameworks, the information from the tutorial is generic and can be applied to any application.
I’ve decided that I will use Symfony on an upcoming freelance project. The project involves user and admin sections to a site, as well as photo uploads and some e-commerce. To aid in this project I purchased a book entitled, “The Definitive Guide to Symfony.”
As I become more familiar with the software, I will post more specific details and any useful pieces of knowledge I encounter along the way.
Aug 11th
Well, this is my first blog post so I’ll keep it brief.
I’m not too sure what the focus of this blog will be, if any. But I will definitely be discussing my freelance work as a software and web developer, some photos and stories, and anything else I feel like blogging about. However, I will try and keep it informative for the most part.