Gorilla3D Primative Teachings

Fact #1: Joseph reads programming languages, who needs a novel!?
Search
Subscribe to Feed:

Gorilla Db - MySQLi Wrapper


Monday, April 7, 2008

Db has been used in a number of my projects, the main focus of this class is to simplify the overall process of prepared statements. As this was migrated into my work place need for docs and log functions was created.

Db is a connection manager, it will use the connection you first create throughout your application. You can continue to call Db:init() and as long as a connection has already been made, you can run queries. Best of all It has prepared statements thanks to Wrapping MySQLi. For documentation and download please visit Gorilla Labs

  1.  
  2. $db = Db::init('localhost', 'root', 'pass', 'clients');
  3.  
  4. //-- Prepared Statements
  5. $rows = $db->query('SELECT * FROM blog_entries WHERE pub_date < ?', array('2008-04-01'));
  6.  
  7. echo 'Number of result: ' . $db->count();
  8. echo '<br/>';
  9.  
  10. echo 'SQL executed: ' . $db->debug();
  11. echo '<br/>';
  12.  
  13. $rows = $db->fetchAll();
  14. /* Output:
  15.  * Number of result: 22
  16.  * SQL executed: SELECT * FROM blog_entries WHERE pub_date < '2008-04-01'
  17.  */
  18.  


0 comments

Zend_Pdf Extension: Gorilla_Pdf_Page & Gorilla_Pdf_Table


Friday, March 28, 2008



At work there is a growing need to move into pdf creation, since we generate all of our invoices via HTML. Some clients need precision on form creation. PDF offers that but Zend_Pdf lib is very limited. So I implemented text-wrapper and table class/functions to help guide me. Its far from done, but a good start to blog about it.

download Gorilla_Pdf file

  1.  
  2. $pdf = new Zend_Pdf();
  3. $page = new Gorilla_Pdf_Page(Zend_Pdf_Page::SIZE_LETTER);
  4. $font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_COURIER);
  5.  
  6. //-- Header
  7. $page->setFont($font, 24);
  8. $page->drawMultilineText(array('Purchase Order'), 390, 48);
  9.  
  10. $page->setFont($font, 10);
  11. $page->setLineWidth(0.5);
  12. $page->drawMultilineText(array('Szzzzice', '9zzzze', 'Szzzzzzzzzzzz26', 'Phone 8555-888-5 Fax 855-4-5554'), 33, 61);
  13.  
  14. $page->drawInfoBox('Date', array('2/29/2008'), 420, 61, 75, 45); // Header Text, Body Text, X, Y, Width, Height
  15. $page->drawInfoBox('PO #', array('000032'), 495, 61, 75, 45);
  16.  
  17. $page->drawInfoBox('Vendor', array('EMC', '3464 Blaire Dr.', 'San Deigo, CA 92081'), 33, 130, 248, 109);
  18. $page->drawInfoBox('Ship To', array('Billy Bob', '453 Wonker Rd.', 'San Deigo, CA 92081'), 320, 130, 248, 109);
  19.  
  20. //-- Draw inventory items
  21. $table = new Gorilla_Pdf_Table($page, 33, 300); // $pdf_page, start x, start y
  22.  
  23. //-- Output the table header
  24. $row = new Gorilla_Pdf_Table_Row();
  25. $col = new Gorilla_Pdf_Table_Column();
  26. $col->setWidth(26)->setText('Qty');
  27. $row->addColumn($col);
  28. $col = new Gorilla_Pdf_Table_Column();
  29. $col->setWidth(93)->setText('Item');
  30. $row->addColumn($col);
  31. $col = new Gorilla_Pdf_Table_Column();
  32. $col->setWidth(183)->setText('Description');
  33. $row->addColumn($col);
  34. $col = new Gorilla_Pdf_Table_Column();
  35. $col->setWidth(93)->setText('Customer');
  36. $row->addColumn($col);
  37. $col = new Gorilla_Pdf_Table_Column();
  38. $col->setWidth(49)->setText('Rate');
  39. $row->addColumn($col);
  40. $col = new Gorilla_Pdf_Table_Column();
  41. $col->setWidth(65)->setText('Amount');
  42. $row->addColumn($col);
  43. $table->addRow($row);
  44.  
  45. //-- Output the inventory
  46. foreach(range(0, 15) as $i) {
  47. $row = new Gorilla_Pdf_Table_Row();
  48. $col = new Gorilla_Pdf_Table_Column();
  49. $col->setWidth(26)->setText(strval($i)); // Qty
  50. $row->addColumn($col);
  51. $col = new Gorilla_Pdf_Table_Column();
  52. $col->setWidth(93)->setText('MAY-ULEX')->setAlignment('center'); // Inventory Code
  53. $row->addColumn($col);
  54. $col = new Gorilla_Pdf_Table_Column();
  55. $col->setWidth(183)->setText('Freedom Task Chair- with Standard Gel Armrests with Matching Textile Cover'); // Inventory Description
  56. $row->addColumn($col);
  57. $col = new Gorilla_Pdf_Table_Column();
  58. $col->setWidth(93)->setText('Billy Bob'); //-- Customer
  59. $row->addColumn($col);
  60. $col = new Gorilla_Pdf_Table_Column();
  61. $col->setWidth(49)->setText('64.00'); // -- Each Price
  62. $row->addColumn($col);
  63. $col = new Gorilla_Pdf_Table_Column();
  64. $col->setWidth(65)->setText(number_format(64 * $i, 2))->setAlignment('right');
  65. $row->addColumn($col);
  66. $table->addRow($row);
  67. }
  68.  
  69. //-- Output the table footer
  70. $row = new Gorilla_Pdf_Table_Row();
  71. $col = new Gorilla_Pdf_Table_Column();
  72. $col->setWidth(468)->setText('Total')->setAlignment('right');
  73. $row->addColumn($col);
  74. $col = new Gorilla_Pdf_Table_Column();
  75. $col->setWidth(65)->setText(number_format(64 * 16, 2))->setAlignment('right');
  76. $row->addColumn($col);
  77. $table->addRow($row);
  78.  
  79. //-- Render the table to the pages/s
  80. $pages = $table->render();
  81.  
  82. //-- If the table overflows onto a new page, they are created
  83. $pdf->pages[] = $page;
  84. foreach($pages as $page) {
  85. $pdf->pages[] = $page;
  86. }
  87.  
  88. $filename = rand().'.pdf';
  89. header('Content-type: application/pdf');
  90. header("Cache-Control: no-cache, must-revalidate");
  91. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  92. echo $pdf->render();
  93.  


3 comments

Html/Php Contact Form


Saturday, March 22, 2008

A 14 minute - 2 part intro to submiting forms via php to email.




Source code:
contactus.zip

HD Videos:
Part 1 - download
Part 2 - download

0 comments

Php Video: Finding out execution time


Sunday, December 23, 2007

An intro to basic profiling for your php scripts, using php's microtime(). This is the FIRST video encoded in both 1024x768 and 320x240, watch the 320x240 stream on youtube or download the thoera/mp4 edition.


Watch this screen casting at 1024x768:
-- Php Execution Time - Theora ~ 5 megabytes
-- Php Execution Time - Mp4 avi ~ 26 megabytes

Free Php Debugger:
http://www.xdebug.org/



0 comments

Faster & Smarter MySQL Random Row Selection


Wednesday, December 19, 2007

In this entry will be dealing the following dataset:
geoip.sql ~ 94k rows | 7.8 MB

Figure 1. Shows the typical random MySQL random row Selection. On my server I ran 1000 iterations coming to about 0.6 seconds average in response time. The script took over 10 mins to execute 1000 random rows. Thats is awful performance and mean that if your site has more then 1 queries per second your database would crawl to a halt.

Figure 1. ~ 0.6 seconds
  1. <?php
  2. //-- Mysql Database Config
  3. $db_host = 'localhost';
  4. $db_db = 'mysite';
  5. $db_user = 'root';
  6. $db_pass = '';
  7.  
  8. //-- Mysql Connection
  9. $db_link = mysql_connect($db_host, $db_user, $db_pass)
  10. or die('MySQL Connection Error:'.mysql_error());
  11. or die('MySQL Error: Cannot select table');
  12. //-- Fetch a random row
  13. $sql = "SELECT * FROM `csv` ORDER BY RAND() LIMIT 1";
  14. $result = mysql_query($sql) or die(mysql_error());
  15. $row = mysql_fetch_assoc($result);
  16. ?>


Figure 2. Shows an alternative method yields 1000 iterations coming to about 0.001 seconds average in response time. Meaning your database can now withstand 1000 queries per second.

Figure 2. ~ 0.001 seconds
  1. <?php
  2. //-- Mysql Database Config
  3. $db_host = 'localhost';
  4. $db_db = 'mysite';
  5. $db_user = 'root';
  6. $db_pass = '';
  7.  
  8. //-- Mysql Connection
  9. $db_link = mysql_connect($db_host, $db_user, $db_pass)
  10. or die('MySQL Connection Error:'.mysql_error());
  11. or die('MySQL Error: Cannot select table');
  12.  
  13. //-- Find the largest ID
  14. $sql = "SELECT * FROM `csv` ORDER BY `id` DESC LIMIT 1";
  15. $result = mysql_query($sql) or die(mysql_error());
  16. $row = mysql_fetch_assoc($result);
  17. //-- Fetch a random row
  18. $max = intval($row['id']);
  19. $sql = "SELECT * FROM `csv` WHERE `id` = ". rand(1, $max) ." LIMIT 1";
  20. $result = mysql_query($sql);
  21. $row = mysql_fetch_assoc($result);
  22. ?>


Now what if your database has large section of missing ids (They skip in range, i.e 1, 3, 7)? Well look at Figure 3. This is an example of just looping the random selection based on the same code as Figure 2. The performance on this will very as it could be the 1st result that yields a row or the 100th, none of the less it still a far better alternative result then using MySQL's built in RAND() function to fetch random rows.

Figure 3. ~ N/A
  1. <?php
  2. // Mysql Database Config
  3. $db_host = 'localhost';
  4. $db_db = 'mysite';
  5. $db_user = 'root';
  6. $db_pass = '';
  7.  
  8. // Mysql Connection
  9. $db_link = mysql_connect($db_host, $db_user, $db_pass)
  10. or die('MySQL Connection Error:'.mysql_error());
  11. or die('MySQL Error: Cannot select table');
  12.  
  13. //-- Find the largest ID
  14. $sql = "SELECT * FROM `csv` ORDER BY `id` DESC LIMIT 1";
  15. $result = mysql_query($sql) or die(mysql_error());
  16. $row = mysql_fetch_assoc($result);
  17. $max = intval($row['id']);
  18. $result = false;
  19. //-- Query a random row until we get a result
  20. while(!$result) {
  21. $sql = "SELECT * FROM `csv` WHERE `id` = ". rand(1, $max) ." LIMIT 1";
  22. $result = mysql_query($sql) or die(mysql_error());
  23. }
  24. $row = mysql_fetch_assoc($result);
  25. ?>


Now if your looking for a pure Mysql method use a subquery, this will allow you to use Mysql to still generate random ids. If you look at Figure 4. the subquery is which just totals the number of rows within our database. Then the table's id is matched against php's random function lcg_value() which only generates 0 - 1 numbers, to fix that we just multiply that against our subquery's 'total'. So in the end what did 1000 iterations prove? Well I got 0.0005 seconds average per query, as you can see even faster then in Figure 2.

Firgure 4. ~ 0.0005 seconds by Joe
  1. <?php
  2. // Mysql Database Config
  3. $db_host = 'localhost';
  4. $db_db = 'mysite';
  5. $db_user = 'root';
  6. $db_pass = '';
  7.  
  8. // Mysql Connection
  9. $db_link = mysql_connect($db_host, $db_user, $db_pass)
  10. or die('MySQL Connection Error:'.mysql_error());
  11. or die('MySQL Error: Cannot select table');
  12. $sql = "SELECT * FROM csv WHERE id = ROUND(".lcg_value()." * (SELECT COUNT(*) FROM csv)) LIMIT 1";
  13. $result = mysql_query($sql) or die(mysql_error());
  14. $row = mysql_fetch_assoc($result);
  15. ?>


So when do you use RAND()?


For a single selection RAND() is just slow but when you need to use WHERE to filter your random selections as well as selection MANY random rows, RAND is your best best. Figure 5. & Figure 6. prove that point RAND() is just what to use when you need to filter your results. Now if you have a table that does not change very often and you are using the same filter over and over, Figure 6. would be your best best, this allows you to reuse the temp table to query rand rows much faster.

Figure 5. - Rand() ~ 0.65 seconds
  1. //-- Mysql Database Config
  2. $db_host = 'localhost';
  3. $db_db = 'mysite';
  4. $db_user = 'root';
  5. $db_pass = '';
  6. //-- Mysql Connection
  7. $db_link = mysql_connect($db_host, $db_user, $db_pass)
  8. or die('MySQL Connection Error:'.mysql_error());
  9. or die('MySQL Error: Cannot select table');
  10. //-- FINALLY query for our random rows w00t
  11. $sql = "SELECT * FROM csv WHERE cn = 'Germany' ORDER BY RAND() LIMIT 50";
  12. $result = mysql_query($sql) or die(mysql_error().'<br>'.$sql);
  13. while($row = mysql_fetch_assoc($result)) {
  14. $row;
  15. }


Figure 6. - Temp Table ~ 1.1 seconds / ~ 0.01 seconds
  1. //-- Mysql Database Config
  2. $db_host = 'localhost';
  3. $db_db = 'mysite';
  4. $db_user = 'root';
  5. $db_pass = '';
  6. //-- Mysql Connection
  7. $db_link = mysql_connect($db_host, $db_user, $db_pass)
  8. or die('MySQL Connection Error:'.mysql_error());
  9. or die('MySQL Error: Cannot select table');
  10.  
  11. //-- Create a temp table, with our WHERE filters
  12. $sql = "CREATE TEMPORARY TABLE IF NOT EXISTS csvTemp (
  13. temp_id INT(10) unsigned NOT NULL auto_increment,
  14. PRIMARY KEY (temp_id)
  15. )
  16. SELECT * FROM csv
  17. WHERE cn = 'Germany'";
  18. mysql_query($sql) or die(mysql_error().'<br>'.$sql);
  19.  
  20. //-- Fetch the total row count (we cant join/subquery the same temp table)
  21. $sql = "SELECT COUNT(*) AS total FROM csvTemp";
  22. $result = mysql_query($sql) or die(mysql_error().'<br>'.$sql);
  23. $row = mysql_fetch_assoc($result);
  24. $total = intval($row['total']);
  25.  
  26. //-- Generate our random temp_ids
  27. $rands = array();
  28. foreach(range(1, 50) as $n) { // Select 50 random ids
  29. $rands[] = intval(lcg_value() * $total);
  30. }
  31.  
  32. //-- FINALLY query for our random rows w00t
  33. $sql = "SELECT * FROM csvTemp WHERE temp_id IN (".implode(', ', $rands).")";
  34. $result = mysql_query($sql) or die(mysql_error().'<br>'.$sql);
  35. while($row = mysql_fetch_assoc($result)) {
  36. $row;
  37. }




If you know better methods, please by all means leave a comment and share your code. You can use syntax highlighting as above by encasing your code in BBcode style tags. i.e

10 comments