SlideShare a Scribd company logo
PHP 102 Out with the Bad, In with the Good Memphis PHP, February 23, 2012
Who is this guy? ,[object Object]
Following Along ,[object Object]
Why Did You  Start Programming?
I wanted to solve problems, but . . .
. . . I frequently caused  as many problems  as I solved.
Let's Solve a Problem Together ,[object Object]
Make horrible mistakes
Correct those mistakes
Make a cool improvement
Learn something?
What's the Problem? ,[object Object]
Requirements: ,[object Object]
Add books
Edit books
Delete books ,[object Object]
So, What do we Need? ,[object Object]
View (index.php)
Form (book-form.php)
Form processor (process-form.php)
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 />  &quot; ;   die (); } $books   =   $dbh -> query( &quot; SELECT   *   FROM  bookshelf  ORDER BY  title&quot; ) -> fetchAll();
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 />&quot;;   die (); } $books   =   $dbh -> query(&quot; SELECT   *   FROM  bookshelf  ORDER BY  title&quot;) -> fetchAll() ;
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 />  &quot; ;   die (); } $books   =   $dbh -> query(&quot; SELECT   *   FROM  bookshelf  ORDER BY  title&quot;) -> fetchAll();
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 />&quot;;   die (); } $books   =   $dbh -> query( &quot; SELECT   *   FROM  bookshelf  ORDER BY  title&quot; ) -> fetchAll();
index.php
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 ;   ?>
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 ; ?>
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 ; ?>
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 ;   ?>
 
book-form.php
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' ]; }
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']; }
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' ]; }
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 >
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 >
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; );
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;);
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;);
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;);
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;);
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; );
Glaring Problems? ,[object Object]
Input isn't filtered
Output isn't escaped
User-provided data used in SQL
Code Duplication try  {   $dbh   =   new   PDO ( $dsn ,  null ,  null ,  $options ); }  catch  ( PDOException   $e ) {   echo   &quot;Error!: &quot;   .   $e -> getMessage()  .   &quot;<br />  &quot; ;   die (); } ,[object Object]
Maintenance nightmare
The next developer will want to kill you
And your family
And your pets
Consolidate ,[object Object]
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 />  &quot; ;   die (); }
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 />&quot;;   die (); }
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 />&quot;;   die (); }
Replace db info with base.php ,[object Object],require_once   dirname ( __FILE__ )   .   '/library/base.php' ;
Duplication removed, but . . .
 
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 >
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' ]; }
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']; }
FIEO ,[object Object]
Prevent SQL injection ,[object Object],[object Object]
Defend against XSS
http://xkcd.com/327/
book-form.php ,[object Object],$id   =   filter_input ( INPUT_GET ,  'id' ,  FILTER_VALIDATE_INT );
process-book.php ,[object Object],$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 );
index.php ,[object Object],<?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 ; ?>
Prepared Statements ,[object Object]
Help protect against SQL injection
Easier to read and maintain
book-form.php: Before $book   =   $dbh -> query( &quot; SELECT  title, author  FROM  bookshelf  WHERE  id  =   $id &quot; ) -> fetch();
book-form.php: After $statement   =   $dbh -> prepare( ' SELECT  title, author  FROM  bookshelf  WHERE  id  =  :id' ); $statement -> bindParam( ':id' ,  $id ); $statement -> execute(); $book   =   $statement -> fetch();
book-form.php: After $statement   =   $dbh -> prepare (' SELECT  title, author  FROM  bookshelf  WHERE  id  =  :id'); $statement -> bindParam(':id', $id); $statement -> execute(); $book  =  $statement -> fetch();
book-form.php: After $statement  =  $dbh -> prepare( ' SELECT  title, author  FROM  bookshelf  WHERE  id  =  :id' ); $statement -> bindParam(':id', $id); $statement -> execute(); $book  =  $statement -> fetch();
book-form.php: After $statement  =  $dbh -> prepare(' SELECT  title, author  FROM  bookshelf  WHERE  id  =  :id'); $statement -> bindParam( ':id' ,  $id ); $statement -> execute(); $book  =  $statement -> fetch();
book-form.php: After $statement  =  $dbh -> prepare(' SELECT  title, author  FROM  bookshelf  WHERE  id  =  :id'); $statement -> bindParam(':id', $id); $statement -> execute(); $book   =   $statement -> fetch();
process-book.php: Before 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 ); }
process-book.php: After 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(); }
process-book.php: After 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(); }
process-book.php: After 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(); }

More Related Content

What's hot

What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?
brynary
 
Practical PHP by example Jan Leth-Kjaer
Practical PHP by example   Jan Leth-KjaerPractical PHP by example   Jan Leth-Kjaer
Practical PHP by example Jan Leth-Kjaer
COMMON Europe
 
Jquery presentation
Jquery presentationJquery presentation
Jquery presentationguest5d87aa6
 
Web Development Course: PHP lecture 2
Web Development Course: PHP lecture 2Web Development Course: PHP lecture 2
Web Development Course: PHP lecture 2
Gheyath M. Othman
 
Let's write secure Drupal code! - DrupalCamp Oslo, 2018
Let's write secure Drupal code! - DrupalCamp Oslo, 2018Let's write secure Drupal code! - DrupalCamp Oslo, 2018
Let's write secure Drupal code! - DrupalCamp Oslo, 2018
Balázs Tatár
 
Evolution of API With Blogging
Evolution of API With BloggingEvolution of API With Blogging
Evolution of API With Blogging
Takatsugu Shigeta
 
Let's write secure Drupal code! - Drupal Camp Poland 2019
Let's write secure Drupal code! - Drupal Camp Poland 2019Let's write secure Drupal code! - Drupal Camp Poland 2019
Let's write secure Drupal code! - Drupal Camp Poland 2019
Balázs Tatár
 
Xslate sv perl-2013-7-11
Xslate sv perl-2013-7-11Xslate sv perl-2013-7-11
Xslate sv perl-2013-7-11Goro Fuji
 
Changing Template Engine
Changing Template EngineChanging Template Engine
Changing Template Engine
Takatsugu Shigeta
 
2014 database - course 2 - php
2014 database - course 2 - php2014 database - course 2 - php
2014 database - course 2 - phpHung-yu Lin
 
Php Tutorial | Introduction Demo | Basics
 Php Tutorial | Introduction Demo | Basics Php Tutorial | Introduction Demo | Basics
Php Tutorial | Introduction Demo | Basics
Shubham Kumar Singh
 
HTML Templates Using Clear Silver
HTML Templates Using Clear SilverHTML Templates Using Clear Silver
HTML Templates Using Clear Silver
PaulWay
 
Introducation to php for beginners
Introducation to php for beginners Introducation to php for beginners
Introducation to php for beginners
musrath mohammad
 
Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019
Balázs Tatár
 
Getting started with MongoDB and PHP
Getting started with MongoDB and PHPGetting started with MongoDB and PHP
Getting started with MongoDB and PHP
gates10gen
 
IPW HTML course
IPW HTML courseIPW HTML course
IPW HTML courseVlad Posea
 

What's hot (18)

Further Php
Further PhpFurther Php
Further Php
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?
 
Practical PHP by example Jan Leth-Kjaer
Practical PHP by example   Jan Leth-KjaerPractical PHP by example   Jan Leth-Kjaer
Practical PHP by example Jan Leth-Kjaer
 
Jquery presentation
Jquery presentationJquery presentation
Jquery presentation
 
Web Development Course: PHP lecture 2
Web Development Course: PHP lecture 2Web Development Course: PHP lecture 2
Web Development Course: PHP lecture 2
 
Let's write secure Drupal code! - DrupalCamp Oslo, 2018
Let's write secure Drupal code! - DrupalCamp Oslo, 2018Let's write secure Drupal code! - DrupalCamp Oslo, 2018
Let's write secure Drupal code! - DrupalCamp Oslo, 2018
 
Ruby on discuz
Ruby on discuzRuby on discuz
Ruby on discuz
 
Evolution of API With Blogging
Evolution of API With BloggingEvolution of API With Blogging
Evolution of API With Blogging
 
Let's write secure Drupal code! - Drupal Camp Poland 2019
Let's write secure Drupal code! - Drupal Camp Poland 2019Let's write secure Drupal code! - Drupal Camp Poland 2019
Let's write secure Drupal code! - Drupal Camp Poland 2019
 
Xslate sv perl-2013-7-11
Xslate sv perl-2013-7-11Xslate sv perl-2013-7-11
Xslate sv perl-2013-7-11
 
Changing Template Engine
Changing Template EngineChanging Template Engine
Changing Template Engine
 
2014 database - course 2 - php
2014 database - course 2 - php2014 database - course 2 - php
2014 database - course 2 - php
 
Php Tutorial | Introduction Demo | Basics
 Php Tutorial | Introduction Demo | Basics Php Tutorial | Introduction Demo | Basics
Php Tutorial | Introduction Demo | Basics
 
HTML Templates Using Clear Silver
HTML Templates Using Clear SilverHTML Templates Using Clear Silver
HTML Templates Using Clear Silver
 
Introducation to php for beginners
Introducation to php for beginners Introducation to php for beginners
Introducation to php for beginners
 
Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019
 
Getting started with MongoDB and PHP
Getting started with MongoDB and PHPGetting started with MongoDB and PHP
Getting started with MongoDB and PHP
 
IPW HTML course
IPW HTML courseIPW HTML course
IPW HTML course
 

Viewers also liked

Tdd in php a brief example
Tdd in php   a brief exampleTdd in php   a brief example
Tdd in php a brief exampleJeremy Kendall
 
Django a whirlwind tour
Django   a whirlwind tourDjango   a whirlwind tour
Django a whirlwind tour
Brad Montgomery
 
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPJeremy Kendall
 
Php 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the GoodPhp 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the Good
Jeremy Kendall
 
PHP Data Objects
PHP Data ObjectsPHP Data Objects
PHP Data Objects
Wez Furlong
 
TDC SP 2015 - PHP7: melhor e mais rápido
TDC SP 2015 - PHP7: melhor e mais rápidoTDC SP 2015 - PHP7: melhor e mais rápido
TDC SP 2015 - PHP7: melhor e mais rápido
Bruno Ricardo Siqueira
 

Viewers also liked (7)

Tdd in php a brief example
Tdd in php   a brief exampleTdd in php   a brief example
Tdd in php a brief example
 
Django a whirlwind tour
Django   a whirlwind tourDjango   a whirlwind tour
Django a whirlwind tour
 
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHP
 
Php 101: PDO
Php 101: PDOPhp 101: PDO
Php 101: PDO
 
Php 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the GoodPhp 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the Good
 
PHP Data Objects
PHP Data ObjectsPHP Data Objects
PHP Data Objects
 
TDC SP 2015 - PHP7: melhor e mais rápido
TDC SP 2015 - PHP7: melhor e mais rápidoTDC SP 2015 - PHP7: melhor e mais rápido
TDC SP 2015 - PHP7: melhor e mais rápido
 

Similar to PHP 102: Out with the Bad, In with the Good

03 Php Array String Functions
03 Php Array String Functions03 Php Array String Functions
03 Php Array String Functions
Geshan Manandhar
 
PHP Basics for Designers
PHP Basics for DesignersPHP Basics for Designers
PHP Basics for DesignersMatthew Turland
 
Php Calling Operators
Php Calling OperatorsPhp Calling Operators
Php Calling Operatorsmussawir20
 
Introduction To Lamp
Introduction To LampIntroduction To Lamp
Introduction To Lamp
Amzad Hossain
 
Php Crash Course
Php Crash CoursePhp Crash Course
Php Crash Coursemussawir20
 
Php Training
Php TrainingPhp Training
Php Training
adfa
 
Haml & Sass presentation
Haml & Sass presentationHaml & Sass presentation
Haml & Sass presentation
bryanbibat
 
The Basics Of Page Creation
The Basics Of Page CreationThe Basics Of Page Creation
The Basics Of Page Creation
Wildan Maulana
 
JQuery 101
JQuery 101JQuery 101
JQuery Basics
JQuery BasicsJQuery Basics
JQuery Basics
Alin Taranu
 
Terms of endearment - the ElasticSearch Query DSL explained
Terms of endearment - the ElasticSearch Query DSL explainedTerms of endearment - the ElasticSearch Query DSL explained
Terms of endearment - the ElasticSearch Query DSL explained
clintongormley
 
Optimizing Drupal for Mobile Devices
Optimizing Drupal for Mobile DevicesOptimizing Drupal for Mobile Devices
Optimizing Drupal for Mobile DevicesSugree Phatanapherom
 
High-level Web Testing
High-level Web TestingHigh-level Web Testing
High-level Web Testingpetersergeant
 
Forum Presentation
Forum PresentationForum Presentation
Forum Presentation
Angus Pratt
 
Ae internals
Ae internalsAe internals
Ae internals
mnikolenko
 

Similar to PHP 102: Out with the Bad, In with the Good (20)

03 Php Array String Functions
03 Php Array String Functions03 Php Array String Functions
03 Php Array String Functions
 
PHP Basics for Designers
PHP Basics for DesignersPHP Basics for Designers
PHP Basics for Designers
 
Php Calling Operators
Php Calling OperatorsPhp Calling Operators
Php Calling Operators
 
Introduction To Lamp
Introduction To LampIntroduction To Lamp
Introduction To Lamp
 
Web Scraping with PHP
Web Scraping with PHPWeb Scraping with PHP
Web Scraping with PHP
 
Php Crash Course
Php Crash CoursePhp Crash Course
Php Crash Course
 
Os Nixon
Os NixonOs Nixon
Os Nixon
 
Php
PhpPhp
Php
 
Php Sq Lite
Php Sq LitePhp Sq Lite
Php Sq Lite
 
Php Training
Php TrainingPhp Training
Php Training
 
Haml & Sass presentation
Haml & Sass presentationHaml & Sass presentation
Haml & Sass presentation
 
The Basics Of Page Creation
The Basics Of Page CreationThe Basics Of Page Creation
The Basics Of Page Creation
 
JQuery 101
JQuery 101JQuery 101
JQuery 101
 
JQuery Basics
JQuery BasicsJQuery Basics
JQuery Basics
 
Terms of endearment - the ElasticSearch Query DSL explained
Terms of endearment - the ElasticSearch Query DSL explainedTerms of endearment - the ElasticSearch Query DSL explained
Terms of endearment - the ElasticSearch Query DSL explained
 
Optimizing Drupal for Mobile Devices
Optimizing Drupal for Mobile DevicesOptimizing Drupal for Mobile Devices
Optimizing Drupal for Mobile Devices
 
Php My Sql
Php My SqlPhp My Sql
Php My Sql
 
High-level Web Testing
High-level Web TestingHigh-level Web Testing
High-level Web Testing
 
Forum Presentation
Forum PresentationForum Presentation
Forum Presentation
 
Ae internals
Ae internalsAe internals
Ae internals
 

More from Jeremy Kendall

Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHP
Jeremy Kendall
 
5 Ways to Awesome-ize Your (PHP) Code
5 Ways to Awesome-ize Your (PHP) Code5 Ways to Awesome-ize Your (PHP) Code
5 Ways to Awesome-ize Your (PHP) Code
Jeremy Kendall
 
Game Changing Dependency Management
Game Changing Dependency ManagementGame Changing Dependency Management
Game Changing Dependency ManagementJeremy Kendall
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
Jeremy Kendall
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkJeremy Kendall
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkJeremy Kendall
 
TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25Jeremy Kendall
 
Zend_Form to the Rescue - A Brief Introduction to Zend_Form
Zend_Form to the Rescue - A Brief Introduction to Zend_FormZend_Form to the Rescue - A Brief Introduction to Zend_Form
Zend_Form to the Rescue - A Brief Introduction to Zend_FormJeremy Kendall
 
Zero to ZF in 10 Minutes
Zero to ZF in 10 MinutesZero to ZF in 10 Minutes
Zero to ZF in 10 Minutes
Jeremy Kendall
 
A Brief Introduction to Zend_Form
A Brief Introduction to Zend_FormA Brief Introduction to Zend_Form
A Brief Introduction to Zend_Form
Jeremy Kendall
 
Zero to Zend Framework in 10 minutes
Zero to Zend Framework in 10 minutesZero to Zend Framework in 10 minutes
Zero to Zend Framework in 10 minutesJeremy Kendall
 

More from Jeremy Kendall (11)

Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHP
 
5 Ways to Awesome-ize Your (PHP) Code
5 Ways to Awesome-ize Your (PHP) Code5 Ways to Awesome-ize Your (PHP) Code
5 Ways to Awesome-ize Your (PHP) Code
 
Game Changing Dependency Management
Game Changing Dependency ManagementGame Changing Dependency Management
Game Changing Dependency Management
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25
 
Zend_Form to the Rescue - A Brief Introduction to Zend_Form
Zend_Form to the Rescue - A Brief Introduction to Zend_FormZend_Form to the Rescue - A Brief Introduction to Zend_Form
Zend_Form to the Rescue - A Brief Introduction to Zend_Form
 
Zero to ZF in 10 Minutes
Zero to ZF in 10 MinutesZero to ZF in 10 Minutes
Zero to ZF in 10 Minutes
 
A Brief Introduction to Zend_Form
A Brief Introduction to Zend_FormA Brief Introduction to Zend_Form
A Brief Introduction to Zend_Form
 
Zero to Zend Framework in 10 minutes
Zero to Zend Framework in 10 minutesZero to Zend Framework in 10 minutes
Zero to Zend Framework in 10 minutes
 

Recently uploaded

PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 

Recently uploaded (20)

PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 

PHP 102: Out with the Bad, In with the Good

  • 1. PHP 102 Out with the Bad, In with the Good Memphis PHP, February 23, 2012
  • 2.
  • 3.
  • 4. Why Did You Start Programming?
  • 5. I wanted to solve problems, but . . .
  • 6. . . . I frequently caused as many problems as I solved.
  • 7.
  • 10. Make a cool improvement
  • 12.
  • 13.
  • 16.
  • 17.
  • 21. 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 /> &quot; ; die (); } $books = $dbh -> query( &quot; SELECT * FROM bookshelf ORDER BY title&quot; ) -> fetchAll();
  • 22. 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 />&quot;; die (); } $books = $dbh -> query(&quot; SELECT * FROM bookshelf ORDER BY title&quot;) -> fetchAll() ;
  • 23. 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 /> &quot; ; die (); } $books = $dbh -> query(&quot; SELECT * FROM bookshelf ORDER BY title&quot;) -> fetchAll();
  • 24. 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 />&quot;; die (); } $books = $dbh -> query( &quot; SELECT * FROM bookshelf ORDER BY title&quot; ) -> fetchAll();
  • 26. 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 ; ?>
  • 27. 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 ; ?>
  • 28. 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 ; ?>
  • 29. 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 ; ?>
  • 30.  
  • 32. 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' ]; }
  • 33. 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']; }
  • 34. 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' ]; }
  • 35. 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 >
  • 36. 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 >
  • 37. 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; );
  • 38. 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;);
  • 39. 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;);
  • 40. 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;);
  • 41. 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;);
  • 42. 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; );
  • 43.
  • 47.
  • 49. The next developer will want to kill you
  • 52.
  • 53. 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 /> &quot; ; die (); }
  • 54. 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 />&quot;; die (); }
  • 55. 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 />&quot;; die (); }
  • 56.
  • 58.  
  • 59. 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 >
  • 60. 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' ]; }
  • 61. 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']; }
  • 62.
  • 63.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70. Help protect against SQL injection
  • 71. Easier to read and maintain
  • 72. book-form.php: Before $book = $dbh -> query( &quot; SELECT title, author FROM bookshelf WHERE id = $id &quot; ) -> fetch();
  • 73. book-form.php: After $statement = $dbh -> prepare( ' SELECT title, author FROM bookshelf WHERE id = :id' ); $statement -> bindParam( ':id' , $id ); $statement -> execute(); $book = $statement -> fetch();
  • 74. book-form.php: After $statement = $dbh -> prepare (' SELECT title, author FROM bookshelf WHERE id = :id'); $statement -> bindParam(':id', $id); $statement -> execute(); $book = $statement -> fetch();
  • 75. book-form.php: After $statement = $dbh -> prepare( ' SELECT title, author FROM bookshelf WHERE id = :id' ); $statement -> bindParam(':id', $id); $statement -> execute(); $book = $statement -> fetch();
  • 76. book-form.php: After $statement = $dbh -> prepare(' SELECT title, author FROM bookshelf WHERE id = :id'); $statement -> bindParam( ':id' , $id ); $statement -> execute(); $book = $statement -> fetch();
  • 77. book-form.php: After $statement = $dbh -> prepare(' SELECT title, author FROM bookshelf WHERE id = :id'); $statement -> bindParam(':id', $id); $statement -> execute(); $book = $statement -> fetch();
  • 78. process-book.php: Before 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 ); }
  • 79. process-book.php: After 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(); }
  • 80. process-book.php: After 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(); }
  • 81. process-book.php: After 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(); }
  • 82. process-book.php: After 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(); }
  • 83.
  • 85. Unused in this app (besides PDO)
  • 86.
  • 87. Take advantage of namespaces
  • 88.
  • 90.
  • 95. (The class name should mirror its location in the file system)
  • 96. BookshelfService.php namespace Bookshelfervice; class BookshelfService { private $_dbh ; public function __construct (PDO $dbh ) { } public function find ( $id ) { } public function findAll () { } public function save ( array $options ) { } }
  • 97. BookshelfService.php private $_dbh ; public function __construct (PDO $dbh ) { $this -> _dbh = $dbh ; }
  • 98. 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(); }
  • 99. 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 ); } }
  • 100.
  • 101. base.php set_include_path ( implode ( PATH_SEPARATOR , array ( get_include_path (), dirname ( __FILE__ ) ) ) );
  • 102. 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' );
  • 103. base.php // database connection code $bookshelf = new BookshelferviceBookshelfService ( $dbh );
  • 104. And now for some before and after shots . . .
  • 105. index.php: Before <?php require_once dirname ( __FILE__ ) . '/library/base.php' ; $books = $dbh -> query( &quot; SELECT * FROM bookshelf ORDER BY title&quot; ) -> fetchAll(); ?>
  • 106. index.php: After <?php require_once dirname ( __FILE__ ) . '/library/base.php' ; $books = $bookshelf -> findAll(); ?>
  • 107. 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']; }
  • 108. book-form.php: After if ( $id ) { $book = $bookshelf -> find( $id ); $title = $book['title']; $author = $book['author']; }
  • 109. 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(); }
  • 110. process-book.php: After $book = array ( 'id' => $id , 'title' => $title , 'author' => $author ); $bookshelf -> save( $book );
  • 111.
  • 112. Made and corrected some typical mistakes
  • 113.
  • 116.
  • 117.
  • 118. PHP Manual: http://www.php.net/manual/en/index.php
  • 119. CSI: PHP http://csiphp.com
  • 120. PHP 101 Suggestions: http://csiphp.com/blog/2011/07/19/stop-doing-it-wrong-and-learn-to-code-good-too/
  • 121. PHP 101: PHP for the Absolute Beginner: http://devzone.zend.com/6/php-101-php-for-the-absolute-beginner/
  • 124.