Fast relational web site
construction with PHP




 Nelson Gomes (nelson.gomes@telecom.pt)
  Team Leader
  ZCE, ITIL Foundation V3, LPIC1-101
  16th of November 2012
Talk Index

Introduction
Frameworks
Relational Database Model
Setting up
The 'Magic'
Queries
Transactions
Conclusion
Links
Q&A
Introduction

The purpose of this talk is to help web developers to take
  advantage of some known PHP frameworks to develop
  complex websites rapidly;
Although we're showing some specific frameworks in this
  talk, other frameworks exist that do almost the same thing
  or even better;
Just google the web and try out other frameworks and use
  the ones you like the most;
The benefit of using these frameworks is to be more
  productive, to use best pratices and to develop faster;
Introduction (cont.)

Developing complex sites with complex relational databases
  can be very difficult without the right tools:
  Manage Database Connections;
  Maintaining Relational Integrity;
  Performing Transactions;
  Acessing data spread over several tables;
  Updating, deleting and inserting records without loosing
    integrity;
Introduction (cont.)

Example of how some developers still program:
 mysql_query(“insert into customers (name, phone) values
     ('$name', '$phone');


When using many tables the developers need to create
  methods to insert, update, delete and query records, this can
  give a lot of work;


In this presentation, I'll try to show how to do all of this
  with minimum programming...
Introduction (cont.)

Web site security depends greatly of the awareness
  developers have for security issues;
Many PHP developers do bad code because don't know the
  problems that can arise from bad programming:
  SQL Injection;
  Cross-Site Scripting;
  Cross-Site Request Forgery;
  (...)
Using these frameworks correctly reduce (some) security
  vulnerabilities;
Introduction (cont.)

Other frameworks:
  Propel;
  Zend_Db;
  Log4PHP;
  Zend;
  Symfony;
  xAjax;
  NuSOAP;
Frameworks

Introducing some PHP frameworks:
  Doctrine – is a Object relational mapper that works on
    top of PDO (PHP Data Objects);
  Smarty – an engine for web templating in PHP;
  MVC – (could use one MVC framework, but on this talk
    won't use any);


You can easily change any of these frameworks with others
  of your choice;
Frameworks (cont.)

Doctrine
  With Doctrine you can use 'Code First', 'Model First' and
    'Database First' approaches, meaning you start by
    creating objects, UML or a database as a start point;
  All doctrine queries are made using DQL – Doctrine
    Query Language;
In this talk we'll go throught 'Database First' approach,
  meaning Doctrine will look into the database and generate
  code for it;
In this talk I'm using Doctrine 1.2.4, why?
Frameworks (cont.)

Advantages of using Doctrine:
 Object Oriented Approach;
  No need to rewrite code when switching database;
  No need to keep track of identifiers of the inserted fields;
  Object are written to database by Doctrine, no need to
    SQL!
  Associations are managed by Doctrine;
  Database can be generated by our models (yaml, xml)
Frameworks (cont.)

Smarty
  Is a template engine for PHP;
  Allows separating design from code;
  Eases the maintainability of on large web sites;
  Allows reuse of templates;
  Makes your website go faster;
  Improves security;
  Easily extensible;
Relational Database Model
Setting Up

Doctrine:
 require_once BASE_DIR.'/lib/Doctrine­1.2.4/Doctrine.php';
 spl_autoload_register(array('Doctrine', 'autoload'));
 spl_autoload_register(array('Doctrine', 'modelsAutoload'));


 $manager = Doctrine_Manager::getInstance();
 $manager­>setAttribute(Doctrine::ATTR_MODEL_LOADING, 
    Doctrine::MODEL_LOADING_CONSERVATIVE);
 $manager­>setCharset('utf8');
 $manager­>connection('mysql://codebits:codebits@127.0.0.1/codebits');
 if (DEBUGMODE) 
       Doctrine::generateModelsFromDb(dirname(__FILE__).'/models/');
 Doctrine::loadModels(dirname(__FILE__).'/models/');
Setting Up (cont.)

Smarty:

 require_once(BASE_DIR.'/lib/Smarty­3.1.12/libs/Smarty.class.php');


 $smarty = new Smarty();
 $smarty­>template_dir = dirname(__FILE__).'/lib/templates/';
 $smarty­>compile_dir  = dirname(__FILE__).'/lib/templates_c/';
 $smarty­>config_dir   = dirname(__FILE__).'/lib/configs/';
 $smarty­>cache_dir    = dirname(__FILE__).'/cache/';


 $smarty­>compile_check=DEBUGMODE;
The 'Magic'

Folder models has been filled by Doctrine with code:
    models/*.php (to fill with your business logic);
    models/generated/*.php (object definitions);


Folder lib/templates_c/*.php has been filled by Smarty with
  munged templates;


Now that the magic is working let's fill a web page with the
  data we have in the tables!
The 'Magic'

Declaring table relations using hasMany, hasOne:

class Customers extends BaseCustomers {
    public function setUp() {
        $this­>hasMany('CustomerUsers as relatedUsers',
              array(
                  'local'=>'id',
                  'foreign'=>'fk_customer_id',
              )
        );
        (…)
    }
}
The 'Magic'

Avoiding XSS in Smarty:
  function escFilter($content,$smarty) { 
      return htmlspecialchars($content,ENT_QUOTES,UTF­8);
  }
  $smarty­>registerFilter('variable','escFilter');



To show unsafe content just explicitly do:
  {$variable nofilter}



Doctrine manages strings avoiding SQL Injection attempts!
  (but cannot do miracles!)
Transactions

But a good business layer only works well if it is
  transactional, to maintain relational integrity.
  $conn=Doctrine_Manager::connection();
  try{
      $conn­>beginTransaction();
      $customer=new Customers();
      $customer­>name=$name; (...)
      $customer­>save();
      $address=new Addresses();
      $address­>fk_customer_id=$customer­>id; (...)
      $address­>save();
   $conn­>commit();
  } catch(Exception $ex) {
      $conn­>rollback();
  }
Queries

Any language or framework is secure depending on how
  users use it:

  static function updateCustomerName($name, $id) {
      $conn=Doctrine_Manager::connection();
      $conn­>execute(“update customers set name='$name' where id=$id”);
  }



Bad pratice to concat any user input, use instead Doctrine
  methods!
The above example can also be database dependant which
  isn't a good practice.
Queries

Usind DQL:
   static function getAllUserCustomers($id,$page=0){
   return Doctrine_Query::create()
       ­>select('c.*')
       ­>from('Customers c')
       ­>where('c.relatedUsers.fk_customer_id=:userid', 
            array(':userid'=>$id))
       ­>orderBy('c.name')
       ­>limit(20)
       ­>offset($page*20)
       #­>getSqlQuery();
       ­>execute();
   }
Conclusion

In this demo:
  We accessed data scattered over 7 different tables with
    (almost) zero programming;
  We didn't established or managed any connection;
  Our application can be now easily converted to another
    database engine with minimum effort;
  Each page is only a couple of lines in size, no more
    HTML embedding nightmares...;
  Our application has become more secure;
  In a couple of minutes...
Links

http://www.doctrine-project.org/
http://www.smarty.net/
http://logging.apache.org/log4php/
http://code.google.com/p/nusoap-for-php5/
http://www.zend.com/
http://www.xajaxproject.org/
(...)
Q&A




      Thank You

Codebits 2012 - Fast relational web site construction.

  • 1.
    Fast relational website construction with PHP  Nelson Gomes (nelson.gomes@telecom.pt) Team Leader ZCE, ITIL Foundation V3, LPIC1-101 16th of November 2012
  • 2.
    Talk Index Introduction Frameworks Relational DatabaseModel Setting up The 'Magic' Queries Transactions Conclusion Links Q&A
  • 3.
    Introduction The purpose ofthis talk is to help web developers to take advantage of some known PHP frameworks to develop complex websites rapidly; Although we're showing some specific frameworks in this talk, other frameworks exist that do almost the same thing or even better; Just google the web and try out other frameworks and use the ones you like the most; The benefit of using these frameworks is to be more productive, to use best pratices and to develop faster;
  • 4.
    Introduction (cont.) Developing complexsites with complex relational databases can be very difficult without the right tools: Manage Database Connections; Maintaining Relational Integrity; Performing Transactions; Acessing data spread over several tables; Updating, deleting and inserting records without loosing integrity;
  • 5.
    Introduction (cont.) Example ofhow some developers still program: mysql_query(“insert into customers (name, phone) values ('$name', '$phone'); When using many tables the developers need to create methods to insert, update, delete and query records, this can give a lot of work; In this presentation, I'll try to show how to do all of this with minimum programming...
  • 6.
    Introduction (cont.) Web sitesecurity depends greatly of the awareness developers have for security issues; Many PHP developers do bad code because don't know the problems that can arise from bad programming: SQL Injection; Cross-Site Scripting; Cross-Site Request Forgery; (...) Using these frameworks correctly reduce (some) security vulnerabilities;
  • 7.
    Introduction (cont.) Other frameworks: Propel; Zend_Db; Log4PHP; Zend; Symfony; xAjax; NuSOAP;
  • 8.
    Frameworks Introducing some PHPframeworks: Doctrine – is a Object relational mapper that works on top of PDO (PHP Data Objects); Smarty – an engine for web templating in PHP; MVC – (could use one MVC framework, but on this talk won't use any); You can easily change any of these frameworks with others of your choice;
  • 9.
    Frameworks (cont.) Doctrine With Doctrine you can use 'Code First', 'Model First' and 'Database First' approaches, meaning you start by creating objects, UML or a database as a start point; All doctrine queries are made using DQL – Doctrine Query Language; In this talk we'll go throught 'Database First' approach, meaning Doctrine will look into the database and generate code for it; In this talk I'm using Doctrine 1.2.4, why?
  • 10.
    Frameworks (cont.) Advantages ofusing Doctrine: Object Oriented Approach; No need to rewrite code when switching database; No need to keep track of identifiers of the inserted fields; Object are written to database by Doctrine, no need to SQL! Associations are managed by Doctrine; Database can be generated by our models (yaml, xml)
  • 11.
    Frameworks (cont.) Smarty Is a template engine for PHP; Allows separating design from code; Eases the maintainability of on large web sites; Allows reuse of templates; Makes your website go faster; Improves security; Easily extensible;
  • 12.
  • 13.
    Setting Up Doctrine: require_once BASE_DIR.'/lib/Doctrine­1.2.4/Doctrine.php'; spl_autoload_register(array('Doctrine', 'autoload')); spl_autoload_register(array('Doctrine', 'modelsAutoload')); $manager = Doctrine_Manager::getInstance(); $manager­>setAttribute(Doctrine::ATTR_MODEL_LOADING,  Doctrine::MODEL_LOADING_CONSERVATIVE); $manager­>setCharset('utf8'); $manager­>connection('mysql://codebits:codebits@127.0.0.1/codebits'); if (DEBUGMODE)  Doctrine::generateModelsFromDb(dirname(__FILE__).'/models/'); Doctrine::loadModels(dirname(__FILE__).'/models/');
  • 14.
    Setting Up (cont.) Smarty: require_once(BASE_DIR.'/lib/Smarty­3.1.12/libs/Smarty.class.php'); $smarty = new Smarty(); $smarty­>template_dir = dirname(__FILE__).'/lib/templates/'; $smarty­>compile_dir  = dirname(__FILE__).'/lib/templates_c/'; $smarty­>config_dir   = dirname(__FILE__).'/lib/configs/'; $smarty­>cache_dir    = dirname(__FILE__).'/cache/'; $smarty­>compile_check=DEBUGMODE;
  • 15.
    The 'Magic' Folder modelshas been filled by Doctrine with code: models/*.php (to fill with your business logic); models/generated/*.php (object definitions); Folder lib/templates_c/*.php has been filled by Smarty with munged templates; Now that the magic is working let's fill a web page with the data we have in the tables!
  • 16.
    The 'Magic' Declaring tablerelations using hasMany, hasOne: class Customers extends BaseCustomers { public function setUp() { $this­>hasMany('CustomerUsers as relatedUsers', array( 'local'=>'id', 'foreign'=>'fk_customer_id', ) ); (…) } }
  • 17.
    The 'Magic' Avoiding XSSin Smarty: function escFilter($content,$smarty) {  return htmlspecialchars($content,ENT_QUOTES,UTF­8); } $smarty­>registerFilter('variable','escFilter'); To show unsafe content just explicitly do: {$variable nofilter} Doctrine manages strings avoiding SQL Injection attempts! (but cannot do miracles!)
  • 18.
    Transactions But a goodbusiness layer only works well if it is transactional, to maintain relational integrity. $conn=Doctrine_Manager::connection(); try{ $conn­>beginTransaction(); $customer=new Customers(); $customer­>name=$name; (...) $customer­>save(); $address=new Addresses(); $address­>fk_customer_id=$customer­>id; (...) $address­>save();  $conn­>commit(); } catch(Exception $ex) { $conn­>rollback(); }
  • 19.
    Queries Any language orframework is secure depending on how users use it: static function updateCustomerName($name, $id) { $conn=Doctrine_Manager::connection(); $conn­>execute(“update customers set name='$name' where id=$id”); } Bad pratice to concat any user input, use instead Doctrine methods! The above example can also be database dependant which isn't a good practice.
  • 20.
    Queries Usind DQL: static function getAllUserCustomers($id,$page=0){ return Doctrine_Query::create() ­>select('c.*') ­>from('Customers c') ­>where('c.relatedUsers.fk_customer_id=:userid',  array(':userid'=>$id)) ­>orderBy('c.name') ­>limit(20) ­>offset($page*20) #­>getSqlQuery(); ­>execute(); }
  • 21.
    Conclusion In this demo: We accessed data scattered over 7 different tables with (almost) zero programming; We didn't established or managed any connection; Our application can be now easily converted to another database engine with minimum effort; Each page is only a couple of lines in size, no more HTML embedding nightmares...; Our application has become more secure; In a couple of minutes...
  • 22.
  • 23.
    Q&A Thank You