Friday, March 30, 2007

ASCII码


Wednesday, March 28, 2007

HTTP_REFERER问题

点击某个链接经过跳转页后到达目标页面时,目标页面取到的HTTP_REFERER_URL为点击链接所在页面的URL,而不是跳转页。也就是说直接从浏览器里进去是跳转页,跳到目标页面时,是取不到HTTP_REFERER的。
另:点Flash页面过来取不到HTTP_REFERER_URL。

Tuesday, March 27, 2007

Why not to use Magic Quotes

Portability

Assuming it to be on, or off, affects portability. Use get_magic_quotes_gpc() to check for this, and code accordingly.

Performance

Because not every piece of escaped data is inserted into a database, there is a performance loss for escaping all this data. Simply calling on the escaping functions (like addslashes()) at runtime is more efficient.

Although php.ini-dist enables these directives by default, php.ini-recommended disables it. This recommendation is mainly due to performance reasons.

Inconvenience

Because not all data needs escaping, it's often annoying to see escaped data where it shouldn't be. For example, emailing from a form, and seeing a bunch of \' within the email. To fix, this may require excessive use of stripslashes().

sar sysstat


[david@localhost soft]# rpm -ivh sysstat-5.0.5-1.src.rpm

[david@localhost soft]# rpmbuild --ba /usr/src/redhat/SPECS/sysstat.spec

[david@localhost soft]# ll /usr/src/redhat/RPMS/i386/sysstat-5.0.5-1.i386.rpm
-rw-r--r-- 1 root root 105209 Mar 27 17:23 /usr/src/redhat/RPMS/i386/sysstat-5.0.5-1.i386.rpm
[david@localhost soft]# rpm -ivh /usr/src/redhat/RPMS/i386/sysstat-5.0.5-1.i386.rpm
Preparing... ########################################### [100%]
1:sysstat ########################################### [100%]
[david@localhost soft]# sa
sa sasl2-static-mechlist saslpasswd2
safe_finger saslauthd sasl-sample-client
sar saslauthd1-checkpass sasl-sample-server
sasl2-sample-client sasldblistusers savecore
sasl2-sample-server sasldblistusers2
sasl2-shared-mechlist saslpasswd
[david@localhost soft]# sar --help
sysstat version 5.0.5
(C) Sebastien Godard
Usage: sar [ options... ] [ [ ] ]
Options are:
[ -A ] [ -b ] [ -B ] [ -c ] [ -d ] [ -H ] [ -h ] [ -i ] [ -q ]
[ -r ] [ -R ] [ -t ] [ -u ] [ -v ] [ -V ] [ -w ] [ -W ] [ -y ]
[ -I { | SUM | ALL | XALL } ] [ -P { | ALL } ]
[ -n { DEV | EDEV | SOCK | FULL } ]
[ -x { | SELF | ALL } ] [ -X { | SELF | ALL } ]
[ -o [ ] | -f [ ] ]
[ -s [ ] ] [ -e [ ] ]
[david@localhost soft]# sar -u 1 3
Linux 2.4.20-8 (intel) 08/30/2005

05:46:16 PM CPU %user %nice %system %idle
05:46:17 PM all 0.00 0.00 1.00 99.00
05:46:18 PM all 0.00 0.00 0.00 100.00
05:46:19 PM all 0.00 0.00 0.00 100.00

利用$argv接收命令行参数

PHP 的二进制文件(php.exe 文件)及其运行的 PHP 脚本能够接受一系列的参数。PHP 没有限制传送给脚本程序的参数的个数(外壳程序对命令行的字符数有限制,但通常都不会超过该限制)。传递给脚本的参数可在全局变量 $argv 中获取。该数组中下标为零的成员为脚本的名称(当 PHP 代码来自标准输入获直接用 -r 参数以命令行方式运行时,该名称为“-”)。另外,全局变量 $argc 存有 $argv 数组中成员变量的个数(而非传送给脚本程序的参数的个数)。

只要传送给脚本的参数不是以 - 符号开头,就无需过多的注意什么。向脚本传送以 - 开头的参数会导致错误,因为 PHP 会认为应该由它自身来处理这些参数。可以用参数列表分隔符 -- 来解决这个问题。在 PHP 解析完参数后,该符号后所有的参数将会被原样传送给脚本程序。

# 以下命令将不会运行 PHP 代码,而只显示 PHP 命令行模式的使用说明:
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]

# 以下命令将会把“-h”参数传送给脚本程序,PHP 不会显示命令行模式的使用说明:
$ php -r 'var_dump($argv);' -- -h
array(2) {
[0]=>
string(1) "-"
[1]=>
string(2) "-h"
}

除此之外,还有另一个方法将 PHP 用于外壳脚本。可以在写一个脚本,并在第一行以 #!/usr/bin/php 开头,在其后加上以 PHP 开始和结尾标记符包含的正常的 PHP 代码,然后为该文件设置正确的运行属性(例如:chmod +x test)。该方法可以使得该文件能够像外壳脚本或 PERL 脚本一样被直接执行。 #!/usr/bin/php
<?php
var_dump($argv);
?>

假设改文件名为 test 并被放置在当前目录下,可以做如下操作:


$ chmod +x test
$ ./test -h -- foo
array(4) {
[0]=>
string(6) "./test"
[1]=>
string(2) "-h"
[2]=>
string(2) "--"
[3]=>
string(3) "foo"
}

正如所看到的,在向该脚本传送以 - 开头的参数时,脚本仍然能够正常运行。

<?php
echo $argc . "\n";
var_dump($argv);
?>

H:\workspace>php test.php arg1 arg2
3
array(3) {
[0]=>
string(8) "test.php"
[1]=>
string(4) "arg1"
[2]=>
string(4) "arg2"
}

Monday, March 26, 2007

Ruby Calendar


require 'date'
month = ARGV[0] ? ARGV[0].to_i : Date.today.mon
year = ARGV[1] ? ARGV[1].to_i : Date.today.year

month_names = %w{January February March April May June July August September
October November Decemeber}

dow_banner = %{Su Mo Tu We Th Fr Sa}
days_in_mon = Date.civil(year, month, -1).day

# Print title:
print " " * ((dow_banner.length -
(year.to_s.length + 1 + month_names[month - 1].length)) / 2)
print "#{month_names[month - 1]} #{year}\n"
print "#{dow_banner}\n"

dow_counter = Date.civil(year, month, 1).wday

print " " * 3 * dow_counter

(1..days_in_mon).each { |i|
if i < 10
print " #{i}"
else
print "#{i}"
end
print " "
dow_counter += 1
if dow_counter % 7 == 0
print "\n"
end
}
print "\n"

#civil(y=-4712, m=1, d=1, sg=ITALY)
# Date.civil # class method
#Create a new Date object for the Civil Date specified by year y, month m, .
#and day-of-month d
#m and d can be negative, in which case they count backwards from the end of the year
#and the end of the month respectively. No wraparound is performed, however,
#and invalid values cause an ArgumentError to be raised. can be negative
#
#y defaults to -4712, m to 1, and d to 1; this is Julian Day Number day 0.
#
#sg specifies the Day of Calendar Reform.
#某年某月有多少天数?如 Date.civil(2008, 2, -1).day #=> 29

return a reference from a function

To return a reference from a function, you have to use the reference operator & in both the function declaration and when assigning the returned value to a variable:

Example 17-13. Returning a reference from a function


<?php
function &returns_reference()
{
return $someref;
}

$newref =& returns_reference();
?>

Sunday, March 25, 2007

variable variables

将某变量值作为变量名时需要注意在结合array使用时的一个问题:
In order to use variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.

References with global and static variables

The Zend Engine 1, driving PHP 4, implements the static and global modifier for variables in terms of references. For example, a true global variable imported inside a function scope with the global statement actually creates a reference to the global variable. This can lead to unexpected behaviour which the following example address.


<?php
function global_ref()
{
//在function中用global,static引入的变量其实是对此变量建立了一个引用reference,
//在function执行完之后会对应变量的值不会丢失。
global $obj;
var_dump($obj);
echo "<br/>";
$obj = &new stdclass;
}
global_ref();
global_ref();
?>

<br/>

<?php
function global_noref()
{
global $obj;
var_dump($obj);
echo "<br/>";
if(!isset($obj))
{
$obj = new stdclass;
}
else
{
echo "has set variable: \$obj. <br/>";
}
}
global_noref();
global_noref();
?>
A similar behaviour applies to the static statement. References are not stored statically:

<?php
function static_ref()
{
static $sta;
var_dump($sta);
if(!isset($sta))
{
$sta = &new stdclass;
}
$sta->num++;
}
static_ref();
static_ref();
static_ref();
?>

<?php
function static_noref()
{
static $sta;
var_dump($sta);
echo "<br>";
if(!isset($sta))
{
$sta = new stdclass;
}
$sta->num++;
}
static_noref();
static_noref();
static_noref();
?>

Using the global keyword inside a function to define a variable is essentially the same as passing the variable by reference as a parameter:

somefunction(){
global $var;
}

is the same as:

somefunction(& $a) {

}

The advantage to using the keyword is if you have a long list of variables needed by the function - you dont have to pass them every time you call the function.

Converting to object(String,Array)

If an object is converted to an object, it is not modified. If a value of any other type is converted to an object, a new instance of the stdClass built in class is created. If the value was NULL, the new instance will be empty. Array converts to an object with properties named by array keys and with corresponding values. For any other value, a member variable named scalar will contain the value.


<br/>
<?php
$bar = "boo";
$obj = (object) $bar;
var_dump($obj);// object(stdClass)#1 (1) { ["scalar"]=> string(3) "boo" }
echo "<br/>";

$arr = array('x' => 1, 'y' => 2, 'z' => 3);

$obj_arr = (object) $arr;
var_dump($arr); //array(3) { ["x"]=> int(1) ["y"]=> int(2) ["z"]=> int(3) }
var_dump($obj_arr); //object(stdClass)#2 (3) { ["x"]=> int(1) ["y"]=> int(2) ["z"]=> int(3) }
echo "<br/>";

$var = 'x';
echo $obj_arr->x; // 1
echo "<br/>";
echo $obj_arr->$var; // 1
?>

Pseudo-types used in this documentation

mixed
mixed indicates that a parameter may accept multiple (but not necessarily all) types.

gettype() for example will accept all PHP types, while str_replace() will accept strings and arrays.

number

number indicates that a parameter can be either integer or float.

callback

Some functions like call_user_func() or usort() accept user defined callback functions as a parameter. Callback functions can not only be simple functions but also object methods including static class methods.

A PHP function is simply passed by its name as a string. You can pass any builtin or user defined function with the exception of array(), echo(), empty(), eval(), exit(), isset(), list(), print() and unset().

A method of an instantiated object is passed as an array containing an object as the element with index 0 and a method name as the element with index 1.

Static class methods can also be passed without instantiating an object of that class by passing the class name instead of an object as the element with index 0.

Apart common user-defined function, create_function() can be used to create an anonymous callback function.

Example 11-13. Callback function examples


<?php
// An example callback function
function my_callback_function() {
echo 'hello world!';
}

// An example callback method
class MyClass {
function myCallbackMethod() {
echo 'Hello World!';
}
}

// Type 1: Simple callback
call_user_func('my_callback_function');

// Type 2: Static class method call
call_user_func(array('MyClass', 'myCallbackMethod'));

// Type 3: Object method call
$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));
?>

Saturday, March 24, 2007

Using static variables

Another important feature of variable scoping is the static variable. A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope.
static variable只作用于本地function内,在程序执行完后此变量值不会丢失,此方法再次调用,将使用上次操作完成后的此变量值。在singleton pattern里,也是利用static variable,使程序在运行期间只产生一个实例。


<?php
function Test_static_var()
{
static $a = 0;
echo $a, "<br />";
$a++;
}
Test_static_var();
Test_static_var();
Test_static_var();
?>
<?php
function Test()
{
static $count = 0;

$count++;
echo $count;
for($i = 0; $i < $count; $i++)
{
echo " ";
}
echo " before recursive <br />\n";
if ($count < 10) {
Test();
}
$count--;
echo $count;
for($i = 0; $i < $count; $i++)
{
echo " ";
}
echo " after recusive <br />\n";
}
Test();
// 1 before recursive
// 2 before recursive
// 3 before recursive
// 4 before recursive
// 5 before recursive
// 6 before recursive
// 7 before recursive
// 8 before recursive
// 9 before recursive
// 10 before recursive
// 9 after recusive
// 8 after recusive
// 7 after recusive
// 6 after recusive
// 5 after recusive
// 4 after recusive
// 3 after recusive
// 2 after recusive
// 1 after recusive
// 0 after recusive
?>

The global keyword


<?php
$a = 1;
$b = 2;
$GLOBALS['c'] = 3;
echo $c, "<br>";
$d = 4;

function Sum()
{
global $a, $b;

$b = $a + $b + $GLOBALS['c'] + $GLOBALS['d'];
}

Sum();
echo $b;
?>

The above script will output "3", "10". By declaring $a and $b global within the function, all references to either variable will refer to the global version. There is no limit to the number of global variables that can be manipulated by a function.

A second way to access variables from the global scope is to use the special PHP-defined $GLOBALS array.

The $GLOBALS array is an associative array with the name of the global variable being the key and the contents of that variable being the value of the array element. Notice how $GLOBALS exists in any scope, this is because $GLOBALS is a superglobal.

Returning References

Returning by-reference is useful when you want to use a function to find which variable a reference should be bound to. Do not use return-by-reference to increase performance, the engine is smart enough to optimize this on its own. Only return references when you have a valid technical reason to do it! To return references, use this syntax:


<?php
function &find_var($param)
{
/* ...code... */
return $found_var;
}

$foo =& find_var($bar);
$foo->x = 2;
?>

In this example, the property of the object returned by the find_var function would be set, not the copy, as it would be without using reference syntax.
Note: Unlike parameter passing, here you have to use & in both places - to indicate that you return by-reference, not a copy as usual, and to indicate that reference binding, rather than usual assignment, should be done for $foo.

Note: If you try to return a reference from a function with the syntax: return ($found_var); this will not work as you are attempting to return the result of an expression, and not a variable, by reference. You can only return variables by reference from a function - nothing else. E_NOTICE error is issued since PHP 4.4.0 and PHP 5.1.0 if the code tries to return a dynamic expression or a result of the new operator.

While trying to create a function to return Database connection objects, it took me a while to get this right:

<?php

class TestClass
{
var $thisVar = 0;

function TestClass($value)
{
$this->thisVar = $value;
}

function &getTestClass($value)
{
static $classes;

if (!isset($classes[$value]))
{
$classes[$value] = new TestClass($value);
}

return $classes[$value];
}
}

echo "<pre>";

echo "Getting class1 with a value of 432\n";
$class1 =& TestClass::getTestClass(432);
echo "Value is: " . $class1->thisVar . "\n";

echo "Getting class2 with a value of 342\n";
$class2 =& TestClass::getTestClass(342);
echo "Value is: " . $class2->thisVar . "\n";

echo "Getting class3 with the same value of 432\n";
$class3 =& TestClass::getTestClass(432);
echo "Value is: " . $class3->thisVar . "\n";

echo "Changing the value of class1 to 3425, which should also change class3\n";
$class1->thisVar = 3425;

echo "Now checking value of class3: " . $class3->thisVar . "\n";

?>

Which outputs:

Getting class1 with a value of 432
Value is: 432
Getting class2 with a value of 342
Value is: 342
Getting class3 with the same value of 432
Value is: 432
Changing the value of class1 to 3425, which should also change class3
Now checking value of class3: 3425

Note that PHP syntax is different from C/C++ in that you must use the & operator in BOTH places, as stated by the manual. It took me a while to figure this out.

What References Are and What Reference Do

References in PHP are a means to access the same variable content by different names. They are not like C pointers; instead, they are symbol table aliases. Note that in PHP, variable name and variable content are different, so the same content can have different names. The most close analogy is with Unix filenames and files - variable names are directory entries, while variable contents is the file itself. References can be thought of as hardlinking in Unix filesystem.

PHP references allow you to make two variables to refer to the same content. Meaning, when you do:


<?php
$a =& $b;
?>

it means that $a and $b point to the same content.
Note: $a and $b are completely equal here, that's not $a is pointing to $b or vice versa, that's $a and $b pointing to the same place.
Unsetting References

When you unset the reference, you just break the binding between variable name and variable content. This does not mean that variable content will be destroyed. For example:

<?php
$a = 1;
$b =& $a;
unset($a);
// OR
$a = 1;
$b =& $a;
$b = NULL;
?>

won't unset $b, just $a.
Again, it might be useful to think about this as analogous to Unix unlink call.

$thisIn an object method, $this is always a reference to the caller object.

PHP5 Exceptions

PHP 5 has an exception model similar to that of other programming languages. An exception can be thrown, and caught ("catched") within PHP. Code may be surrounded in a try block, to facilitate the catching of potential exceptions. Each try must have at least one corresponding catch block. Multiple catch blocks can be used to catch different classes of exeptions. Normal execution (when no exception is thrown within the try block, or when a catch matching the thrown exception's class is not present) will continue after that last catch block defined in sequence. Exceptions can be thrown (or re-thrown) within a catch block.

When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block. If an exception is not caught, a PHP Fatal Error will be issued with an "Uncaught Exception ..." message, unless a handler has been defined with set_exception_handler().


<?php
try
{
throw new Exception("throw error from try{ }.");
// Code following an exception is not executed.
echo 'Never executed';
}
catch(Exception $e)
{
echo "error msg: <br>";
echo $e->getMessage();
}

?>
<?php
class Exception
{
protected $message = 'Unknown exception'; // exception message
protected $code = 0; // user defined exception code
protected $file; // source filename of exception
protected $line; // source line of exception

function __construct($message = null, $code = 0);

final function getMessage(); // message of exception
final function getCode(); // code of exception
final function getFile(); // source filename
final function getLine(); // source line
final function getTrace(); // an array of the backtrace()
final function getTraceAsString(); // formated string of trace

/* Overrideable */
function __toString(); // formated string for display
}
?>

Object cloning

Creating a copy of an object with fully replicated properties is not always the wanted behavior. A good example of the need for copy constructors, is if you have an object which represents a GTK window and the object holds the resource of this GTK window, when you create a duplicate you might want to create a new window with the same properties and have the new object hold the resource of the new window. Another example is if your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.
An object copy is created by using the clone keyword (which calls the object's __clone() method if possible). An object's __clone() method cannot be called directly.
$copy_of_object = clone $object;
When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. Any properties that are references to other variables, will remain references. If a __clone() method is defined, then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed.


<?php
class SubObject
{
static $instances = 0;
public $instance;

public function __construct() {
$this->instance = ++self::$instances;
}

public function __clone() {
$this->instance = ++self::$instances;
}
}

class MyCloneable
{
public $object1;
public $object2;

function __clone()
{
// Force a copy of this->object, otherwise
// it will point to same object.
$this->object1 = clone($this->object1);
}
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;


print("Original Object:\n");
print_r($obj);

print("Cloned Object:\n");
print_r($obj2);

?>

Factory of Patterns

Patterns

Patterns are ways to describe best practices and good designs. They show a flexible solution to common programming problems.

Factory

The Factory pattern allows for the instantiation of objects at runtime. It is called a Factory Pattern since it is responsible for "manufacturing" an object. A Parameterized Factory receives the name of the class to instantiate as argument.


<?php
class Factory
{
public static function driver($class_name)
{
if(include_once($class_name . ".php"))
{
return new $class_name;
}
else
{
// throw new Exception ("no such {$class_name}");
}
}
}

$a = Factory::driver('caller');
var_dump($a);
// $v = Factory::driver('mysql');
?>

Singleton

The Singleton pattern applies to situations in which there needs to be a single instance of a class. The most common example of this is a database connection. Implementing this pattern allows a programmer to make this single instance easily accessible by many other objects.


<?php
class Singleton
{
private static $instance;

private function __construct()
{
echo "it's construct.<br />";
}

// prevend users to clone the instance.
private function __clone()
{
trigger_error("error.<br/>", E_USER_ERROR);
}

public static function singleton()
{
if(!isset(self::$instance))
{
$class_name = __CLASS__;
self::$instance = new $class_name;
}
return self::$instance;
}

public function wow()
{
echo "<br/>", "it works, wow!", "<br/>";
}
}
// $s = new Singleton(); //Fatal error: Call to private Singleton::__construct() from invalid context
$s = Singleton::singleton();
var_dump($s);
$s->wow();
?>

Member overloading

Overloading

Both method calls and member accesses can be overloaded via the __call, __get and __set methods. These methods will only be triggered when your object or inherited object doesn't contain the member or method you're trying to access. All overloading methods must not be defined as static. In PHP 5.0.x, all overloading methods must be defined as public.

Since PHP 5.1.0 it is also possible to overload the isset() and unset() functions via the __isset and __unset methods respectively.
Member overloading
void __set ( string name, mixed value )
mixed __get ( string name )
bool __isset ( string name )
void __unset ( string name )
Class members can be overloaded to run custom code defined in your class by defining these specially named methods. The $name parameter used is the name of the variable that should be set or retrieved. The __set() method's $value parameter specifies the value that the object should set the $name.


<?php
class Setter
{
public $n = 1;
private $array_x = array('x' => 1, 'y' => 2, 'z' => 3);

private function __get($var)
{
echo "Getting {$var}: <br />";
if(isset($this->array_x[$var]))
{
return $this->array_x[$var] . "<br/>";
}
else
{
echo "Nothing get {$var} in array_x. <br />";
}
}

private function __set($name, $value)
{
echo "Setting {$value} to {$name}. <br/>";
if(isset($this->array_x[$name]))
{
$this->array_x[$name] = $value;
}
else
{
echo "{$name} Nothing find in array_x.<br/>";
}
}

private function __isset($name)
{
echo "isset {$name} ? ";
if(isset($this->array_x[$name]))
{
echo "Yes.<br/>";
}
else
{
echo "No.<br/>";
}
}

private function __unset($name)
{
echo "unset {$name} <br/>";
unset($this->array_x[$name]);
}
}
$s = new Setter();
echo $s->x;
echo $s->y;
$s->y = 100;
echo $s->y;
isset($s->x);
isset($s->a);
// echo isset($s->n);
$s->z;
unset($s->z);
isset($s->z);
?>

Method overloading

mixed __call ( string name, array arguments )

Class methods can be overloaded to run custom code defined in your class by defining this specially named method. The $name parameter used is the name as the function name that was requested to be used. The arguments that were passed in the function will be defined as an array in the $arguments parameter. The value returned from the __call() method will be returned to the caller of the method.


<?php
class Caller
{
private $x = array(1, 3, 5, 7, 9);

private function __call($func, $args)
{
echo "call missing method: {$func}<br>";
echo "<pre>";
print_r($args);
echo "</pre>";
return $this->x;
}
}

$c = new Caller();
$rs = $c->test(1, 3, 'test', 'array', 'args');
var_dump($rs);
?>

Object Interfaces

Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.
Interface里只要指明有哪些方法,这些方法是在class中实现,interface本身不需要对这些方法处理实现。
Interfaces are defined using the interface keyword, in the same way as a standard class, but without any of the methods having their contents defined.

All methods declared in an interface must be public, this is the nature of an interface.
在Interface里定义的方法必须都是public的,这是Interface的特点。在abstract class 中方法可以是其他二种属性。
implements

To implement an interface, the implements operator is used. All methods in the interface must be implemented within a class; failure to do so will result in a fatal error. Classes may implement more than one interface if desired by separating each interface with a comma.
Note: A class cannot implement two interfaces that share function names, since it would cause ambiguity.
class 实现一个interface用implements操作符,Interface中所有定义的方法在class中都必须实现,这点与abstract class 一样,如果class中有个方法没有实现的话会报错,错误性质与abstract class一样。
可以在同一个class实现多个interface,用“,”隔开interface。


<?php
interface anInterface
{
public function getVar($name, $age);
public function getHtml($html);
}

class ImplementInterface implements anInterface
{
public function getVar($name, $age)
{
echo "name is: {$name}", " age is : {$age}", "<br>";
}
public function getHtml($html)
{
echo "<pre>";
print_r($html);
echo "</pre>";
}
}

$i = new ImplementInterface();
$i->getVar("yu", 29);
$i->getHtml("<a href='#'> test a href </a>");
?>

定义一个interface一般习惯以小写字母开始,命名同变量命名,class 和 abstract class 定义是名字首字母习惯大写开始。

Class Abstraction

PHP 5 introduces abstract classes and methods. It is not allowed to create an instance of a class that has been defined as abstract. Any class that contains at least one abstract method must also be abstract.Methods defined as abstract simply declare the method's signature they cannot define the implementation.
class中包括一个abstract方法以上, 则此class也为abstratct class。Abstract method只是在abstract class 声明一下,并确定此method的visibility,并不具体实现这些方法的功能。这些是在继承类subclass中实现。

When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child; additionally, these methods must be defined with the same (or weaker) visibillity. For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public.


<?php
abstract class AbstractClass
{
abstract protected function getValue();
abstract public function addPrefix($prefix);

public function putOut()
{
echo "<br>", $this->getValue(), "<br>";
}
}

class ConcreteClass extends AbstractClass
{
public function getValue()
{
echo "<br>", "Concrete Class.", "<br>";
}
// Fatal error: Class ConcreteClass contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (AbstractClass::addPrefix)
// Fatal error: Access level to ConcreteClass::addPrefix() must be public (as in class AbstractClass)
public function addPrefix($prefix)
{
echo "<br>", "{$prefix}Concrete Class.", "<br>";
}
}

$c = new ConcreteClass();
$c->putOut();
$c->addPrefix("yu_");
?>

PHP5 static property and static function


<?php
class Visibility
{
public $a = "a";
// var is synmic of public.
protected $b = "b";
private $c = "c";
const T = "const";
public static $s = "static";

public function public_func()
{
echo "public function";
echo "<br>";
}

protected function protected_func()
{
echo "protected function";
echo "<br>";
}

private function private_func()
{
echo "private function.";
echo "<br>";
}

public function static_var()
{
echo self::$s;
echo " self::\$s<br><br>";
}

public static function static_func()
{
echo "static function.";
echo "<br>";
echo "can't use \$this.";
echo "<br>";
// echo $this->a;
// Fatal error: Using $this when not in object context
}
}

$v = new Visibility();
echo $v->a;
// echo $v->b; // Fatal error
// echo $v->c; // Fatal error
echo "<br>";
$v->public_func();
// $v->protected_func(); // Fatal error
// $v->private_func(); // Fatal error
// echo Visibility::$a;
// Fatal error: Access to undeclared static property: Visibility::$a
echo Visibility::$s;
echo "<br>";
// echo Visibility::s; //Undefined class constant 's'
echo Visibility::T;
echo "<br>";
echo $v->static_var();
// echo $v->s; // output nothing.
// Static properties cannot be accessed through the object using the arrow operator ->.
$v->static_func(); // Static methods can be accessed through the object using ->.
Visibility::static_func();
// Because static methods are callable without an instance of the object created,
// the pseudo variable $this is not available inside the method declared as static.
echo "<br>==============================<br>";
?>

<?php
class ExVisibility extends Visibility
{
public static $s = "e static";
public function ex_func()
{
echo parent::$s;
echo " parent::\$s<br>";
echo self::$s;
echo " self \$s<br>";
}

}
$e = new ExVisibility();
$e->ex_func();
echo ExVisibility::$s;
echo "<br />";

?>

Friday, March 23, 2007

PHP5 Visibility Public Protected Private

The visibility of a property or method can be defined by prefixing the declaration with the keywords: public, protected or private. Public declared items can be accessed everywhere. Protected limits access to inherited and parent classes (and to the class that defines the item). Private limits visibility only to the class that defines the item.

Members Visibility

Class members must be defined with public, private, or protected.


Example 19-10. Member declaration

<?php
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';

function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}

$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private


/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';

function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}

$obj2 = new MyClass2();
echo $obj->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, not Private

?>

Note: The PHP 4 method of declaring a variable with the var keyword is still supported for compatibility reasons (as a synonym for the public keyword). In PHP 5 before 5.1.3, its usage would generate an E_STRICT warning.

Method Visibility

Class methods must be defined with public, private, or protected. Methods without any declaration are defined as public.

Example 19-11. Method Declaration

<?php
/**
* Define MyClass
*/
class MyClass
{
// Contructors must be public
public function __construct() { }

// Declare a public method
public function MyPublic() { }

// Declare a protected method
protected function MyProtected() { }

// Declare a private method
private function MyPrivate() { }

// This is public
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}

$myclass = new MyClass;
$myclass->MyPublic(); // Works
$myclass->MyProtected(); // Fatal Error
$myclass->MyPrivate(); // Fatal Error
$myclass->Foo(); // Public, Protected and Private work


/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// This is public
function Foo2()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate(); // Fatal Error
}
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Works
$myclass2->Foo2(); // Public and Protected work, not Private
?>

PHP5 class basic

The Basics

class

Every class definition begins with the keyword class, followed by a class name, which can be any name that isn't a reserved word in PHP. Followed by a pair of curly braces, which contains the definition of the classes members and methods. A pseudo-variable, $this is available when a method is called from within an object context. $this is a reference to the calling object (usually the object to which the method belongs, but can be another object, if the method is called statically from the context of a secondary object). This is illustrated in the following examples:
Example 19-1. $this variable in object-oriented language


<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this is defined (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this is not defined.\n";
}
}
}

class B
{
function bar()
{
A::foo();
}
}

$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>
The above example will output:

$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.

Example 19-2. Simple Class definition

<?php
class SimpleClass
{
// member declaration
public $var = 'a default value';

// method declaration
public function displayVar() {
echo $this->var;
}
}
?>
The default value must be a constant expression, not (for example) a variable, a class member or a function call.
Example 19-3. Class members' default value

<?php
class SimpleClass
{
// invalid member declarations:
public $var1 = 'hello '.'world';
public $var2 = <<hello world
EOD;
public $var3 = 1+2;
public $var4 = self::myStaticMethod();
public $var5 = $myVar;

// valid member declarations:
public $var6 = myConstant;
public $var7 = self::classConstant;
public $var8 = array(true, false);


}
?>

计算某月天数

function days_in_month($a_month, $a_year) {
return date('t', strtotime($a_year . '-' . $a_month . '-01'));
}
date :
t 给定月份所应有的天数 28 到 31

strtotime
(PHP 3 >= 3.0.12, PHP 4, PHP 5)
strtotime -- 将任何英文文本的日期时间描述解析为 Unix 时间戳
说明
int strtotime ( string time [, int now] )
本函数预期接受一个包含美国英语日期格式的字符串并尝试将其解析为 Unix 时间戳(自 January 1 1970 00:00:00 GMT 起的秒数),其值相对于 now 参数给出的时间,如果没有提供此参数则用系统当前时间。
本函数将使用 TZ 环境变量(如果有的话)来计算时间戳。自 PHP 5.1.0 起有更容易的方法来定义时区用于所有的日期/时间函数。此过程在 date_default_timezone_get() 函数页面中有说明。
注: 如果给定的年份是两位数字的格式,则其值 0-69 表示 2000-2069,70-100 表示 1970-2000。
参数
time
被解析的字符串,格式根据 GNU Date Input Formats 语法
now
用来计算返回值的时间戳
返回值
成功则返回时间戳,否则返回 FALSE。在 PHP 5.1.0 之前本函数在失败时返回 -1。

echo strtotime("now"), "\n";
echo strtotime("10 September 2000"), "\n";
echo strtotime("+1 day"), "\n";
echo strtotime("+1 week"), "\n";
echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
echo strtotime("next Thursday"), "\n";
echo strtotime("last Monday"), "\n";

Thursday, March 22, 2007

PHP4 reference example 2


<?php
function refArgs(&$v)
{
$x = &$v;
echo "old x value: " . $x;
echo "<br />";
$x = "new x value.";
}
$old_x = "old x value.";
refArgs($old_x);
echo "new x value: " . $old_x;
//old x value: old x value.
//new x value: new x value.
//通过reference引用&$v,$old_x 和 $x 其实就是指向一个相同的对象。
?>

php4 reference example


<php
class A {
function A($i) {
$this->value = $i;
// try to figure out why we do not need a reference here
$this->b = new B($this);
}

function createRef() {
$this->c = new B($this);
}

function echoValue() {
echo "<br />","class ",get_class($this),': ',$this->value;
}

function thisAfunc(){
echo "<br>this is class A's function. ";
}
}


class B {
function B(&$a) {
$this->a = &$a;
}

function echoValue() {
echo "<br />","class ",get_class($this),': ',$this->a->value;
}

function getAfunc(){
$this->a->thisAfunc();
}

function thisBfunc(){
echo "<br>this is class B's function. ";
}
}

// try to understand why using a simple copy here would yield
// in an undesired result in the *-marked line
$a =& new A(10);
$a->createRef();

$a->echoValue();
$a->b->echoValue();
//$a->b->thisAfunc();
//Fatal error: Call to undefined method B::thisAfunc() in /Users/yu/Sites/CakePHP/views/php/reference.thtml on line 43
$a->b->thisBfunc();
$a->c->echoValue();
//$a->c->thisAfunc();
//Fatal error: Call to undefined method B::thisAfunc() in /Users/yu/Sites/CakePHP/views/php/reference.thtml on line 47
$a->c->thisBfunc();
$a->c->getAfunc();

$a->value = 11;

$a->echoValue();
$a->b->echoValue(); // *
$a->c->echoValue();

?>

Wednesday, March 21, 2007

assignment operator in PHP4 and PHP5

The assignment(=) copies the original variable to the new one (assignment by value), so changes to one will not affect the other. This may also have relevance if you need to copy something like a large array inside a tight loop. Since PHP 4, assignment by reference has been supported, using the $var = &$othervar; syntax, but this is not possible in PHP 3. 'Assignment by reference' means that both variables end up pointing at the same data, and nothing is copied anywhere. To learn more about references, please read References explained.
As of PHP5 objects are assigned by reference
unless explicitly told otherwise with the new clone keyword.


如果是php4,在new一个class对象是copy操作,copy 了等号右边的原始对象赋给左边的变量,所以左边那个变量操作是与原来右边的对象是独立的,即通过对象操作改变了左边对象里的某个属性值,原来等号右边的对象仍然是原始初始化所赋的值。具体例子见php5手册里关于php4 reference的例子。如果需要操作此对象影响到右边的new出来的对象,则需要用到reference assignment(=&)。
在php5中默认就是reference assignment,除非明确声明是clone此对象。

使用ssh 客户密钥快速登录

使用ssh 密钥代替密码验证来加速并自动登录如果您是几台机器的管理员,那么能够快速导航到任意指定服务器上的某个shell 是很关键的。必须键入“ssh my.server.com”(后面跟有密码)不仅乏味,而且容易分散注意力。必须突然从“哪里出现问题了?”转到“到达出问题的地方”并回到“那么这究竟是怎么一回事?”,使得不少管理员都未老先衰。这种方法也会提出类似于“我为什么进入了这间房屋?”的数字等价问题(此外/usr/games/fortune 只会使这个问题变得更加糟糕)。
缓慢费力地登录到机器上意味着花在解决问题的精力减少了。较新版本
的ssh 提供了一种安全的方法即公钥交换,可以替代反复地输入密码。
要使用ssh 服务器的公钥,首先需要生成公钥/ 私钥对:
$ ssh-keygen -t rsa
对于DSA 密钥也可使用-t dsa,或者若使用v1 协议则使用-t rsa1。(如果确实在使用v1 协议,那应该感到惭愧哦。赶快升级到v2 吧!)在输入上述命令后,可看到如下内容:
Generating public/private rsa key pair.
Enter file in which to save the key (/home/rob/.ssh/id_rsa):
只需在此敲回车键。系统就会提示输入通行短语;只需连续两次敲入回车键(但应该阅读下面的安全通告)。结果看上去应该像下面显示的这样:
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/rob/.ssh/id_rsa.
Your public key has been saved in /home/rob/.ssh/id_rsa.pub.
The key fingerprint is:
a6:5c:c3:eb:18:94:0b:06:a1:a6:29:58:fa:80:0a:bc rob@localhost

这样将会创建两个文件,~/.ssh/id_rsa 和~/.ssh/id_rsa.pub。要对服务器使用此密钥对,可尝试:
$ ssh server "mkdir .ssh; chmod 0700 .ssh"
$ scp .ssh/id_rsa.pub server:.ssh/authorized_keys2
当然,要用服务器名代替server。每次系统都会提示您输入密码。现在,只需简单地键入ssh server,无须输入密码即可自动登录。如果登录成功,系统也会将此公钥用于scp。
如果该工具不能让您登录,请检查您在~/.ssh/* 和server:~/.ssh/* 上的文件许可。您的公钥(id_rsa)应该是0600(仅显示在本地机器上),在所有其他机器上则应该是0655 或更大的数字。非常好。现在您可以快速而明了地使用ssh 服务器了。还有可能比这更快地连接到经常要连接的机器上吗?答案当然是肯定的,请参阅第67小节“Turbo 模式的ssh 登录”。
安全性因素
有些人认为使用公钥会导致潜在的安全风险。但毕竟用户必须窃取您的私钥才能访问您的服务器。虽然如此,密码也存在这样的问题。好好想想,为了对机器(或scp 文件)进行shell 访问,您每天要输入多少次同一个密码?那些机器中有多少台(或全部)都使用同一个密码?是否曾经以不太可靠的方式使用密码(在Web站点上,在并非总能保持及时更新的个人计算机上,或者在您无法直接控制的带有ssh 客户端的机器上使用密码)?如果经常遇到以上任意一种情形,那么就必须考虑对相同设置采用一个ssh 密钥,这可以使得攻击者实际上不可能在未经授权的情况下获得访问权限(当然,首先要假定您安全地保存了您的私钥)。

Tuesday, March 20, 2007

winddows 2003 server 无法启动mongrel_rails service

mongrel_rails 在windows 2003 server上安装好service之后,不能正常启动,而在cmd下可以正常启动,后检查mongrel_service.log发现因为ruby,rails,mongrel_rails都是装在Program Files里,因为文件夹里空格造成service启动时找不到程序路径才启动失败,将ruby移到C盘根目录下,修改一下rails及mongrel_rails等文件里的路径,即将C:\Program Files\Ruby\bin\rails改为C:\Ruby\bin\rails,其他几个文件雷同处理即可。

Sunday, March 18, 2007

JavaScript watch function

watch: Watches for a property to be assigned a value and runs a function when that occurs.
Syntax: watch(prop, handler)
Description: Watches for assignment to a property named prop in this object, calling handler(prop, oldval, newval) whenever prop is set and storing the return value in that property. A watchpoint can filter (or nullify) the value assignment, by returning a modified newval (or oldval).

o = {p:1};
o.watch("p",
function (id,oldval,newval) {
document.write("o." + id + " changed from " + oldval + " to " + newval + "
");
return newval;
})

o.p = 2;
o.p = 3;
delete o.p;
o.p = 4;
o.unwatch('p');
o.p = 5;

Javascript Nesting functions

You can nest a function within a function. The nested (inner) function is private to its containing (outer) function:

The inner function can be accessed only from statements in the outer function.

The inner function can use the arguments and variables of the outer function. The outer function cannot use the arguments and variables of the inner function.
The following example shows nested functions:
function addSquares (a,b) {
function square(x) {
return x*x
}
return square(a) + square(b)
}
a=addSquares(2,3) // returns 13
b=addSquares(3,4) // returns 25
c=addSquares(4,5) // returns 41

When a function contains a nested function, you can call the outer function and specify arguments for both the outer and inner function:

function outside(x) {
function inside(y) {
return x+y
}
return inside
}
result=outside(3)(5) // returns 8

JavaScript Function implemented

JavaScript 1.1, NES 2.0


JavaScript 1.2: added arity, arguments.callee properties; added ability to nest functions.


JavaScript 1.3: added apply, call, and toSource methods; deprecated arguments.caller property.


JavaScript 1.4: deprecated arguments, arguments.callee, arguments.length, and arity properties (arguments remains a variable local to a function rather than a property of Function).

Property:Description

arguments
:An array corresponding to the arguments passed to a function.

arguments.callee:Specifies the function body of the currently executing function.

arguments.caller:Specifies the name of the function that invoked the currently executing function.

arguments.length:Specifies the number of arguments passed to the function.

arity
:Specifies the number of arguments expected by the function.

constructor:Specifies the function that creates an object's prototype.

length:Specifies the number of arguments expected by the function.

prototype:Allows the addition of properties to a Function object.

Saturday, March 17, 2007

Hierarchy of javascript and java










JavaScript

Java


function Manager () {
this.reports = [];
}
Manager.prototype = new Employee;
function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;



public class Manager extends Employee {
public Employee[] reports;
public Manager () {
this.reports = new Employee[0];
}
}
public class WorkerBee extends Employee {
public String[] projects;
public WorkerBee () {
this.projects = new String[0];
}
}

Using the arguments Array

[Deprecated]The arguments of a function are maintained in an array. Within a function, you can address the arguments passed to it as follows:
arguments[i]

where i is the ordinal number of the argument, starting at zero. So, the first argument passed to a function would be arguments[0]. The total number of arguments is indicated by arguments.length.

Using the arguments array, you can call a function with more arguments than it is formally declared to accept. This is often useful if you don't know in advance how many arguments will be passed to the function. You can use arguments.length to determine the number of arguments actually passed to the function, and then treat each argument using the arguments array.

For example, consider a function that concatenates several strings. The only formal argument for the function is a string that specifies the characters that separate the items to concatenate. The function is defined as follows:

function myConcat(separator) {
var result="" // initialize list
// iterate through arguments
for (var i=1; i < arguments.length; i++) {
result += arguments[i] + separator
}
return result
}

You can pass any number of arguments to this function, and it creates a list using each argument as an item in the list.

// returns "red, orange, blue, "
myConcat(", ","red","orange","blue")

// returns "elephant; giraffe; lion; cheetah; "
myConcat("; ","elephant","giraffe","lion", "cheetah")

// returns "sage. basil. oregano. pepper. parsley. "
myConcat(". ","sage","basil","oregano", "pepper", "parsley")

See the Function object in the Core JavaScript Reference for more information.

JavaScript 1.3 and earlier versions. The arguments array is a property of the Function object and can be preceded by the function name, as follows:

functionName.arguments[i]

Working With Regular Expressions

Regular expressions are used with the RegExp methods test and exec and with the String methods match, replace, search, and split.These methods are explained in detail in the Core JavaScript Reference.


Methods that use regular expressions

Method:Description

exec:A RegExp method that executes a search for a match in a string. It returns an array of information.

test:A RegExp method that tests for a match in a string. It returns true or false.

match:A String method that executes a search for a match in a string. It returns an array of information or null on a mismatch.

search:A String method that tests for a match in a string. It returns the index of the match, or -1 if the search fails.

replace:A String method that executes a search for a match in a string, and replaces the matched substring with a replacement substring.

split:A String method that uses a regular expression or a fixed string to break a string into an array of substrings.

When you want to know whether a pattern is found in a string, use the test or search method; for more information (but slower execution) use the exec or match methods. If you use exec or match and if the match succeeds, these methods return an array and update properties of the associated regular expression object and also of the predefined regular expression object, RegExp. If the match fails, the exec method returns null (which converts to false).

In the following example, the script uses the exec method to find a match in a string.

<script LANGUAGE="JavaScript1.2">
myRe=/d(b+)d/g;
myArray = myRe.exec("cdbbdbsbz");
</script>

If you do not need to access the properties of the regular expression, an alternative way of creating myArray is with this script:

<script LANGUAGE="JavaScript1.2">
myArray = /d(b+)d/g.exec("cdbbdbsbz");
</script>

If you want to construct the regular expression from a string, yet another alternative is this script:

<script LANGUAGE="JavaScript1.2">
myRe= new RegExp ("d(b+)d", "g");
myArray = myRe.exec("cdbbdbsbz");
</script>

With these scripts, the match succeeds and returns the array and updates the properties shown in the following table.

Results of regular expression execution.









































Object

Property or index

Description

In this example

myArray


The matched string and all remembered substrings.

["dbbd", "bb"]

index

The 0-based index of the match in the input string.

1

input

The original string.

"cdbbdbsbz"

[0]

The last matched characters.

"dbbd"

myRe
lastIndex
The index at which to start the next match.
(This property is set only if the regular expression uses the g option, described in Executing a Global Search, Ignoring Case, and Considering Multiline Input.)

5

source

The text of the pattern.Updated at the time that the regular expression is created, not executed.

"d(b+)d"

As shown in the second form of this example, you can use the a regular expression created with an object initializer without assigning it to a variable. If you do, however, every occurrence is a new regular expression. For this reason, if you use this form without assigning it to a variable, you cannot subsequently access the properties of that regular expression. For example, assume you have this script:

<script LANGUAGE="JavaScript1.2">
myRe=/d(b+)d/g;
myArray = myRe.exec("cdbbdbsbz");
document.writeln("The value of lastIndex is " + myRe.lastIndex);
</script>

This script displays:

The value of lastIndex is 5
However, if you have this script:
<script LANGUAGE="JavaScript1.2">
myArray = /d(b+)d/g.exec("cdbbdbsbz");
document.writeln("The value of lastIndex is " + /d(b+)d/g.lastIndex);
</script>

It displays:

The value of lastIndex is 0
The occurrences of
/d(b+)d/g in the two statements are
different regular expression objects and hence have different values for their lastIndex property.
If you need to access the properties of a regular expression created with an object initializer, you should first assign it to a variable.

JavaScript Operator

delete

The delete operator deletes an object, an object's property, or an element at a specified index in an array. The syntax is:

delete objectName
delete objectName.property
delete objectName[index]
delete property // legal only within a with statement

where objectName is the name of an object, property is an existing property, and index is an integer representing the location of an element in an array.

The fourth form is legal only within a with statement, to delete a property from an object.

You can use the delete operator to delete variables declared implicitly but not those declared with the var statement.

If the delete operator succeeds, it sets the property or element to undefined. The delete operator returns true if the operation is possible; it returns false if the operation is not possible.

x=42
var y= 43
myobj=new Number()
myobj.h=4 // create property h
delete x // returns true (can delete if declared implicitly)
delete y // returns false (cannot delete if declared with var)
delete Math.PI // returns false (cannot delete predefined properties)
delete myobj.h // returns true (can delete user-defined properties)
delete myobj // returns true (can delete if declared implicitly)



Deleting array elements
When you delete an array element, the array length is not affected. For example, if you delete a[3], a[4] is still a[4] and a[3] is undefined.

When the delete operator removes an array element, that element is no longer in the array. In the following example, trees[3] is removed with delete.

trees=new Array("redwood","bay","cedar","oak","maple")
delete trees[3]
if (3 in trees) {
// this does not get executed
}

If you want an array element to exist but have an undefined value, use the undefined keyword instead of the delete operator. In the following example, trees[3] is assigned the value undefined, but the array element still exists:

trees=new Array("redwood","bay","cedar","oak","maple")
trees[3]=undefined
if (3 in trees) {
// this gets executed
}



in

The in operator returns true if the specified property is in the specified object. The syntax is:

propNameOrNumber in objectName

where propNameOrNumber is a string or numeric expression representing a property name or array index, and objectName is the name of an object.

The following examples show some uses of the in operator.

// Arrays
trees=new Array("redwood","bay","cedar","oak","maple")
0 in trees // returns true
3 in trees // returns true
6 in trees // returns false
"bay" in trees // returns false (you must specify the index number,
// not the value at that index)
"length" in trees // returns true (length is an Array property)

// Predefined objects
"PI" in Math // returns true
myString=new String("coral")
"length" in myString // returns true

// Custom objects
mycar = {make:"Honda",model:"Accord",year:1998}
"make" in mycar // returns true
"model" in mycar // returns true



instanceof

The instanceof operator returns true if the specified object is of the specified object type. The syntax is:

objectName instanceof objectType

where objectName is the name of the object to compare to objectType, and objectType is an object type, such as Date or Array.

Use instanceof when you need to confirm the type of an object at runtime. For example, when catching exceptions, you can branch to different exception-handling code depending on the type of exception thrown.

For example, the following code uses instanceof to determine whether theDay is a Date object. Because theDay is a Date object, the statements in the if statement execute.

theDay=new Date(1995, 12, 17)
if (theDay instanceof Date) {
// statements to execute
}



new

You can use the new operator to create an instance of a user-defined object type or of one of the predefined object types Array, Boolean, Date, Function, Image, Number, Object, Option, RegExp, or String. On the server, you can also use it with DbPool, Lock, File, or SendMail. Use new as follows:

objectName = new objectType ( param1 [,param2] ...[,paramN] )

You can also create objects using object initializers, as described in "Using Object Initializers" on page 93.

See new in the Core JavaScript Reference for more information.



this

Use the this keyword to refer to the current object. In general, this refers to the calling object in a method. Use this as follows:

this[.propertyName]

Example 1. Suppose a function called validate validates an object's value property, given the object and the high and low values:

function validate(obj, lowval, hival) {
if ((obj.value < lowval) || (obj.value > hival))
alert("Invalid Value!")
}

You could call validate in each form element's onChange event handler, using this to pass it the form element, as in the following example:

Enter a number between 18 and 99:
onChange="validate(this, 18, 99)">

Example 2. When combined with the form property, this can refer to the current object's parent form. In the following example, the form myForm contains a Text object and a button. When the user clicks the button, the value of the Text object is set to the form's name. The button's onClick event handler uses this.form to refer to the parent form, myForm.


Form name:


onClick="this.form.text1.value=this.form.name">





typeof

The typeof operator is used in either of the following ways:

1. typeof operand
2. typeof (operand)

The typeof operator returns a string indicating the type of the unevaluated operand. operand is the string, variable, keyword, or object for which the type is to be returned. The parentheses are optional.

Suppose you define the following variables:

var myFun = new Function("5+2")
var shape="round"
var size=1
var today=new Date()

The typeof operator returns the following results for these variables:

typeof myFun is function
typeof shape is string
typeof size is number
typeof today is object
typeof dontExist is undefined

For the keywords true and null, the typeof operator returns the following results:

typeof true is boolean
typeof null is object

For a number or string, the typeof operator returns the following results:

typeof 62 is number
typeof 'Hello world' is string

For property values, the typeof operator returns the type of value the property contains:

typeof document.lastModified is string
typeof window.length is number
typeof Math.LN2 is number

For methods and functions, the typeof operator returns results as follows:

typeof blur is function
typeof eval is function
typeof parseInt is function
typeof shape.split is function

For predefined objects, the typeof operator returns results as follows:

typeof Date is function
typeof Function is function
typeof Math is function
typeof Option is function
typeof String is function



void

The void operator is used in either of the following ways:

1. void (expression)
2. void expression

The void operator specifies an expression to be evaluated without returning a value. expression is a JavaScript expression to evaluate. The parentheses surrounding the expression are optional, but it is good style to use them.

You can use the void operator to specify an expression as a hypertext link. The expression is evaluated but is not loaded in place of the current document.

The following code creates a hypertext link that does nothing when the user clicks it. When the user clicks the link, void(0) evaluates to undefined, which has no effect in JavaScript.

Click here to do nothing

The following code creates a hypertext link that submits a form when the user clicks it.


Click here to submit

Friday, March 16, 2007

JavaScript logical operation result

Examples of expressions that can be converted to false are those that evaluate to null, 0, the empty string (""), or undefined.

The following code shows examples of the && (logical AND) operator.

a1=true && true // t && t returns true
a2=true && false // t && f returns false
a3=false && true // f && t returns false
a4=false && (3 == 4) // f && f returns false
a5="Cat" && "Dog" // t && t returns Dog
a6=false && "Cat" // f && t returns false
a7="Cat" && false // t && f returns false

The following code shows examples of the || (logical OR) operator.

o1=true || true // t || t returns true
o2=false || true // f || t returns true
o3=true || false // t || f returns true
o4=false || (3 == 4) // f || f returns false
o5="Cat" || "Dog" // t || t returns Cat
o6=false || "Cat" // f || t returns Cat
o7="Cat" || false // t || f returns Cat

JavaScript and Ruby difference of '+'

JavaScript does not convert numeric values to strings. For example:

"37" - 7 // returns 30
"37" + 7 // returns 377

Ruby will raise error when execute this example:

irb(main):001:0> "37" - 7
NoMethodError: undefined method `-' for "37":String
from (irb):1
irb(main):002:0> "37" + 7
TypeError: can't convert Fixnum into String
from (irb):2:in `+'
from (irb):2
irb(main):003:0> "37".to_i - 7
=> 30
irb(main):004:0> "37" + 7.to_s
=> "377"
irb(main):005:0>

Array Search Prototype

from DZone Snippets: javascript code by pcx99 (Patrick)
This prototype extends the Array object to allow for searches
within the Array. It will return false if nothing is found. If
item(s) are found you'll get an array of indexes back which matched
your search request. It accepts strings, numbers, and regular expressions as search
criteria. 35 is different than '35' and vice-versa.

// Examples
var test=[1,58,'blue','baby','boy','cat',35,'35',18,18,104]
result1=test.find(35); //returns 6
result2=test.find(/^b/i); //returns 2,3,4
result3=test.find('35'); //returns 7
result4=test.find(18); // returns 8,9
result5=test.find('zebra'); //returns false



Array.prototype.find = function(searchStr) {
var returnArray = false;
for (i=0; i if (typeof(searchStr) == 'function') {
if (searchStr.test(this[i])) {
if (!returnArray) { returnArray = [] }
returnArray.push(i);
}
} else {
if (this[i]===searchStr) {
if (!returnArray) { returnArray = [] }
returnArray.push(i);
}
}
}
return returnArray;
}

Rendering empty responses

Rendering empty responses
from the { buckblogs :here } - Home by Jamis

Sometimes (and especially once you start dealing with writing web services) you’ll find yourself wanting to return an empty response, with only a status code and (possibly) a few headers set.

You can do this easily enough using the render method:

headers['Location'] = person_url(@person)
render :nothing => true, :status => "201 Created"

That, however, is unbearably verbose, especially when you find yourself needing to do it in multiple places.

Enter the head method:

head :created, :location => person_url(@person)

There, isn’t that beautiful?

Top 10 custom JavaScript functions of all time

UPDATE: For anyone who lands on this article months after the fact, there is now a podcast entry about this article reviewing each and every function.

If there was ever a universal common.js shared among the entire develosphere, you’d fine these ten (plus one bonus) functions. It would be the swiss army knife no developer would go into production without. They have no doubt been tested tried and true and have proven usefulness and helpfulness to all those who’ve used them. So without further ado, here are what I believe to the top ten greatest custom JavaScript functions in use today.

Upon further reading this article, it is suggested that for this article in particular the reader should use an alternate style with cleaner whitespace and larger margins. This is available by selecting Clean with Whitespace available on the side bar.
10) addEvent()

Surely a staple to event attachment! Regardless to what version you use written by whatever developer, it does what it says it does. And of course as you might of known, I’ve put together quite a handy version myself recently of addEvent() with some help from the contest winner and Mark Wubben along with a few minor syntax adjustments. But just to be fair to Scott Andrew, here is the original that started it all.
Scott Andrew’s original addEvent() function

function addEvent(elm, evType, fn, useCapture) {
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}

9) addLoadEvent()

Originally written by Simon Willison and highly adopted by many others as a simple way to add events to trigger after the page has loaded. This of course attaches all your events to the onload event handler which some still see as necessary, nevertheless it does exactly what it’s supposed to, and does it well.
addLoadEvent() by Simon Willison

function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
}
else {
window.onload = function() {
oldonload();
func();
}
}
}

Of course another method is to simply assign multiple event listeners to the window by using addEvent() as described in number 10 as follows:
assigning multiple load events to window

addEvent(window,'load',func1,false);
addEvent(window,'load',func2,false);
addEvent(window,'load',func3,false);

8) getElementsByClass()

Originially written by nobody in particular. Several developers have implemented their own version and no one single version has proven to be better than another. As you might expect, my humble self has even had a crack at it. This function was spawned from developers needing a quick and elegant way of grabbing elements by a className and to a developer’s surprise, it’s not an original DOM method as one might think…afterall, we have getElementById, getElementsByName(), getElementsByTagName, what the hell happened to getElementsByClass??? Here it is in all its glory:
getElementsByClass by Dustin Diaz

function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
node = document;
if ( tag == null )
tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp('(^|\\s)'+searchClass+'(\\s|$)');
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}

Simply add a class name to the beginning of the funciton and the 2nd and 3rd arguments are optional and the magic is done for you!
7) cssQuery()

Originally written by Dean Edwards as a way to query the DOM according to CSS properties which supports a multitude of selectors. However in all fairness, this is more like a mini-library and not quite so light on the weight factor, but still, a very kick-ass function. Due to its length (and CC lisencing) I won’t post it on this site. Full documentation can be found on the myCssQuery reference and download page.
6) toggle()

To be totally honest, there are probably more variations of this function than there needs to be. The history of ‘toggling’ basically comes down to showing/hiding an element upon an event being fired. To make matters much simpler, I too have put one together. But by no means is it considered the ultimate toggle function, but it does do the basic functionality of showing and hiding.
toggle() by the masses

function toggle(obj) {
var el = document.getElementById(obj);
if ( el.style.display != 'none' ) {
el.style.display = 'none';
}
else {
el.style.display = '';
}
}

5) insertAfter()

As far as I know, Jeremy Keith sort of came up with this idea even though one would have thought this too would be a DOM core method. But just like getElementsByClass, it isn’t. So rather than pulling the function straight out of the book, I’ll leave that up to you to buy it yourself. Instead I’ve pulled this simple method from public domain:
insertAfter() on public domain

function insertAfter(parent, node, referenceNode) {
parent.insertBefore(node, referenceNode.nextSibling);
}

4) inArray()

This too is very sad that this isn’t part of the DOM core functionality. But hey, it makes for fun references like this! This function however isn’t quite a function; it’s a prototype that extends the DOM Array object. I remember one day thinking to myself “surely I can do this in PHP, it’s gotta be in JavaScript.” Well, this extension makes it work just like you’d expect if you’re a PHP developer. Here is a version from EmbiMEDIA
inArray Prototype Array object by EmbiMedia


Array.prototype.inArray = function (value) {
var i;
for (i=0; i < this.length; i++) {
if (this[i] === value) {
return true;
}
}
return false;
};

3, 2, & 1) getCookie(), setCookie(), deleteCookie()

I honestly don’t know what I would do without these guys. I hate the DOM implementations of setting cookies in JavaScript. In PHP it’s so easy, and it’s easy for one main reason, they work just like the functions below. All three of these functions were found to be public domain and free to use.
getCookie(), setCookie(), deleteCookie() open domain

function getCookie( name ) {
var start = document.cookie.indexOf( name + "=" );
var len = start + name.length + 1;
if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
return null;
}
if ( start == -1 ) return null;
var end = document.cookie.indexOf( ';', len );
if ( end == -1 ) end = document.cookie.length;
return unescape( document.cookie.substring( len, end ) );
}

function setCookie( name, value, expires, path, domain, secure ) {
var today = new Date();
today.setTime( today.getTime() );
if ( expires ) {
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date( today.getTime() + (expires) );
document.cookie = name+'='+escape( value ) +
( ( expires ) ? ';expires='+expires_date.toGMTString() : '' ) + //expires.toGMTString()
( ( path ) ? ';path=' + path : '' ) +
( ( domain ) ? ';domain=' + domain : '' ) +
( ( secure ) ? ';secure' : '' );
}

function deleteCookie( name, path, domain ) {
if ( getCookie( name ) ) document.cookie = name + '=' +
( ( path ) ? ';path=' + path : '') +
( ( domain ) ? ';domain=' + domain : '' ) +
';expires=Thu, 01-Jan-1970 00:00:01 GMT';
}

Last but not least, a bonus function: The Prototype Dollar Function

This function straight up kicks so much ass. First of all, just look at it.
Prototype function $

function $() {
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string')
element = document.getElementById(element);
if (arguments.length == 1)
return element;
elements.push(element);
}
return elements;
}

// Sample Usage:
var obj1 = document.getElementById('element1');
var obj2 = document.getElementById('element2');
function alertElements() {
var i;
var elements = $('a','b','c',obj1,obj2,'d','e');
for ( i=0;i

Tell me that’s not beautiful! Short not only by name, but by reference. It not only takes in strings, it takes objects too. You can pass it one argument, or pass it many! This by far is my favorite function of all time which will provide years and years of handiness.
And so will they all…

I hope this quick and handy list of JavaScript functions has been as useful for you as they have been for me. And for your downloading pleasure, here is all these functions wrapped up in a common.js just for you.
After the fact

Added after 30 comments or so…: Ok, I can understand everyone’s point of view when it comes to ‘these ten being the best‘. The fact of the matter is, this is what I think were the best. If Dean Edwards wrote his top ten, I’m sure it would be different. If Stuart Langridge wrote his list, it too would be different. I mainly concentrated my list on the DOM. Browser detection is up to the developer at hand. Ajax functions I felt do not qualify as an ‘all timer’ mainly because Ajax is still in its infancy and has yet to impress me with something amazingly useful. For those wishing to just push these functions aside and slap on prototype to their documents, go ahead and slap on the extra 30k if you feel that’s necessary. Nevertheless, thank you all thus far for the wonderful comments. I still hope this small list will come in handy for quite some time. And believe me, there are hundreds of other great functions that could possibly make it here. Just because it isn’t here, doesn’t mean it’s not good. Just use your imagination ;)


http://www.dustindiaz.com/top-ten-javascript/

Thursday, March 08, 2007

AJAX problem with drag and drop for Internet Explorer using Scriptaculous

I have been having this kind of hair tearing problem with Internet Explorer 6 in the last few days while trying to implement drag and drop within the AJAX framework of Ruby On Rails. The problem is extremely frustrating to track down as it works perfectly with Firefox (a sign of the time, I suppose, IE used to be the benchmark for sane rendering, but alas no more !). Hopefully by detailing it here, no one else will have to go through the same pain I did.

I should point out here that most advertised features work perfectly in both Internet Explorer and Firefox. However, it was a combination of what I did which caused problems in IE. So if you ever get this problem where Internet Explorer throws out this Javascript error "Unspecified error" each time you attempt to move a drag-able item over potential drop sites, then read on.

Ruby On Rails comes integrated with a pretty cool Javascript client library called Scriptaculous, which takes away the pain of cross browser incompatibilities (supposedly, but as I will show here, even this library has its limits when it comes to browser idiosyncrasies). Scriptaculous provides AJAX support, drag and drop, auto-complete, and many other cool features out of the box. I had no problem implementing the basic drag and drop, which worked fine in both Firefox and Internet Explorer. However, I ran into the above mentioned error where Internet Explorer will consistently throw out streams of Javascript "Unspecified error" once a drop has been made. The error itself is of no help as it gives you no clues as to what the problem is. What is it which has completely messed up the DOM in such a way that once the first drop is made, no other items can be dragged around without causing errors ? The Javascript error happens consistently on a block of code in the dragdrop.js file at line 1589, column 7, ( or prototype.js 2326, column 7) which is highlighted bold below.


var Enumerable = {
each: function(iterator) {
var index = 0;
try {
this._each(function(value) {
try {
iterator(value, index++);
} catch (e) {
if (e != $continue) throw e;
}
});
} catch (e) {
if (e != $break) throw e;
}
},


I tried out the Scriptaculous demo shopping cart on Internet Explorer, which works perfectly. This tells me Internet Explorer is not the problem, or indeed the basic boiler plate drag and drop code (just a process of elimination). Well, back to my code. It must be something in my code that causes this. The basic code must work as I am able to drop the draggable item once. So, it must be something to do with the sequence of events, rather than the drag and drop technology itself. I viewed the html before and after the drag and drop action, looks ok. Then I viewed the list of Droppables objects using the JScript debugger, this looked OK too.

Google was of no help. Not sure if it is because the subject is relatively new (Ruby on Rails, AJAX, Scriptaculous etc.). Whatever I could find led me to try out these desperate measures:

* download the latest version of Scriptaculous instead of using the one packaged with Rails
* deploy an application called Browser Object Helper daemon, which allows me to look at all the third party extensions loaded into IE on start up, as these BOH's have been known to cause problems with IE crashing with "Unspecified error"
* re-engineer my pages so that the different fragments get generated together instead of via cascaded Javascript hooks on the :onComplete event

None of the above solutions helped !! Where is Sherlock when you need him ?

Then, on the third day (what is it about the third day ? I always seem to have more luck on the third day !), something dawned on me. I quickly checked out the list of drop sites again in the JScript debugger, and sure enough, the error always happened on the second drop site in the list. A quick drill down gave me an insight into my problem, in that the second drop site has the same name as the first drop site. How is this possible ? pages are generated on the fly, and all the drop sites are guaranteed to have unique id's within the page. Looking through the code again told me the problem, which is to do with Rails's partial rendering mechanism. Rails has a very good built in AJAX engine, which allows you to refresh fragments of the page without regenerating the whole page (this is the technology used extensively at Google Maps). It is this partial rendering which is the root of all problems. Normally, when a page is reloaded, the whole list of drop sites, which is built up from the initial rendering, is started from scratch. In fact, this should work perfectly too, normally, if you do not re-generate the drop sites within the page as part of partial rendering. However, if these drop sites are re-generated (as mine is), then this is when IE behaves differently to Firefox.

Firefox looks like it did the right thing (or maybe not, depending on your point of view), and still honours calls to the DOM element associated with the defunct drop site, specifically the cumulativeOffset() call in dragdrop.js, which traverses up the DOM in order to calculate the overlap between the dragged item and the drop site. It could be because Firefox looks up the DOM element by name and resolves it to the newly created element automatically (cool or what ?).

However, Internet Explorer goes completely crazy on this (or maybe it should, again depending on your point of view) and throws out these JScript errors about the dead drop site still sitting happily in the cached list of Droppables. This list is created by the drag and drop technology, and because we are not reloading the page, is never cleared out properly between AJAX calls.

The solution, once known looks so simple, is to place this Javascript call into the page fragment which is re-built on each AJAX call (but only if you intend to re-generate the drop sites):

<script type="text/javascript">
if (document.all) { Droppables.drops = [] }
</script>

Go, go, gadgets, go !!

The footnote is, however, even though Firefox is more forgiving in this instance (I mean it does the right thing in terms of intended design), in the long run, if your partial rendering is more intensive, it is probably a good idea to clear out the drop sites regardless of the browser to make it more memory efficient and also quicker to iterate through the list of possible drop sites each time an item is dragged around on the screen.

Also, the moral of the story is, Internet Explorer absolutely detests having different DOM elements with the same identifier. Firefox seems to do something internally to cope with this rather impressively. As a client side developer, I know which one I'd rather use. Alas, the majority out there do not write web pages for a living. Also, if technical superiority counts, we'd all be using Betamax tapes, right ?

This article source: http://public.transcraft.co.uk/articles/development/ie_ajax_dragdrop.html

Wednesday, March 07, 2007

mongrel_rails mongrel_cluster win32

c:/ruby/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.0/lib/mongrel_cluster/init.rb
:55:in ``': Exec format error - mongrel_rails start -d -e prod -p 8000 -a 127.0.
0.1 -P log/mongrel.8000.pid -c C:\ruby\finance (Errno::ENOEXEC)
from c:/ruby/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.0/lib/mongrel_cl
uster/init.rb:55:in `run'
from c:/ruby/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.0/lib/mongrel_cl
uster/init.rb:34:in `run'
from c:/ruby/lib/ruby/gems/1.8/gems/mongrel-0.3.13.1-mswin32/lib/mongrel
/command.rb:211:in `run'
from c:/ruby/lib/ruby/gems/1.8/gems/mongrel-0.3.13.1-mswin32/bin/mongrel
_rails:227
from c:/ruby/bin/mongrel_rails:18

To deal with this 'Exec format error',
You want to be calling:
argv = “mongrel_rails.cmd” ]
instead of:
argv = [ “mongrel_rails” ]
in the mongrel_cluster init.rb

Windows can’t find “mongrel_rails”.

Friday, March 02, 2007

Apache2 configure

apache2.2.4 configure parameters:

./configure \
--prefix=/usr/local/apache2 \
--enable-so \
--enable-rewrite \
--enable-module=most \
--enable-shared=max \
--enable-cgi \
--enable-mime-magic \
--enable-dav \
--enable-dav-fs \
--enable-maintainer-mode \
--enable-ssl \
--enable-proxy \
--enable-proxy-connect \
--enable-proxy-ftp \
--enable-proxy-http \
--enable-proxy-balancer \
--with-included-apr

checking for APR-util... yes
configure: error: Cannot use an external APR-util with the bundled APR
To check to see if this new problem is caused by some change I've made to the server (unlikely - all this machine does is serve web pages - the only changes I ever make are security patches), I tried re-compiling 2.2.3. No problem - everything worked as before.

So, *something* has changed in 2.2.3 -> 2.2.4 that is *broken* on my machine (meaning, I can't even configure 2.2.4). In the config.log, I see the following:

Could you post your ./configure line?
Could you run the commands
locate apr-1-config
locate apu-1-config
and tell us what the output is?

Finally, try adding --with-included-apr to ./configure . This forces the build process to use the apr and apr-util that come with the release.

Thursday, March 01, 2007

apache proxy balancer + mongrel clusters and deploying application with capistrano

So you want to setup production server with mongrel clusters and apache proxy balancer, also wants to use capistrano for deployment, huh. Take it easy, its very simple.

You need Apache 2.2 or later on your production server, and the following ruby gems on your both machine(server and local):

* capistrano
* mongrel
* mongrel_cluster

I haven’t mentioned rails and rake gem as we are deploying a rails application so these gems are obvious.

Lets install above gems (if not installed) by issuing:

gem install --include-dependencies capistrano
gem install --include-dependencies mongrel
gem install --include-dependencies mongrel_cluster

gem install --include-dependencies capistrano gem install --include-dependencies mongrel gem install --include-dependencies mongrel_cluster

Now make sure that the following modules are enabled (they are disabled by default) :

* mod-rewrite
* mod-proxy
* mod-proxy-http
* mod-proxy-balancer

to check if they are enabled issue ” /etc/init.d/apachectl -M ” on server, it will list all the enabled modules. For Debian systems all enabled modules are in /etc/apache2/mods-enabled directory and all available modules are in /etc/apache2/mods-available directory, to enable them issue ” a2enmod MOD_NAME “.

Now create the production database(on server) and update database.yml for production database settings.

After this configure mongrel by issuing ” mongrel_rails cluster::configure -e production -p 8000 -a 127.0.0.1 -N 2 -c ./ ” inside the rails application root directory(on client machine). This will create mongrel_cluster.yml in config directory. You can change parameters in this command, as -p 8000 specifies that mongrel instances will start up on port number starting 8000, -a 127.0.0.1 specifies that mongrel instances will listen to the localhost, -N specifies the number of mongrel instances and -c specifies the rails root directory.

Now its time to capistranize rails application, issue ” cap –apply-to ./ APP_NAME ” inside rails application root directory(on client machine), this will add two files(config/deploy.rb and lib/tasks/capistrano.rake) to the rails application. Edit deploy.rb according to your requirements. Also add the following code to deploy.rb :
view plainprint?

task :restart, :roles => :app do
# stop mongrel clusters for previous release and start for current
run "cd #{previous_release} && mongrel_rails cluster::stop"
run "sleep 5"
run "cd #{current_release} && mongrel_rails cluster::start"
end


Now on your local machine issue these two commands in only once ” rake remote:setup ” and ” rake remote:cold_deploy “, when you issue ” rake remote:setup ” it will prompt for the server password and create necessary directories on the server and ” rake remote:cold_deploy ” will deploy your code to the server. Next time whenever you want to deploy to the server you just need to issue ” rake remote:deploy ” not ” rake remote:cold_deploy “.

Now we are just one step back, we need to configure apache proxy balancer for mongrel instances. Add the following code to the httpd.conf file:
view plainprint?



<Proxy balancer://mongrel_cluster>
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
</Proxy>

<VirtualHost *:8080>
ServerName test.com
DocumentRoot /Users/yu/Sites/RubyOnRails

<Directory "/Users/yu/Sites/RubyOnRails">
Options FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>

RewriteEngine On

RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]

RewriteRule ^/$ /index.html [QSA]
# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ $1.html [QSA]

RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
</virtualHost>

you need to change the above code according to you requirement. Also you need to restart apache server by issuing ” /etc/init.d/apachectl restart “. Now you are done.

But we also need to add a script to start mongrel instances when the server restarts, otherwise whenever the server restart there will no mongrel instance running.

Just create a file named mongrel_clusters (you can choose any name) in /etc/init.d directory with the following code:
view plainprint?

1. #!/bin/bash
2. #
3. # chkconfig: 345 94 16
4. # description: Startup script for mongrel
5. BASEDIR=/var/www/your_app
6. export HZ=100
7. export TERM=linux
8. export SHELL=/bin/bash
9. export HUSHLOGIN=FALSE
10. export USER=root
11. export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
12. export MAIL=/var/mail/root
13. export _=/usr/bin/env
14. export PWD=/etc/init.d
15. export HOME=/root
16. export SHLVL=2
17. export LOGNAME=root
18.
19. cd $BASEDIR
20. case "$1" in
21. start)
22. echo "starting up mongrel in $BASEDIR"
23. mongrel_rails cluster::start
24. ;;
25. stop)
26. echo "stopping mongrel"
27. mongrel_rails cluster::stop
28. ;;
29. restart)
30. mongrel_rails cluser::stop
31. sleep 3
32. mongrel_rails cluster::start
33. ;;
34. esac

You need to change the BASEDIR in the above code. Make this file executable by ” chmod +x /etc/init.d/mongrel_clusters ”
Issue these commands to add this script at system startup:

Debian: /usr/sbin/update-rc.d /etc/init.d/mongrel_clusters defaults
RedHat: /usr/sbin/chkconfig –add /etc/init.d/mongrel_clusters and /usr/sbin/chkconfig –level 2 /etc/init.d/mongrel_clusters on

http://vinsol.com/2007/02/04/apache-proxy-balancer-mongrel-clusters-and-deploying-application-with-capistrano/