Thursday, March 31, 2011

javascript object oriented programming 3 - inheritance

inheritance - more details

Let's review the simple inheritance example in my last  blog:

//constructor method
function Person(name, sex) {
       this.name = name;
       this.sex = sex;
   }
//define Person prototype 
Person.prototype = {
       getName: function() {
           return this.name;
       },
       getSex: function() {
           return this.sex;
       }
}
//define an Employee constructor method
function Employee(name, sex, employeeID) {
    this.name = name;
    this.sex = sex;
    this.employeeID = employeeID;
}

Employee.prototype = new Person();
Employee.prototype.getEmployeeID = function() {
    return this.employeeID;
};
As we said, there are some problems in this inheritance. Let's address these problems one by one.
1. When we create the Employee constructor method and protoype, we also have to create a Person instance. It is not reasonable and not efficient.
To fix this issue, we should try to inherit the prototype only. We should put reusable properties and methods into prototype. Let's change our code:
Employee.prototype = Person.prototype;

In this way, every time we create a new Employee object, it can access any methods and properties in Person's prototype too. And we don't need to instance a Person object.

2. Another problem is Employee's prototype is completely re defined, this will cause Employee's constructor is referencing to the wrong object. Try the code below:


var e = new Employee('henry', 'm', 25);
console.log(e.constructor == Employee); //false
The constructor is not pointing to itself. To fix this issue, we simply change our code to this:
Employee.prototype = Person.prototype;
Employee.prototype.constructor = Employee.
3. Directly copying Person's prototype to Employee's prototype is easy and efficient. But it does bring some side effects. Employee's prototype is pointing to the same object, the Person's prototype, Employee's prototype properties and methods will complete override its parent object's prototype's same name properties and methods.
For example, if we also define a getName method in Employee's prototype:
Employee.prototype.getName = function(){return 'henry'};
var p = new Person('Jack', 'm');
p.getName(); //henry

To fix this issue, we must break the chain. We need to introduce an intermediary. We create an empty functoin F(){} first. Then we set its prototype to Person's prototype: F.prototype = Person.prototype. Now, let's see how we should do the inheritance:
function F(){};
F.prototype = Person.prototype;
Employee.prototype = new F();
Employee.prototype.constructor = Employee;

4. How to call parent object's method in child object? Javascript doesn't have someting like PHP's 'parent::' feature. There are several implementations for this. I just use a simple and traditional way: uber property. Finally the inheritance mechanism is:
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;

What is the uber? Let's change our Person's getName method:
getName: function() {
var parentName = '';
if (this.constructor.uber) {
if (this.constructor.uber.getName) {
         parentName = this.getName();
}
   }
   return this.name + "'s parent is " + parentName;
}

Monday, March 28, 2011

javascript object oriented programming 2: inheritance

Inheritance - simple way

First, we need to know prototype. We can think prototype as a template. In javascript, everything is an object, every object has its own prototype.

A simple inheritance in javascript:
//constructor method
function Person(name, sex) {
       this.name = name;
       this.sex = sex;
   }
//define Person prototype 
Person.prototype = {
       getName: function() {
           return this.name;
       },
       getSex: function() {
           return this.sex;
       }
}
//define an Employee constructor method
function Employee(name, sex, employeeID) {
    this.name = name;
    this.sex = sex;
    this.employeeID = employeeID;
}
// Make Employee.prototype link to an instance of Person
// The Person instance can call the methods in Person prototype, so Employee's instances can access methods and properties of Person prototype as well.
Employee.prototype = new Person();
Employee.prototype.getEmployeeID = function() {
    return this.employeeID;
};
However, there are some problems with such a simple inheritance.
1. When we create the Employee constructor method and protoype, we also create a Person instance. That is not reasonable.
2. Employee's constructor method cannot access its parent/super class Person's constructor method.
3. Employee's constructor is pointing to the wrong place.
We will see how to address all these problems in my next blog.

Pass parameters to a function/expression called within setTimeout

javascript's setTimeout(aFunction,  timeout); Sometimes we need to pass parameters to aFunction. To do this, we must use 'closure': setTimeout(funciton(){aFunction(parameter)}, timeout);

Saturday, March 26, 2011

javascript object oriented programming 1:create objects

how to create objects One way to create an object:
var ship = {
     wings: 'wings',
     body: 'body',
     jet: 'jet',
     guns: 'guns'
};
Now, we have a ship object. This object has 4 properties:wings,body,jet,guns. An object property can contain a function, we call it a method.
var ship = {
     wings: 'wings',
     body: 'body',
     jet: 'jet',
     guns: 'guns',
     fire = function () {
         return 'start to fire';
     }
};
Now our ship object has a method fire. Accessing Object's properties We can access an object's properties by using either square bracket notation or dot notation. For example: ship.wings or ship['wings']. Dot notation is easier to read and write. Accessing a non-existing property returns 'undefined': ship.tail. Calling Object's methods ship.fire() invokes the fire function and returns the value 'start to fire'. Calling a non-existing method causes error: ship.move(). Using keyword 'this' Let 's add a method to our ship.
var ship = {
     wings: 'wings',
     body: 'body',
     jet: 'jet',
     guns: 'guns',
     fire = function () {
         return 'start to fire';
     }
     getGuns = function() {
         return this.guns;
     }
};
'this' actually refers to this object or current object. Another way to create objects is to use constructor function. This way is actually more familiar to people with java or php5 background.
function Ship(model) {
 this.model = model;
 this.wings = 'the wings';
 this.body  = 'the body';
 this.jet   = 'the jet';
 this.guns  = 'the guns';
 this.fire  = function() {
  return this.guns + ' start to fire';
 };
 this.getModel = function(){return this.model};
}
var shipOne = new Ship(1);
var shipTwo = new Ship(2);
We can also create a new object in this way, although it looks a little wierd:
var shipOne = new Ship(1);
var shipTwo = new shipOne.constructor(2);
This works because constructor property refers to a function and we can call this function to return a new object. We use instanceof to tell an object's type: if (shipTwo instanceof Ship){}; In javascript, object is passed by reference, same to most of other OOP langauges. Global Object In javascript, the host environment provides a global object and all global variables are actually properties of the global object. If your host environment is the web browser, the global object is called window.

Wednesday, March 23, 2011

PHP singleton inheritance

Prior to PHP 5.3, here is how we implement singleton:
class Service
{
private static $_instance = null;
private function __construct(){};
private function __clone(){};

public static function getInstance()
{
if (self::$_instance === null) {
self::$_instance = new self;
}
return self::$_instance;
}
}

However, we all know that it is very tricky if we want to extend/inherit this singleton class.
PHP 5.3 introduces LSB, which stands for Late Static Binding. It solves our problem of inheriting a singleton class. In PHP 5.3, we implement singleton in this way
class Service
{
private static $_instance = null;
private function __construct(){};
private function __clone(){};

public static function getInstance()
{
if (static::$_instance === null) {
static::$_instance = new static;
}
return static::$_instance;
}
}

Simply replace the 'self' keyword with 'static', we can inherit a singleton just like usual inheritance.

The difference is self keyword is bound to the referenced property or method at compile time. The self keyword points to the containing class and is unaware of subclasses. The static keyword forces PHP to bind to the code implementation at the latest possible moment.

how to use left join in mysql

Let's setup two tables for our experiment.

create table student(id int primary key auto_increment, name varchar(255));

insert into student (name) values('henry'),('jack'),('alice');

create table class_a(id int primary key auto_increment, student_id int, registered_datetime datetime);

insert into class_a(student_id, registered_datetime) values(1,now());


We use a simple left join to see the result:


select s.*,c.id as class_id from student s left join class_a c on s.id = c.student_id;
+----+-------+----------+
| id | name | class_id |
+----+-------+----------+
| 1 | henry | 1 |
| 2 | jack | NULL |
| 3 | alice | NULL |
+----+-------+----------+


We can see that left join returns all rows from the left table(student) even the student may not have a match in the right table(class_a). In this case, any c

So thing are quite obvious now. If we only want to get the students that are not registered in class_a, we can simply add a filter for left join:

select s.*,c.id as class_id from student s left join class_a c on s.id = c.student_id where c.id is null;
+----+-------+----------+
| id | name | class_id |
+----+-------+----------+
| 2 | jack | NULL |
| 3 | alice | NULL |
+----+-------+----------+

Tuesday, March 22, 2011

phpundercontrol build success even with php codesniffer violation error

This issue had been confusing me for a while, cause it seems phpundercontrol will build fail only when phpunit failed.

Later i check the difference in the build.xml between PHPUnit target and CodeSniffer target. I found PHPUnit is setup like this '' while codesniffer doesn't have 'failonerror="on"', after i add it to codesniffer target, phpundercontrol will build fail if there is any codesniffer violation.

Friday, March 18, 2011

VIM IDE for PHP

1. install the project plugin for VIM. Here is the link: http://www.vim.org/scripts/script.php?script_id=69

2.
sudo aptitude install exuberant-ctags
cd ~
wget http://rafal.zelazko.info/wp-content/uploads/ftp/vim-custom.tgz
tar -xvzf vim-custom.tgz -C ~

Link for step 2: The link: http://rafal.zelazko.info/2010/04/18/vim-php-symfony/

Tuesday, March 15, 2011

install mongodb php driver on windows

Download the correct driver for your environment from http://github.com/mongodb/mongo-php-driver/downloads. For my case, i download "mongo-1.1.4.zip — All of the Windows build for the 1.1.4 release"

Unzip the package. There are several entries, for example:

mongo-1.1.4-php5.2vc6
mongo-1.1.4-php5.2vc6ts
...

Based on the official document, vc6 is for Apache (vc9 is for IIS). 'ts' means Thread Save. Thread safe is for running PHP as an Apache module (typical installation), non-thread safe is for CGI.

So i copy the mongo.dll from the mongo-1.1.4-php5.2vc6ts folder to my php/ext/ folder. And then update my php.ini by adding extension=php_mongo.dll

Finally, restart my apache and then have a look at phpinfo(), i can find a mongo section. It is done

Monday, March 14, 2011

PHP case insensitive file_exists

We know that PHP's file_exists is case sensitive on *nix system. However, i've been through a situation that i need this function case insensitive. For example, there exists a file: /var/www/project/public/images/company/logo.png. In Url it will be http://project.com/images/company/logo.png. Now, if the html code is < img src = "http://project.com/images/Company/logo.PNG" > or even < img src = "images/Company/Logo.png" >, it works fine on windows. But on linux, it won't work. My task is, i need to allow users to export some special html pages in a zip archive so that they can browse them offline. If the html pages contain image links, the images will be exported too if they exists. Well, as you can imagine, it is pretty much like the "Save as..." function when you right click your mouse on a web page.

I can't find a perfect solution. Some solutions only allow you to have file name case insensitive, and you still have to ensure the directory name of the file must be correct in case sensitive way. Some solutions use customized glob() functions that i can't easily understand. So i finally decided to implement my own solution based on my situation.

Here is my thought: some specific path is defined in your config file and you can never get it wrong. For example, you may have config settings like this:
//paths
$conf['root_dir'] = dirname(__FILE__) . '/..';
$conf['public'] = $conf['root_dir'] . '/public';
$conf['images'] = $conf['public'] . '/images';
So, the only uncertain part is the sub folders and files under the 'images' folder. Here is how i implement my case insensitive file_exists():
//$filename is the full path file name, like /var/www/project/public/images/Company/Logo.PNG
//$baseDir is the base directory that you can't get it wrong, here it might be /var/www/project/public/images/
//return: the function return false if file NOT exists,
//it will return the correct case sensitive path if the file exists in case insensitive way.

function caseInsensitiveFileExists($filename, $baseDir)
{
//well if file_exists() can find the $filename, we can return
if(file_exists($filename) {
return $filename;
}
//we only do this on *nix system, on windows, we don't have to worry about case sensitive issue.
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($baseDir));
foreach ($iterator as $value) {
if ($value->isFile()) {
$filePath = $value->getPathname();
//if they are equals, we know the $filename exists.
if (strotolower(filePath) == strtolower($filename)) {
return filePath;
}
}
}
}
return false;
}


How is this function's performance if we have huge number of files and folders under $baseDir? I haven't really tested this issue yet. At the moment this function serves my purpose very well. However, i'm looking forward to any other decent implementation.

Thursday, March 10, 2011

a difference i didn't expect between php 5.2 & php 5.3 (overriding abstract function)

Here is my code:

abstract class App_Daos_Abstract
{
abstract public function buildModel($result);
}

class UserDao extends App_Daos_Abstract
{
public function buildModel($result = null)
{
}
}

If i run this code on php 5.2.14 + windows, i will get "Fatal error: Declaration of news::buildModel() must be compatible with that of App_Daos_Abstract::buildModel()".

However, if i run the code on php 5.3 + ubuntu, everything is fine.

I don't think windows or ubuntu matter. I think this is a difference between PHP 5.2 and PHP 5.3. So even at this point PHP 5.3 is more closer to JAVA.