Codebits 2012 - Fast relational web site construction.
-
Upload
nelson-gomes -
Category
Documents
-
view
747 -
download
5
Transcript of Codebits 2012 - Fast relational web site construction.
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