MySQL engines, InnoDb versus MyISAM for web developers February 23, 2010
Posted by chris in : SQL, php , add a commentLet me start out by saying I think MyISAM sucks. I hate it. It’s the default MySQL database engine, but its non-relational so a lot of people just start using it without exploring the other options. Hey thats okay, I did the same thing until some smart guys over at my last job introduced be to InnoDb. MyISAM is probably the best way to go for newer web developers just trying to cut their teeth on web application development. At some point its time to a pick up a book and learn how InnoDb can save you time, save you headaches, reduce the amount of code you write, and make the world a better place (okay that last one is a reach).
The best part about InnoDB is that its relational. Its transaction-safe too, but I’ll just focus on the relation side of things for now. What is a relation? A relation joins two tables together on a common value. Typically this is a parent-child relationship known as a one-to-many, but it can be a one-to-one relation too. Lets look at three tables.
tbl_profile
—————
profile_id
profile_name
tbl_profile_setting
———————–
profile_setting_id
profile_setting_name
tbl_profile_has_setting
—————————
profile_id
profile_setting_id
We have a profile table for storing whatever, then a profile can have settings. It doesn’t really matter what these settings are for the purpose of this article, but a profile can have multiple of these settings. You could have this same structure in MyISAM, but you would have to store the relations in your code. Your code is prone to errors. It happens, in fact is happens enough that I try to write as little code as possible. My goal is to leverage as much pre-written code as possible, because its been reviewed by more people and if I’m using that code I likely trust the source. InnoDB is an awesome example of this. Its widely deployed and written by people with more skills than me. No inferiority-complex here, thanks InnoDB.
For creating a relation. We’ll use phpMyAdmin. MySQL Administrator works great too and if your nutty enough you can look up the SQL for doing it in the mysql command line console. Go into the tbl_profile_has_setting table. In the structure tab you will see a link called Relation View. Click on this. You’ll notice a drop down next profile_id and profile_setting_id (these will only appear if you made these primary keys). You’ll need to create indexes on these two columns in the tbl_profile_has_setting table as well. Select the tbl_profile.profile_id and tbl_profile_setting.profile_setting_id for their respective columns. For the On Delete drop down select cascade.
What you’ve just done is create relations that have the following rules enforced by the database engine.
- When you delete a profile, its corresponding record(s) in tbl_profile_has_settings is deleted automajically
- When you delete a profile setting, its corresponding record(s) in tbl_profile_has_settings is deleted automajically
- When you add a record to tbl_profile_has_setting the profile_id and profile_setting_id must exist in their respective tables
Guess what, you don’t have to verify that the setting exists anymore when inserting into tbl_profile_has_setting and you don’t even need to worry about the profile existing. MySQL will return an error if these rules are violated. You now have referential integrity, clean data, and happy reports. You made all this possible just by creating the relation. So what did the cascade option do? That created rule 1 and 2 above. The auto-delete. Cascade should be used wisely as it can have devastating consequences (you records are automatically deleted), but when you implement a cascade this is normally what you want.
So why doesn’t everyone use InnoDb over MyISAM. There are several reasons:
- You need to be more knowledgeable to use it. This isn’t just throw data in grab it out anymore. It takes more thought and for bigger projects you’ll want to create ER diagrams to flowchart out your database.
- Performance penalty. Since you’ve offloaded the work to the database engine your database now runs slower. I scoff when people use this as an argument against InnoDb. If your application has gotten to be so successful that InnoDb is the sole reason of your slow down then congratulations, not many people are as successful as you. Plus InnoDb operates in a lower level language that is faster than the PHP code you are writing. Also most of your slowdowns in PHP web applications can be attributed to poorly written queries, bad database design to begin with, and lack of innovation to come up with solutions to improve speed.
- Harded to backup. Yes you can still use the mysqldump to backup your data, but you can’t copy the actaul database file like you could with MyIsam. This is a crappy form of database backup anyways. If you’re big enough to wear the mysqldump is no longer a sane method of doing backups then just stop being cheap and go buy the enterprise software to manage your data. Your data is important to you right?
Hope this helps some people and I hope it offends some people as well. This is one of those things that I cannot find common ground on, its debated often between me and co-workers. On a side note, don’t let your domain expire while on vacation. You’ll lose your SERPs fast.
How To Write a Page Controller in PHP for Dynamic Content February 6, 2010
Posted by chris in : php, seo , add a commentThis how to will cover the topic of creating a dynamic content system. It’s a well known fact that when you come across a site like wikipedia that they don’t have an html file for each article. That would be insanity. It would be nearly impossible to display the file tree in an IDE and cumbersome to search through even with an OS that has a slick file system and powerful shell like Linux. Trust me, I worked on a site that created a unique page for each product on their site (they’ve since gotten with the times). So how can web browsers access a page like http://en.wikipedia.org/wiki/Mike_Tyson, when that file doesn’t exist. The application uses a combination of server-side code, database storage, and apache htaccess magic. Here’s how to do this.
Apache HTACCESS
This is the most important part of redirecting dynamic content. The .htaccess file is what makes the magic happen. What happens is a user requests http://en.wikipedia.org/wiki/Mike_Tyson, apache goes to process the request and does its thing. Normally apache would redirect this to a 404 error page because the file does not exist, but if it see’s the .htaccess file in the directory, then apache will follow the rules we defined in the htaccess. Our rule will tell apache that if the file is not found, to go to some other file. We will call this file mycontroller.php (because its the controller in our ModelViewController). Below is some example code to get your started:
Options -Indexes
Options +FollowSymLinks
DirectoryIndex index.php
ErrorDocument 404 /404.php
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ mycontroller.php [L,QSA]
</IfModule>
Recap:
1. We have /public_html/mydomain.com/wiki/.htaccess
This overwrites the Apache Web Servers default operating procedures.
2. We redirect the request to /public_html/mydomain.com/wiki/mycontroller.php
This contains the server side code that will handle our request for the Mike Tyson article.
The Database
Going in detail on this topic is beyond the scope of this article, but you’ll need some sort of database management system to store your article on Mike Tyson and the thousands of other articles. Of course there are other options like an XML file, but a database such as MySQL is the sanest approach for most sites.
Server Side Code
You’ll need some sort of server-side code running whether is ASP, JSP, or PHP. I’m a bit partial to PHP so lets roll with that. In mycontroller.php your code might look something like this:
$uriArr = explode('/',$_SERVER['REQUEST_URI']);
$article = $uriArr[2];
$article = urldecode($page); // in this case the article equates to Mike_Tyson
$sql = "SELECT * FROM article WHERE name = '$article'";
$result = mysql_query($sql);
if(mysql_num_rows($result) == 1){
$page = mysql_fetch_assoc($result);
header('HTTP/1.1 200 OK');
header('Connection: close');
include_once 'mytemplatepage.php';
DIE():
}
else{
header('HTTP/1.1 404 Not Found');
header('location: /404.php');
header('Connection: close');
DIE();
}
This is asking our database for any records it has on the request Mike_Tyson. If a row is returned than we know we’ve found our article. We tell the browser that this is a 200 OK request. Then we include a file called mytemplate.php (this file is never actually seen by the browser). We set the record in the database to a variable array called $page. Our mytemplate.php file will look for this variable and begin populating the article. Lets see $page contains the following data: Title, Body, Image, and References. The mytemplate.php file might look something like this:
$title = $page['title ']; $body = $page['body ']; $image = $page['image ']; $references = $page['references ']; echo "<html><head><title>$title</title></head><body>"; echo "<h1>$title</h1>"; echo "<div class="mainImage">$image</div>"; echo "<p>$body</p>"; echo "<p>$references</p>"; echo "</body></html>";
Sweet! We can use the same template for a bunch of different articles, without having to create multiple files. Now if the user had searched for the following url: http://en.wikipedia.org/wiki/Mike_TysonIsEvil, we wouldn’t have an article on that. So instead the code would tell the browser this is a 404 Error and route the browser to the 404.php page.
This is an over simplified version of a dynamic content system, but it would work. If I was developing one of these on a professional level it would be complete with objects to handle requests, string cleaners to protect against SQL injection and XSS attacks, error logging, and the works! Let me know if you have questions I can answer and thanks for reading.
adventures in linux printing, set default printer and firefox command line print July 23, 2009
Posted by chris in : linux, php , 2commentsWe are in the process of redesigning our packing slips that get sent out to customers with each order. The previous developer went with a solution, html2ps, that has shotty support for CSS and design principals in general. The designer and I decided we needed something else. After trying numerous solutions, a co-worker suggested I give FireFox command line print a try.
using the geonames web service with php April 14, 2009
Posted by chris in : php , 2commentsThe GeoNames web service API, http://www.geonames.org/export/web-services.html, can be used to retrieve information on foreign countries such as postal code, city name, country code, longitude, and latitude. This information can come in very handy in variety of circumstances. I used the information obtained from the API to automate updating a table of countries with the postal code (just needed one in this instance) of every capital in the world.
First you will need to use cURL. I have written a simple cURL class:
/**
* Curl: psuedo implements cUrl for posting data to td ameritrade api
* @author cnizz.com
* @param void
* @uses *cUrl
*/
class Curl
{
/**
* constructor
* @author cn
* @param url(str),paramArr(array),$jsession_id(str)
*/
function __construct(){
}
/**
* post: posts parameters to url
* @author cnizz.com
* @param url(str), paramArr(array), returnString((bool - forces return as string)
* @return array(default)
*/
public function post($url,$paramArr=array(),$returnsString=0,$url_encode=0)
{
$string = $this->returnPostParamStr($paramArr);
if($url_encode==1){
$string=urlencode($string)."\n\n";
}
$ch = curl_init(); /// initialize a cURL session
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $string);
curl_setopt($ch, CURLOPT_TIMEOUT, '60');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$cUrlResponse = curl_exec($ch);
$httpResponseArr = curl_getinfo($ch);
curl_close($ch);
$return = $this->xml2array($cUrlResponse);
if(!is_array($return) || $return['result']=='FAIL' || $httpResponseArr['http_code']!=200)
{
$return['custome_error'] = $cUrlResponse;
$return['custom_http_code'] = $httpResponseArr['http_code'];
}
return $return;
}
/**
* returnPostParamStr: accepts an array and returns a parameter string
* @author cnizz.com
* @param array (key is post name, value is post attribute)
* @return string
*/
public function returnPostParamStr($val)
{
$string='';
if(is_array($val))
{
foreach($val as $k => $i)
{
if($j==0){
$string.="$k=$i";
$j=1;
}
else if($k=='|S'){
$string.="$k=$i";
}
else{
$string.="&$k=$i";
}
}
}
return $string;
}
/**
* xml2array: converts xml to an array
* @author unknown, modified by cn
* @link http://us.php.net/manual/en/function.xml-parse.php#87920
* @param xmlStr(string)
* @return array
*/
public function xml2array($xmlStr, $get_attributes = 1, $priority = 'tag')
{
// I renamed $url to $xmlStr, $url was the first parameter in the method if you
// want to load from a URL then rename $xmlStr to $url everywhere in this method
$contents = "";
if (!function_exists('xml_parser_create'))
{
return array ();
}
$parser = xml_parser_create('');
// commented out since I already have the xml text stored in memory
// this reads XML in from a URL
/*
if (!($fp = @ fopen($url, 'rb')))
{
return array ();
}
while (!feof($fp))
{
$contents .= fread($fp, 8192);
}
fclose($fp);
*/
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, trim($xmlStr), $xml_values);
xml_parser_free($parser);
if (!$xml_values)
return; //Hmm...
$xml_array = array ();
$parents = array ();
$opened_tags = array ();
$arr = array ();
$current = & $xml_array;
$repeated_tag_index = array ();
foreach ($xml_values as $data)
{
unset ($attributes, $value);
extract($data);
$result = array ();
$attributes_data = array ();
if (isset ($value))
{
if ($priority == 'tag')
$result = $value;
else
$result['value'] = $value;
}
if (isset ($attributes) and $get_attributes)
{
foreach ($attributes as $attr => $val)
{
if ($priority == 'tag')
$attributes_data[$attr] = $val;
else
$result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
}
}
if ($type == "open")
{
$parent[$level -1] = & $current;
if (!is_array($current) or (!in_array($tag, array_keys($current))))
{
$current[$tag] = $result;
if ($attributes_data)
$current[$tag . '_attr'] = $attributes_data;
$repeated_tag_index[$tag . '_' . $level] = 1;
$current = & $current[$tag];
}
else
{
if (isset ($current[$tag][0]))
{
$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
$repeated_tag_index[$tag . '_' . $level]++;
}
else
{
$current[$tag] = array (
$current[$tag],
$result
);
$repeated_tag_index[$tag . '_' . $level] = 2;
if (isset ($current[$tag . '_attr']))
{
$current[$tag]['0_attr'] = $current[$tag . '_attr'];
unset ($current[$tag . '_attr']);
}
}
$last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
$current = & $current[$tag][$last_item_index];
}
}
elseif ($type == "complete")
{
if (!isset ($current[$tag]))
{
$current[$tag] = $result;
$repeated_tag_index[$tag . '_' . $level] = 1;
if ($priority == 'tag' and $attributes_data)
$current[$tag . '_attr'] = $attributes_data;
}
else
{
if (isset ($current[$tag][0]) and is_array($current[$tag]))
{
$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
if ($priority == 'tag' and $get_attributes and $attributes_data)
{
$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
}
$repeated_tag_index[$tag . '_' . $level]++;
}
else
{
$current[$tag] = array (
$current[$tag],
$result
);
$repeated_tag_index[$tag . '_' . $level] = 1;
if ($priority == 'tag' and $get_attributes)
{
if (isset ($current[$tag . '_attr']))
{
$current[$tag]['0_attr'] = $current[$tag . '_attr'];
unset ($current[$tag . '_attr']);
}
if ($attributes_data)
{
$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
}
}
$repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
}
}
}
elseif ($type == 'close')
{
$current = & $parent[$level -1];
}
}
return ($xml_array);
}
}
Using the web service
include_once 'Curl.class.php';
$curl = new Curl();
$array = $curl->post('http://ws.geonames.org/postalCodeSearch?',array('placename'=>'Berlin'));
print_r($array);
using php debug_print_backtrace for debugging code March 4, 2009
Posted by chris in : php , add a commentThis is a built-in PHP function that I can’t believe I didn’t learn about until just a few weeks ago. One of the developers at work was debugging an application that had a lot of includes and he called debug_print_backtrace(). It dumps out a nice array showing which files called a function, and what line number it occurs on.
See http://us2.php.net/debug_print_backtrace for more information.
using firephp to debug php web applications February 3, 2009
Posted by chris in : php , add a commentFirePHP enables you to log to your Firebug Console using a simple PHP method call. All data is sent via response headers and will not interfere with the content on your page. FirePHP is ideally suited for AJAX development where clean JSON and XML responses are required. Using FirePHP on a production server is a safe and easy way to debug an application without inconveniencing end-users. FirePHP requires PHP 5 on the server, firebug on the client with all three options settings including Net enabled for the site. It can be installed via PEAR or by uploading two classes to your server and referencing them via the include_once() method.
Once the files are uploaded to the server, include them in your script, instantiate the FirePHP class as an object, and call the log() method by passing in two parameters the variable and a title.
include_once('FirePHPCore/FirePHP.class.php');
$firephp = new FirePHP();
$firephp->log($variable,'Enter an optional title for the second parameter');
When you pass an array as a variable to firebug it will display it in a human readable format similar to placing print_r() in between the pre html tags. The most notable security risk to using FirePHP is that anyone with the firephp extension enabled can you use it to see any information you are dumping to the client. My advice is to immediately comment out firebug logging calls once you are finished debugging the application, especially if you are dumping out raw SQL syntax to the client.
Decoding eval gzinflate base64_decode January 20, 2009
Posted by chris in : php , 1 comment so farI recently downloaded a wordpress theme for one of my sites which has a very solid Google page rank of 4, with hundreds of inbound links, and ranks in the top page for a lot of nice search terms. Unfortunately the blog author encrypted some php code that was then executed through eval(), these links dillute the value of my domain, and make it tough for me to sell links on the page. I found the code at the bottom of this article helpful in decoding the following:
eval(gzinflate(str_rot13(base64_decode('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'))));
Here it is:
echo "\nDECODE nested eval(gzinflate()) from Taree Internet\n\n"; echo "1. Reading coded.txt\n"; $fp1 = fopen ('coded.txt', "r"); $contents = fread ($fp1, filesize ('coded.txt')); fclose($fp1); echo "2. Decoding\n"; while (preg_match("/eval\(gzinflate/",$contents)) { $contents=preg_replace("/<\?|\?>/", "", $contents); eval(preg_replace("/eval/", "\$contents=", $contents)); } echo "3. Writing decoded.txt\n"; $fp2 = fopen("decoded.txt","w"); fwrite($fp2, trim($contents)); fclose($fp2);
simple php data encryption cipher class November 28, 2008
Posted by chris in : php , add a commentI am writing a pretty awesome web application and needed a way of encrypting data. So I wrote a quick class using PHPs mcrypt functions. It uses the super secure Rijndael 256 bit American Encryption Standard (AES).
Here is the class:
class Cipher
{
private $key,$iv_size,$iv;
function __construct($key)
{
$this->iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$this->iv = mcrypt_create_iv($this->iv_size, MCRYPT_RAND);
$this->key=trim($key);
}
public function encrypt($string)
{
$string=trim($string);
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->key, $string, MCRYPT_MODE_ECB, $this->iv));
}
public function decrypt($string)
{
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256,$this->key,base64_decode($string),MCRYPT_MODE_ECB,$this->iv));
}
}
capturing and storing echo or include data into a php variable November 11, 2008
Posted by chris in : php , add a commentHave you ever included a file into your php web application or used a function that executes an echo rather than a return? Have you ever wanted to capture the data returned into a variable instead? Well here’s how:
ob_start(); // always start with this the_title(); // this function does an echo $title = ob_get_contents(); // this grabs the echo and stores the data as $title ob_end_clean(); // always end with this
This will store the data echoed from the_title() as $title. For more information take a look at PHP.net’s entry on ob_start.
posting to and searching twitter with the twitter api and php November 4, 2008
Posted by chris in : php , add a commentI asked a co-worker today if he ever used twitter. His response was “No, I have friends.” The feeling was mutual, however twitter seems very popular and its been a while since I’ve played around with an API. So I created a twitter account, and then began looking through the API documentation. I was happy to see they had support for JSON.