Your SlideShare is downloading. ×
0
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP   2011-12-05
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Intro to #memtech PHP 2011-12-05

1,022

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,022
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. <ul>Intro to #memtech: PHP December 5, 2011 </ul><ul>Jeremy Kendall <li>http://about.me/jeremykendall </li></ul>
  • 2. Who is this guy? <ul>Jeremy Kendall PHP developer since about 2001 Organizer of Memphis PHP Zend Framework expert fanboi Speaker Photographer Sometime blogger Sometime open source contributor Not as smart as you </ul><ul>#memtech </ul>
  • 3. Following Along <ul>You can follow along with the presentation code at github.com. http://github.com/jeremykendall/bookshelf </ul>
  • 4. What is PHP? <ul><li>Scripting language
  • 5. Designed for the web
  • 6. Cross-platform
  • 7. Free (as in beer) </li></ul>
  • 8. Getting started <ul><li>Included in most Linux distributions
  • 9. Included in OS X
  • 10. Mac: MAMP, MacPorts, Homebrew . . .
  • 11. Windows: WampServer, xampp
  • 12. Google, follow instructions, and . . .
  • 13. . . . you can be coding in about 5 minutes </li></ul>
  • 14. Why Did You (or why do you want to) Start Programming?
  • 15. I Wanted to Solve Problems <ul><li>I usually caused more problems than I solved
  • 16. We'll solve a problem together
  • 17. Create a typical first web application
  • 18. Make horrible mistakes
  • 19. Correct those mistakes
  • 20. Make a cool improvement
  • 21. Learn something? </li></ul>
  • 22. What's the Problem? <ul><li>I want to create an application that stores and displays books from my bookshelf
  • 23. Requirements: </li><ul><li>Display books
  • 24. Add books
  • 25. Edit books
  • 26. Delete books </li></ul><li>Why no delete? I ran out of time and energy. </li></ul>
  • 27. So, What do we Need? <ul><li>Database (sqlite)
  • 28. View (index.php)
  • 29. Form (book-form.php)
  • 30. Form processor (process-form.php) </li></ul>
  • 31. index.php
  • 32. book-form.php
  • 33. Database Schema CREATE TABLE bookshelf ( id INTEGER PRIMARY KEY , title, author );
  • 34. index.php – db connection <?php $db = realpath ( dirname ( __FILE__ ) . '/data/db/bookshelf.db' ); $dsn = &quot;sqlite: $db &quot; ; $options = array ( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION , PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: FETCH_ASSOC ); try { $dbh = new PDO ( $dsn , null , null , $options ); } catch ( PDOException $e ) { echo &quot;Error!: &quot; . $e -> getMessage() . &quot;<br /> n &quot; ; die (); } $books = $dbh -> query( &quot; SELECT * FROM bookshelf ORDER BY title&quot; ) -> fetchAll();
  • 35. index.php – db connection <?php $db = realpath ( dirname ( __FILE__ ) . '/data/db/bookshelf.db' ); $dsn = &quot;sqlite: $db &quot; ; $options = array ( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION , PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: FETCH_ASSOC ); try { $dbh = new PDO ($dsn, null , null , $options); } catch ( PDOException $e) { echo &quot;Error!: &quot; . $e -> getMessage() . &quot;<br />n&quot;; die (); } $books = $dbh -> query(&quot; SELECT * FROM bookshelf ORDER BY title&quot;) -> fetchAll() ;
  • 36. index.php – db connection <?php $db = realpath ( dirname ( __FILE__ ) . '/data/db/bookshelf.db'); $dsn = &quot;sqlite:$db&quot;; $options = array ( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ); try { $dbh = new PDO ( $dsn , null , null , $options ); } catch ( PDOException $e ) { echo &quot;Error!: &quot; . $e -> getMessage() . &quot;<br /> n &quot; ; die (); } $books = $dbh -> query(&quot; SELECT * FROM bookshelf ORDER BY title&quot;) -> fetchAll();
  • 37. index.php – db connection <?php $db = realpath ( dirname ( __FILE__ ) . '/data/db/bookshelf.db'); $dsn = &quot;sqlite:$db&quot;; $options = array ( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ); try { $dbh = new PDO ($dsn, null , null , $options); } catch ( PDOException $e) { echo &quot;Error!: &quot; . $e -> getMessage() . &quot;<br />n&quot;; die (); } $books = $dbh -> query( &quot; SELECT * FROM bookshelf ORDER BY title&quot; ) -> fetchAll();
  • 38. index.php – books table <?php if ( count ( $books ) > 0 ): ?> < table > < tr > < th > Title </ th >< th > Author </ th > </ tr > <?php foreach ( $books as $book ): ?> < tr > < td > < a href= &quot;book-form.php?id=<?php echo $book ['id']; ?>&quot; > <?php echo $book [ 'title' ]; ?> </ a > </ td > < td > <?php echo $book [ 'author' ]; ?> </ td > </ tr > <?php endforeach ; ?> </ table > <?php else : ?> < p > We have no books! </ p > <?php endif ; ?>
  • 39. index.php – books table <?php if ( count ( $books ) > 0 ): ?> < table > < tr > < th > Title </ th >< th > Author </ th > </ tr > <?php foreach ( $books as $book ): ?> < tr > < td > < a href= &quot;book-form.php?id=<?php echo $book ['id']; ?>&quot; > <?php echo $book [ 'title' ]; ?> </ a > </ td > < td > <?php echo $book [ 'author' ]; ?> </ td > </ tr > <?php endforeach ; ?> </ table > <?php else : ?> < p >We have no books!</ p > <?php endif ; ?>
  • 40. index.php – books table <?php if ( count ($books) > 0): ?> < table > < tr > < th >Title</ th >< th >Author</ th > </ tr > <?php foreach ( $books as $book ): ?> < tr > < td > < a href= &quot;book-form.php?id=<?php echo $book ['id']; ?>&quot; > <?php echo $book [ 'title' ]; ?> </ a > </ td > < td > <?php echo $book [ 'author' ]; ?> </ td > </ tr > <?php endforeach ; ?> </ table > <?php else : ?> < p >We have no books!</ p > <?php endif ; ?>
  • 41. index.php – books table <?php if ( count ($books) > 0): ?> < table > < tr > < th >Title</ th >< th >Author</ th > </ tr > <?php foreach ($books as $book): ?> < tr > < td > < a href=&quot;book-form.php?id=<?php echo $book['id']; ?>&quot;> <?php echo $book['title']; ?> </ a > </ td > < td > <?php echo $book['author']; ?> </ td > </ tr > <?php endforeach ; ?> </ table > <?php else : ?> < p > We have no books! </ p > <?php endif ; ?>
  • 42. book-form.php <?php $id = empty ( $_GET [ 'id' ]) ? null : $_GET [ 'id' ]; if ( $id ) { // Database connection code $book = $dbh -> query( &quot; SELECT title, author FROM bookshelf WHERE id = $id &quot; ) -> fetch(); $title = $book [ 'title' ]; $author = $book [ 'author' ]; }
  • 43. book-form.php <?php $id = empty ( $_GET [ 'id' ]) ? null : $_GET [ 'id' ]; if ($id) { // Database connection code $book = $dbh -> query(&quot; SELECT title, author FROM bookshelf WHERE id = $id&quot;) -> fetch(); $title = $book['title']; $author = $book['author']; }
  • 44. book-form.php <?php $id = empty ($_GET['id']) ? null : $_GET['id']; if ( $id ) { // Database connection code $book = $dbh -> query( &quot; SELECT title, author FROM bookshelf WHERE id = $id &quot; ) -> fetch(); $title = $book [ 'title' ]; $author = $book [ 'author' ]; }
  • 45. book-form.php < form method= &quot;post&quot; action= &quot;process-book.php&quot; > < input type= &quot;hidden&quot; id= &quot;id&quot; name= &quot;id&quot; value= &quot;<?php echo $id ; ?>&quot; /> < dl > < dt > < label for= &quot;title&quot; > Title </ label > </ dt > < dd > < input type= &quot;text&quot; id= &quot;title&quot; name= &quot;title&quot; value= &quot;<?php echo $title ; ?>&quot; /> </ dd > < dt > < label for= &quot;author&quot; > Author </ label > </ dt > < dd > < input type= &quot;text&quot; id= &quot;author&quot; name= &quot;author&quot; value= &quot;<?php echo $author ; ?>&quot; /> </ dd > < dt > &nbsp; </ dt > < dd > < input type= &quot;submit&quot; value= &quot;Submit&quot; /> </ dd > </ dl > </ form >
  • 46. book-form.php < form method= &quot;post&quot; action= &quot;process-book.php&quot; > < input type=&quot;hidden&quot; id=&quot;id&quot; name=&quot;id&quot; value= &quot;<?php echo $id ; ?>&quot; /> < dl > < dt > < label for=&quot;title&quot;>Title</ label > </ dt > < dd > < input type=&quot;text&quot; id=&quot;title&quot; name=&quot;title&quot; value= &quot;<?php echo $title ; ?>&quot; /> </ dd > < dt > < label for=&quot;author&quot;>Author</ label > </ dt > < dd > < input type=&quot;text&quot; id=&quot;author&quot; name=&quot;author&quot; value= &quot;<?php echo $author ; ?>&quot; /> </ dd > < dt > &nbsp; </ dt > < dd > < input type=&quot;submit&quot; value=&quot;Submit&quot; /> </ dd > </ dl > </ form >
  • 47. process-book.php <?php if ( strtolower ( $_SERVER [ 'REQUEST_METHOD' ]) == 'get' ) { header ( &quot;Location: /&quot; ); } // Database connection code if ( empty ( $_POST [ 'id' ])) { $sql = &quot; INSERT INTO bookshelf (title, author) &quot; . &quot;VALUES ('{ $_POST ['title']}', '{ $_POST ['author']}')&quot; ; $dbh -> exec( $sql ); } else { $sql = &quot; UPDATE bookshelf SET title = '{ $_POST ['title']}', &quot; . &quot;author = '{ $_POST ['author']}' WHERE id = { $_POST ['id']}&quot; ; $dbh -> exec( $sql ); } header ( &quot;Location: /&quot; );
  • 48. process-book.php <?php if ( strtolower ( $_SERVER [ 'REQUEST_METHOD' ]) == 'get' ) { header ( &quot;Location: /&quot; ); } // Database connection code if ( empty ($_POST['id'])) { $sql = &quot; INSERT INTO bookshelf (title, author) &quot; . &quot;VALUES ('{$_POST['title']}', '{$_POST['author']}')&quot;; $dbh -> exec($sql); } else { $sql = &quot; UPDATE bookshelf SET title = '{$_POST['title']}', &quot; . &quot;author = '{$_POST['author']}' WHERE id = {$_POST['id']}&quot;; $dbh -> exec($sql); } header (&quot;Location: /&quot;);
  • 49. process-book.php <?php if ( strtolower ($_SERVER['REQUEST_METHOD']) == 'get') { header (&quot;Location: /&quot;); } // Database connection code if ( empty ($_POST['id'])) { $sql = &quot; INSERT INTO bookshelf (title, author) &quot; . &quot;VALUES ('{$_POST['title']}', '{$_POST['author']}')&quot;; $dbh -> exec($sql); } else { $sql = &quot; UPDATE bookshelf SET title = '{$_POST['title']}', &quot; . &quot;author = '{$_POST['author']}' WHERE id = {$_POST['id']}&quot;; $dbh -> exec($sql); } header (&quot;Location: /&quot;);
  • 50. process-book.php <?php if ( strtolower ($_SERVER['REQUEST_METHOD']) == 'get') { header (&quot;Location: /&quot;); } // Database connection code if ( empty ( $_POST [ 'id' ])) { $sql = &quot; INSERT INTO bookshelf (title, author) &quot; . &quot;VALUES ('{ $_POST ['title']}', '{ $_POST ['author']}')&quot; ; $dbh -> exec( $sql ); } else { $sql = &quot; UPDATE bookshelf SET title = '{$_POST['title']}', &quot; . &quot;author = '{$_POST['author']}' WHERE id = {$_POST['id']}&quot;; $dbh -> exec($sql); } header (&quot;Location: /&quot;);
  • 51. process-book.php <?php if ( strtolower ($_SERVER['REQUEST_METHOD']) == 'get') { header (&quot;Location: /&quot;); } // Database connection code if ( empty ($_POST['id'])) { $sql = &quot; INSERT INTO bookshelf (title, author) &quot; . &quot;VALUES ('{$_POST['title']}', '{$_POST['author']}')&quot;; $dbh -> exec($sql); } else { $sql = &quot; UPDATE bookshelf SET title = '{ $_POST ['title']}', &quot; . &quot;author = '{ $_POST ['author']}' WHERE id = { $_POST ['id']}&quot; ; $dbh -> exec( $sql ); } header (&quot;Location: /&quot;);
  • 52. process-book.php <?php if ( strtolower ($_SERVER['REQUEST_METHOD']) == 'get') { header (&quot;Location: /&quot;); } // Database connection code if ( empty ($_POST['id'])) { $sql = &quot; INSERT INTO bookshelf (title, author) &quot; . &quot;VALUES ('{$_POST['title']}', '{$_POST['author']}')&quot;; $dbh -> exec($sql); } else { $sql = &quot; UPDATE bookshelf SET title = '{$_POST['title']}', &quot; . &quot;author = '{$_POST['author']}' WHERE id = {$_POST['id']}&quot;; $dbh -> exec($sql); } header ( &quot;Location: /&quot; );
  • 53. Glaring Problems? <ul><li>Code duplication
  • 54. Input isn't filtered
  • 55. Output isn't escaped
  • 56. User-provided data used in SQL </li></ul>
  • 57. Code Duplication <ul><li>Violates DRY principle
  • 58. Maintenance nightmare
  • 59. The next developer will thank you </li></ul>
  • 60. Consolidate <ul>We'll throw all that duplicated code into library/base.php (and add a few other nice things). </ul>
  • 61. base.php <?php date_default_timezone_set ( 'America/Chicago' ); error_reporting ( - 1 ); ini_set ( 'display_errors' , 1 ); ini_set ( 'display_startup_errors' , 1 ); $db = realpath ( dirname ( __FILE__ ) . '/../data/db/bookshelf.db' ); $dsn = &quot;sqlite: $db &quot; ; $options = array ( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION , PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: FETCH_ASSOC ); try { $dbh = new PDO ( $dsn , null , null , $options ); } catch ( PDOException $e ) { throw $e ; echo &quot;Error!: &quot; . $e -> getMessage() . &quot;<br /> n &quot; ; die (); }
  • 62. base.php <?php date_default_timezone_set ( 'America/Chicago' ); error_reporting ( - 1); ini_set ('display_errors', 1); ini_set ('display_startup_errors', 1); $db = realpath ( dirname ( __FILE__ ) . '/../data/db/bookshelf.db'); $dsn = &quot;sqlite:$db&quot;; $options = array ( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ); try { $dbh = new PDO ($dsn, null , null , $options); } catch ( PDOException $e) { throw $e; echo &quot;Error!: &quot; . $e -> getMessage() . &quot;<br />n&quot;; die (); }
  • 63. base.php <?php date_default_timezone_set ('America/Chicago'); error_reporting ( - 1 ); ini_set ( 'display_errors' , 1 ); ini_set ( 'display_startup_errors' , 1 ); $db = realpath ( dirname ( __FILE__ ) . '/../data/db/bookshelf.db'); $dsn = &quot;sqlite:$db&quot;; $options = array ( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ); try { $dbh = new PDO ($dsn, null , null , $options); } catch ( PDOException $e) { throw $e; echo &quot;Error!: &quot; . $e -> getMessage() . &quot;<br />n&quot;; die (); }
  • 64. base.php <?php date_default_timezone_set ('America/Chicago'); error_reporting ( - 1); ini_set ('display_errors', 1); ini_set ('display_startup_errors', 1); $db = realpath ( dirname ( __FILE__ ) . '/../data/db/bookshelf.db' ); $dsn = &quot;sqlite: $db &quot; ; $options = array ( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION , PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: FETCH_ASSOC ); try { $dbh = new PDO ( $dsn , null , null , $options ); } catch ( PDOException $e ) { throw $e ; echo &quot;Error!: &quot; . $e -> getMessage() . &quot;<br /> n &quot; ; die (); }
  • 65. Replace db info with base.php <ul><li>Remove the db connection code from each file and add . . . </li></ul>require_once dirname ( __FILE__ ) . '/library/base.php' ; <ul><li>. . . at the top of each file. </li></ul>
  • 66. Duplication removed, but . . . <ul><li>Turning error reporting up to 11 reveals a problem in book-form.php </li></ul>
  • 67. Oops
  • 68. We echo $title and $author < form method=&quot;post&quot; action=&quot;process-book.php&quot;> < input type=&quot;hidden&quot; id=&quot;id&quot; name=&quot;id&quot; value=&quot;<?php echo $id; ?>&quot; /> < dl > < dt > < label for=&quot;title&quot;>Title</ label > </ dt > < dd > < input type=&quot;text&quot; id=&quot;title&quot; name=&quot;title&quot; value= &quot;<?php echo $title ; ?>&quot; /> </ dd > < dt > < label for=&quot;author&quot;>Author</ label > </ dt > < dd > < input type=&quot;text&quot; id=&quot;author&quot; name=&quot;author&quot; value= &quot;<?php echo $author ; ?>&quot; /> </ dd > < dt > &nbsp; </ dt > < dd > < input type=&quot;submit&quot; value=&quot;Submit&quot; /> </ dd > </ dl > </ form >
  • 69. Without defining $title and $author require_once dirname ( __FILE__ ) . '/library/base.php' ; $id = empty ( $_GET [ 'id' ]) ? null : $_GET [ 'id' ]; if ( $id ) { $book = $dbh -> query( . . . ) -> fetch(); $title = $book [ 'title' ]; $author = $book [ 'author' ]; }
  • 70. Super easy to fix require_once dirname ( __FILE__ ) . '/library/base.php'; $id = empty ($_GET['id']) ? null : $_GET['id']; $title = null ; $author = null ; if ($id) { $book = $dbh -> query( . . . ) -> fetch(); $title = $book['title']; $author = $book['author']; }
  • 71. FIEO <ul><li>Filter input </li><ul><li>They want to destroy your app
  • 72. Prevent SQL injection </li></ul><li>Escape output </li><ul><li>You might help them destroy your app
  • 73. Defend against XSS </li></ul></ul>
  • 74. book-form.php <ul><li>Use filter_input() to guarantee $id is either false or an int. </li></ul>$id = filter_input ( INPUT_GET , 'id' , FILTER_VALIDATE_INT );
  • 75. process-book.php <ul><li>More filter_input() </li></ul>$id = filter_input ( INPUT_POST , 'id' , FILTER_VALIDATE_INT ); $title = filter_input ( INPUT_POST , 'title' , FILTER_SANITIZE_STRING ); $author = filter_input ( INPUT_POST , 'author' , FILTER_SANITIZE_STRING );
  • 76. index.php <ul><li>Use htmlentities() to escape output </li></ul><?php foreach ($books as $book): ?> < tr > < td > < a href=&quot;book-form.php?id=<?php echo $book['id']; ?>&quot;> <?php echo htmlspecialchars ( $book [ 'title' ], ENT_COMPAT , 'UTF-8' ); ?> </ a > </ td > < td > <?php echo htmlspecialchars ( $book [ 'author' ], ENT_COMPAT , 'UTF-8' ); ?> </ td > </ tr > <?php endforeach ; ?>
  • 77. Prepared Statements <ul><li>More efficient (in some cases)
  • 78. Help protect against SQL injection
  • 79. Easier to read and maintain </li></ul>
  • 80. book-form.php $statement = $dbh -> prepare( ' SELECT title, author FROM bookshelf WHERE id = :id' ); $statement -> bindParam( ':id' , $id ); $statement -> execute(); $book = $statement -> fetch();
  • 81. book-form.php $statement = $dbh -> prepare (' SELECT title, author FROM bookshelf WHERE id = :id'); $statement -> bindParam(':id', $id); $statement -> execute(); $book = $statement -> fetch(); $title = $book['title']; $author = $book['author'];
  • 82. book-form.php $statement = $dbh -> prepare( ' SELECT title, author FROM bookshelf WHERE id = :id' ); $statement -> bindParam(':id', $id); $statement -> execute(); $book = $statement -> fetch();
  • 83. book-form.php $statement = $dbh -> prepare(' SELECT title, author FROM bookshelf WHERE id = :id'); $statement -> bindParam( ':id' , $id ); $statement -> execute(); $book = $statement -> fetch();
  • 84. book-form.php $statement = $dbh -> prepare(' SELECT title, author FROM bookshelf WHERE id = :id'); $statement -> bindParam(':id', $id); $statement -> execute(); $book = $statement -> fetch();
  • 85. process-book.php if ( $id ) { $statement = $dbh -> prepare( &quot; UPDATE bookshelf SET title = :title, author = :author WHERE id = :id&quot; ); $statement -> bindParam( ':title' , $title ); $statement -> bindParam( ':author' , $author ); $statement -> bindParam( ':id' , $id ); $statement -> execute(); } else { $statement = $dbh -> prepare( &quot; INSERT INTO bookshelf (title, author) VALUES (:title, :author)&quot; ); $statement -> bindParam( ':title' , $title ); $statement -> bindParam( ':author' , $author ); $statement -> execute(); }
  • 86. process-book.php if ( $id ) { $statement = $dbh -> prepare( &quot; UPDATE bookshelf SET title = :title, author = :author WHERE id = :id&quot; ); $statement -> bindParam(':title', $title); $statement -> bindParam(':author', $author); $statement -> bindParam(':id', $id); $statement -> execute(); } else { $statement = $dbh -> prepare( &quot; INSERT INTO bookshelf (title, author) VALUES (:title, :author)&quot; ); $statement -> bindParam(':title', $title); $statement -> bindParam(':author', $author); $statement -> execute(); }
  • 87. process-book.php if ($id) { $statement = $dbh -> prepare(&quot; UPDATE bookshelf SET title = :title, author = :author WHERE id = :id&quot;); $statement -> bindParam( ':title' , $title ); $statement -> bindParam( ':author' , $author ); $statement -> bindParam( ':id' , $id ); $statement -> execute(); } else { $statement = $dbh -> prepare(&quot; INSERT INTO bookshelf (title, author) VALUES (:title, :author)&quot;); $statement -> bindParam( ':title' , $title ); $statement -> bindParam( ':author' , $author ); $statement -> execute(); }
  • 88. process-book.php if ($id) { $statement = $dbh -> prepare(&quot; UPDATE bookshelf SET title = :title, author = :author WHERE id = :id&quot;); $statement -> bindParam(':title', $title); $statement -> bindParam(':author', $author); $statement -> bindParam(':id', $id); $statement -> execute(); } else { $statement = $dbh -> prepare(&quot; INSERT INTO bookshelf (title, author) VALUES (:title, :author)&quot;); $statement -> bindParam(':title', $title); $statement -> bindParam(':author', $author); $statement -> execute(); }
  • 89. A Touch of OOP Abstraction <ul><li>Yes, Virginia, PHP has a full object model
  • 90. Object model rewritten for PHP 5
  • 91. Unused in this app (besides PDO)
  • 92. Let's create a service layer
  • 93. Introduces some OOP principles
  • 94. High ROI </li><ul><li>Maintainability
  • 95. Testability </li></ul></ul>
  • 96. What? Where? Why? <ul><li>Class name: BookshelfService
  • 97. Namespace: BookshelfService
  • 98. Location: library/Bookshelf/Service
  • 99. Filename: BookshelfService.php
  • 100. PSR-0 autoloader compliant
  • 101. (The class name should mirror its location in the file system) </li></ul>
  • 102. BookshelfService.php namespace BookshelfService; class BookshelfService { private $_dbh ; public function __construct ( PDO $dbh ) { } public function find ( $id ) { } public function findAll () { } public function save ( array $options ) { } }
  • 103. BookshelfService.php private $_dbh ; public function __construct ( PDO $dbh ) { $this -> _dbh = $dbh ; }
  • 104. BookshelfService.php public function find ( $id ) { $sql = ' SELECT * FROM bookshelf WHERE id = :id' ; $statement = $this -> _dbh -> prepare( $sql ); $statement -> bindParam( ':id' , $id ); $statement -> execute(); return $statement -> fetch(); } public function findAll () { $sql = ' SELECT * FROM bookshelf ORDER BY title' ; return $this -> _dbh -> query( $sql ) -> fetchAll(); }
  • 105. BookshelfService.php public function save ( array $options ) { if ( $options [ 'id' ]) { $statement = $this -> _dbh -> prepare( &quot; UPDATE bookshelf SET title = :title, author = :author WHERE id = :id&quot; ); $statement -> execute( $options ); } else { unset ( $options [ 'id' ]); $statement = $this -> _dbh -> prepare( &quot; INSERT INTO bookshelf (title, author) VALUES (:title, :author)&quot; ); $statement -> execute( $options ); } }
  • 106. A New Class Means . . . <ul>. . . we need to add a few things to base.php. </ul>
  • 107. base.php set_include_path ( implode ( PATH_SEPARATOR , array ( get_include_path (), dirname ( __FILE__ ) ) ) );
  • 108. base.php function autoload ( $className ) { $className = ltrim ( $className , ' ' ); $fileName = '' ; $namespace = '' ; if ( $lastNsPos = strripos ( $className , ' ' )) { $namespace = substr ( $className , 0 , $lastNsPos ); $className = substr ( $className , $lastNsPos + 1 ); $fileName = str_replace ( ' ' , DIRECTORY_SEPARATOR , $namespace ) . DIRECTORY_SEPARATOR ; } $fileName .= str_replace ( '_' , DIRECTORY_SEPARATOR , $className ) . '.php' ; require $fileName ; } spl_autoload_register ( 'autoload' );
  • 109. base.php // database connection code $bookshelf = new BookshelfService BookshelfService ( $dbh );
  • 110. And now for some before and after shots . . .
  • 111. index.php: Before <?php require_once dirname ( __FILE__ ) . '/library/base.php' ; $books = $dbh -> query( &quot; SELECT * FROM bookshelf ORDER BY title&quot; ) -> fetchAll(); ?>
  • 112. index.php: After <?php require_once dirname ( __FILE__ ) . '/library/base.php' ; $books = $bookshelf -> findAll(); ?>
  • 113. book-form.php: Before if ( $id ) { $statement = $dbh -> prepare( ' SELECT title, author FROM bookshelf WHERE id = :id' ); $statement -> bindParam( ':id' , $id ); $statement -> execute(); $book = $statement -> fetch(); $title = $book['title']; $author = $book['author']; }
  • 114. book-form.php: After if ( $id ) { $book = $bookshelf -> find( $id ); $title = $book['title']; $author = $book['author']; }
  • 115. process-book.php: Before if ( $id ) { $statement = $dbh -> prepare( &quot; UPDATE bookshelf SET title = :title, author = :author WHERE id = :id&quot; ); $statement -> bindParam( ':title' , $title ); $statement -> bindParam( ':author' , $author ); $statement -> bindParam( ':id' , $id ); $statement -> execute(); } else { $statement = $dbh -> prepare( &quot; INSERT INTO bookshelf (title, author) VALUES (:title, :author)&quot; ); $statement -> bindParam( ':title' , $title ); $statement -> bindParam( ':author' , $author ); $statement -> execute(); }
  • 116. process-book.php: After $book = array ( 'id' => $id , 'title' => $title , 'author' => $author ); $bookshelf -> save( $book );
  • 117. What Have We Done? <ul><li>Put together a nice first application
  • 118. Made and corrected some typical mistakes
  • 119. Seen some nice features of PHP </li><ul><li>PDO
  • 120. Filtering and escaping
  • 121. Object model
  • 122. Superglobals </li></ul><li>Learned something? </li></ul>
  • 123. Want More? <ul><li>Come check out Memphis PHP!: http://MemphisPHP.org
  • 124. Presentation source code: https://github.com/jeremykendall/bookshelf
  • 125. PHP Manual: http://www.php.net/manual/en/index.php
  • 126. CSI: PHP http://csiphp.org
  • 127. PHP 101 Suggestions: http://csiphp.com/blog/2011/07/19/stop-doing-it-wrong-and-learn-to-code-good-too/
  • 128. PHP 101: PHP for the Absolute Beginner: http://devzone.zend.com/6/php-101-php-for-the-absolute-beginner/
  • 129. php|architect: http://www.phparch.com/ </li></ul>
  • 130. Thanks! <ul>Jeremy Kendall http://about.me/jeremykendall [email_address] </ul>

×