Codebits 2012 - Fast relational web site construction

Embed Size (px)

Citation preview

Slide 1

Fast relational web site construction with PHP

Nelson Gomes ([email protected])Team LeaderZCE, ITIL Foundation V3, LPIC1-10116th of November 2012

Introduction

Frameworks

Relational Database Model

Setting up

The 'Magic'

Queries

Transactions

Conclusion

Links

Q&A

Talk Index

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.)

DoctrineWith 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.)

SmartyIs 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:[email protected]/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...

Linkshttp://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