Debugging techniques with free tools [updated 30 June]

  • Netbeans PHP 6.* + Xdebug + Firefox (with netbeans extension to server debug with javascript) !
    howto configure with
    Wamp 2.0h:
    – download
    php_xdebug-2.0.4-5.2.8.dll into the Wamp folder
    – open port 9000 in the firewall
    – edit php.ini adding


    – now, let’s debug the script with Netbeans choosing “Server side PHP with client side Javascript”. Netbeans will install an extension for firefox which will allows to launch the script in the server (localhost). The extension will “pause” (thanks to extension and javascript) the server execution and it will be possibile to debug with netbeans when the breakpoints (put them in valid lines) will be reached.

    See the screenshot: array debug

    Note: obviously it’s possible to debug the script directly in the php command line (no browsers is needed).

    Tested with Netbeans 6.7, Wamp 2.0h

    see official wiki

  • Eclipse PDT + Xdebug ! both are free. In Eclipse you can set breakpoints, then run the application; when breakpoints are reached, Eclipse will show variable values (tree explorer for multi-level arrays )
  • debug with php code
    function debugAll(var_dump($GLOBALS));
    “[pre]; debugAll(); print [/pre];
  • zend debugger […]
  • […]

Symfony: password hashing and login

It’s a good practice not to keep the clear values of the passwords in the db, but to store only their hash values.

You can do login operations comparing the hash value of the inserted password with the stored hash value.

How to do it with Symfony 1.2, propel ORM, MD5 hashing:
  • db schema: Use a VARCHAR, length must be at least 32
  • validator:
    – require a minimum length (ex: 3 chars) or (better) regexp validation
    – use a widget Schema password
    $this->widgetSchema[‘password’] = new sfWidgetFormInputPassword (array(
    ‘always_render_empty’ => false, //IMPORTANT !!
  • model: modify the method setPassword($v) assigning the md5 value:
    public function setPassword($v)
    //set md5 password if there is a new inserted password
    if (strlen($v)!=32) //if is not a md5 value, convert into it (*)
    $v = md5($v);
    parent::setPassword($v); }
  • To check the login data, use the md5 value in the post action :

From now, only the hash value of the passwords will be stored.

The CRUD operations will work.

(*) Note: it won’t work if the clear password is 32 chars length.

LAMP documentation links



JSON generation with PHP and parsing with jQuery

JSON [official site][wiki] is a data interchange format (similar to XML, but simpler), often used for WEB 2.0 applications to load structured data with AJAX HTTP calls.

– PHP offers functions to encode and decode JSON from/to a PHP value.
– jQuery includes a function (getJSON) to parse HTTP resource with JSON data.

JSON pseudo grammar
#json block: comma separated couple key: value
#key must be a string (example: “abc123”)
KEY_N = string
# value must be a native type, or array of values or json_block (recursive)
VALUE_N = string | number | true | false | null |
| [

Minimal example:
//note: “less/greater than” symbols are replaced with square brackets because of blogspot limitation

/* json.php – json generation */
print json_encode( array(
“title” => “products”,
“items”=> array(
result (“items” key contains an array with two values, each one is a block).
“items”: [ {“id”:”1″,”title”:”1st”}, {“id”:”2″,”title”:”2nd”} ]

/* page.html – call JSON resource (ajax with jQuery) and write into the DOM*/
[script src=“jquery-1.3.2.min.js” ][/script]
each(data.items, function(i,item){
div id=“main” ][/div]

div id=“main”
[h1]1[h1] [h4]1st[h4]
h1]2[h1] [h4]2nd[h4]

MySQL : version differences notes (draft)

Relevant features added in Mysql 4.0

  • FULLTEXT search
  • INNODB tables (and on [delete|update features]
  • UNION statement
  • TRUNCATE TABLE statement
  • multiple table delete and update
Relevant features added in Mysql 4.1

  • Subquery (nested query) supported
  • “CREATE table LIKE table 2” syntax supported
  • added storages:
    – EXAMPLE (for developers)
    – NBCLUSTER (table partitioned over many computers)
    – CSV (comma separated values storage)
    – BLACKHOLE (it doesn’t store data)
  • added command “HELP”
  • API improved (multiple statement in a single call)
  • GROUP_CONCAT() added
Relevant features added in Mysql 5.0

  • BIT data type
  • Math precision improved
  • SQLSTATE error message
  • TRIGGERS (limited support)
  • VARCHAR max length increased to 2^16 byte (64 Kb)
  • “greedy” optimizer, “merge index” to improve join performance
  • Improvement of “NOT IN”
  • VARCHAR more efficient
  • INNODB less disk space usage (-20%)
  • Added storages ARCHIVE and FEDERATED
Relevant features added in Mysql 5.1

  • Partitioning (tables in different locations)
  • plugin API to load/unload components at runtime
  • event scheduler (like cronotab)
  • customizable MySQL logs (to file or tables)
  • XML and XPath functions
Relevant features added in Mysql 6.0
  • UTF8 (4 bytes), UTF16 and UTF32
  • BACKUP_DATABASE and RESTORE statements (to backup)
  • performance optimization for subqueries and joins
  • transactional locks
  • LOAD_XML statement

INNODB storage engine: notes


  • transactions
  • row-level locking
  • foreign key constraints ! and behaviour

  • INNODB does NOT support FULLTEXT index (MyISAM does)
  • not initial value for auto_increment keys

array_walk example

bool array_walk ( array &$array , callback $funcname [, mixed $userdata ] )

/* example !!
* transform array with other arrays as elements into an array with simple elements
* array trasform !

$ar = array( array(1,2), array(10,20), array(100,200) );
sum(&$ar) //NOTE: Argument By reference
$ar = $ar[0]+$ar[1];

array_walk($ar, “sum”);

[0] => 3
[1] => 30
[2] => 300

PHP security: input validation and XSS

for lots of reasons, security included, it’s very important to validate all user input and protect our application from intentional or accidental wrong inputs.

First of all, here are some advices
  • don’t use register_globals ! A malicious user may change value of script variables simply modifying the query string
  • don’t use $_REQUEST: possibile loss of data. Use $_GET and $_POST

Number validation
use cast operator to validate numbers. If the malicious input is “‘); drop table users“, the casted (int) value will be zero.

When you use casting, remember the maximum size of int to prevent overflow. you may use (float) instead of (int).
Remember: the decimal separator is the point, not the period !
A numeric value with period (,) is not numeric, and a float casting will be delete the decimal part.
String validation
First of all, the input may contain stressed letters (French and Italian languages do, for example à,è,ì,ò and ù).
The stressed characters will be converted into the corresponding non-stressed characters (à->a, è->e, etc…).
To validate string inputs, use regular expressions !
ereg($patter, $string) // or eregi: same arguments but case insensitive
if (ereg(“^[0-9]{5}$”, $_POST[‘postcode’])!==false) { /*postcode valid*/ }
“^[0-9]{5}$” means: string that contain 5 characters, each must be a number
don’t forget “^” and “$” , or “a12345b” will be considered valid.
Use regular expression to validate various type of input: e-mails, URLs. For further details, examples and google !
File uploads
as second argument of
move_uploaded_file ( string $filename , string $destination )
use basename($_FILE[“fieldName”][“name”]) to increase security
$filename must be $_FILE[“fieldName”][“tmp_name”]
Don’t trust $_FILE[“fieldName”][“type”]
If you expect a image, use getimagesize(). If isn’t an image, the return value will be FALSE
If the size of the $destination file is different form the size of the temp file ($filename), delete it !!
Do not use magic quotes !
Magic quotes doesn’t escape correctly all the special characters !
it’s better to use specific db functions, such as
Pay attention to the current PHP configuration, you may do a stripslashes to $_GET data if the magic quotes are enabled. Use the get_magic_quotes_gpc()
Do not allow the user to modify serialized data !
A malicious user may be change and array with 100 elements a:100:{} to an array with millions of elements (it requires lots of memory).
If you need to pass serialized data, you should use a two-way cipher algorithm with key.
Cross site scripting allows users to insert malicious code in frontend via form submit. When the result page with the user data will be displayed (examples: weblog comments or site guestbook), the code will be executed or shown.
Examples of malicious inputs:
  • [? passthru(“rm -rf *”); ?]
  • [iframe src=”” … /]
Some tips:
  • Convert characters to html entities. the “less and greater than” will be converted in HTML entities preventing not-expected HTML formatting or PHP code execution
    pho function: htmlspecialchars() //converts “ampersand”, “double and single quote”, “less and greater than” into HTML entities
  • Pay attention to quotes or double quotes if you compose tag attributes with user’s data:
    print “[a href='{$_GET[‘link’]}’]text[/a]”;
    if $_GET[‘link’] is: #’ onclick=’alert(‘malicous js code’)’ title=’
    the result of the link will be execute a user-defined javascript
  • If the HTML tags are not allowed, you can use strip_tags() and remove all the tags from the user data. Note: strip_tags() does not convert special chars !
  • To only remove attributes to user submitted tags, use preg_replace()
  • If the user data is a URL, remember to check that it will not start with “javascript:” to prevent javascript code, or (better), parse with eregi()
  • to obtain a IP-based accesscontrol, you should also consider the proxy. If the user uses it, the real IP is contained in the variabile HTTP_X_FORWARDED_FOR, and validate it by using ip2long(), then long2ip() and check if the IP remain the same
  • HTTP_REFERER is not reliable, some browsers don’t send it

Design Pattern: Strategy

Strategy is a way to encapsulate, manage and interchange (also at runtime) algorithms.

In the following example, we have three classes (A,B and C) that implement an interface with the method f().
The class AlgoContainer must be initiated by passing the object (external instantiation) or the class name (internal instantation).

Interface StrategyInt
public function f();

class A implements StrategyInt {
public function f() { print "A:f()"; }

class B implements StrategyInt {
public function f() { print "B:f()"; }

class C implements StrategyInt {
public function f() { print "C:f()"; }

class AlgoContainer {
private $strategy;
private $name;
public function __construct($s){
if (is_object($s))
$this->strategy = $s;
$this->strategy = new $s();
public function doF() {

//Usage 1 (external instantiation):
$ac = new AlgoContainer(new A);
$ac-> doF();

//Usage 2 (internal instantiation):
$ac = new AlgoContainer("A");
$ac-> doF();

Design Pattern: Decorator

Decorator is similar to Proxy.

Basically, decorator is an extension (or wrapper) of the original class (component) and adds features.
A decorator contains a pointer to the component class (initialized by the constructor), and the methods of the component overridden.

class ImgComponent {
private $src;
private $alt;
public function __construct($name, $src) { /* assign to properties*/ };
public function getHTML() {
return "[ img src="{$this->src}" alt="{$this->alt}" /]";

Let’s write a decorator:

class ImgWithCaption extends imgComponent
private $caption;
private $imgComponent;
public function __construct(&$img, $caption) {
$caption->imgComponent = $caption;
$this->imgComponent = &$img;

public function getHTML() {
return "<div><div>{parent::getHTML()}</div>
<div> $caption</div></div>";