Install PHPUnit On Debian

First my Debian version is:

[root@www:~]# cat /proc/version
Linux version 2.6.32-pony6-3 (root@debian) (gcc version 4.4.6 (Debian 4.4.6-14) ) #1 SMP Tue Mar 13 07:31:44 PDT 2012

Per PHPUnit To install PHPUnit, using the following two command:

pear config-set auto_discover 1
pear install

However, nothing is simple, you may see the error message, like

[root@www:~]# pear install
Did not download optional dependencies: phpunit/PHP_Invoker, use --alldeps to download automatically
phpunit/PHPUnit requires PEAR Installer (version >= 1.9.4), installed version is 1.9.1
phpunit/PHPUnit can optionally use package "phpunit/PHP_Invoker" (version >= 1.1.0, version <= 1.1.99) phpunit/File_Iterator requires PEAR Installer (version >= 1.9.2), installed version is 1.9.1
phpunit/Text_Template requires PEAR Installer (version >= 1.9.4), installed version is 1.9.1
phpunit/PHP_CodeCoverage requires PEAR Installer (version >= 1.9.4), installed version is 1.9.1
phpunit/PHP_CodeCoverage requires package "phpunit/File_Iterator" (version >= 1.3.0)
phpunit/PHP_CodeCoverage requires package "phpunit/Text_Template" (version >= 1.1.1)
phpunit/PHP_CodeCoverage can optionally use PHP extension "xdebug" (version >= 2.0.5)
phpunit/PHP_Timer requires PEAR Installer (version >= 1.9.2), installed version is 1.9.1
phpunit/PHPUnit_MockObject requires PEAR Installer (version >= 1.9.4), installed version is 1.9.1
phpunit/PHPUnit_MockObject requires package "phpunit/Text_Template" (version >= 1.1.1)
phpunit/PHP_TokenStream requires PEAR Installer (version >= 1.9.4), installed version is 1.9.1
No valid packages found
install failed

If you see this error, it means you need to upgrade your Pear. To upgrade Pear you can use the following commands,

pear upgrade

If you see the following result, that means you pear has been upgraded.

upgrade ok: channel://
upgrade ok: channel://
upgrade ok: channel://
upgrade ok: channel://

Then you can try to install PHPUnit again.

pear install

If everything is good, then you should be able to run phpunit from your command line, if command is found, congratulations, you have installed phpunit.

Now you would need to learn how using phpunit, that is a hard part.

PHPMyAdmin connect to both Local and Remote Server

Add servers into, there may be two, one is under “/etc/phpmyadmin”, the other is under your web root folder. If so, update the one under your root.

//server 1 - local
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['verbose']   = 'local';
$cfg['Servers'][$i]['host']      = 'localhost';//or ip:''
$cfg['Servers'][$i]['extension'] = 'mysqli';

//server 2 - remote
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['verbose']   = 'remote';
$cfg['Servers'][$i]['host']      = '';//hostname or ip:''
// this server must allow remote clients, e.g., host 10.9.8.%
// not only in but also in the startup configuration
$cfg['Servers'][$i]['extension'] = 'mysqli';

Then, you should see the two servers shown up on the PHPMyAdmin login screen.
If you receive the error when trying to connect to remote server, then keep on reading.

To access remote mysql database, you have to enable remote access on the remote server. Check this article.

The tricky part is to open TCP port 3306 using iptables. You have to add an rule via iptables

iptables -A INPUT -i eth0 -s -p tcp --destination-port 3306 -j ACCEPT
## is client ip, where we try to connect to db server.

But you need to make sure there is no REJECT ALL rule before this new rule. For example, using command “iptables -L”, you see there is a REJECT ALL rule before the new rule we added, then the new rule will be ignored.

[root@leijinet resources]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:http
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable
ACCEPT     tcp  --             anywhere            tcp dpt:mysql

To fix this, we need to move the new rule up. I could not find the move command, so what I did was that remove the “REJECT ALL” RULE and then add it to the end. Like

### remove a rule, "6" is the index
iptables -D INPUT 6

### add a rule back
iptables -A INPUT -i eth0 -j REJECT

Some simple note here hope can help you.

Reading Note 4 – PHP 5 Advanced OOP and Design Patterns

OK. It’s Object Oriented Time!

1. Because a constructor cannot return a value, the most common practice for raising an error from within the constructor is by throwing an exception.

2. $obj = NULL will destruct the obj (or __desctruct() ill be called.

3. Static properties are defined by using static keywords, and you can think it as global variable that sit inside the class, but are accessible from anywhere via the class. Static property is used in a singleton pattern.

4. Static properties or methods can be called outside the class without creating an instance.

static staticproperty;

$this->staticproperty //THIS IS WRONG!!!!

5. parent:: and self::
They can access to static members, methods (both static and non-static method), and constants.

class A{
public $abc = 2;
function getabc(){
echo self::abc; //THIS IS WRONG, because abc is not static
Class B extends A{
function getabc(){
echo parent::abc; //HIS IS WRONG, because abc is not static

6. public protected, private are access modifiers for both properties and menthods

7.class constants do not use the define() function, which is used for global constant, but use the “const” keyword.

class myclass {
const RD = "red";

8. polymorphism uses “extends” keyword and means inheritance

9. PHP 5 introduces abstract classes and methods. Classes defined as abstract may not be instantiated, and 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.

10. In PHP, you can only extends from one parent class, but you can use implements to archive multiple inheritance.

class A implements B, C, ... {

11. interface class like abstract. So no implantation of method and can not be directly instantiated. The different is that you can only extend from one abstract, but can extend from multiple interfaces.

12. final methods.
If you want to make sure that a method cannot be re-implemented in its derived classes, then use final access modifier.

13. final classes.
Final classes are not allowed inherited.

12. classes cannot be defined as abstract, final, but all classes are public in PHP. There’s no such thing as a “private/protect class”.

13. Exceptions
When using exceptions, follow these basic rules (both for performance and code-manageability reasons):

  1. 1. Remember that exceptions are exceptions. You should only use them to handle problems, which brings us to the next rule….
  2. 2. Never use exceptions for flow control. This makes the code hard to follow (similar to the goto statement found in some languages) and is slow.
  3. 3. The exception should only contain the error information and shouldn’t contain parameters (or additional information) that affect flow control and logic inside the catch handler.

14. Example to catch dived by zero exception
PHP5 brought exceptions to the table, and newer PHP provided libraries (PDO) will throw exceptions when bad/unexpected things happen. Hoever, the core codebase was NOT rewritten to use exception. Core functions and operations still rely on the old error system. If you want to “catch” these, you’ll need to set a custom error handler that will detect division by zero errors and do something about them.

   //$a = 1/0;
   $a = devide(1,0);
   echo $a;
catch(DevidedByZeroException $e1){
   echo $e1->getMessage();
   print " in file " . $e1->getFile();
   print " on line " . $e1->getLine() . "\n";
catch(Exception $e){
   echo $e->getMessage();

function devide($a, $b){
      throw new DevidedByZeroException("Division by zero is invalid");
      return $a/$b;

class DevidedByZeroException extends Exception {
   function __construct($message)

14. __autoload()

function __autoload($class_name) {
include $class_name . '.php';

$obj = new MyClass1();
$obj2 = new MyClass2();

spl_autoload_register() provides a more flexible alternative for autoloading classes. For this reason, using __autoload() is discouraged and may be deprecated or removed in the future.

// function __autoload($class) {
// include 'classes/' . $class . '.class.php';
// }

function my_autoloader($class) {
include 'classes/' . $class . '.class.php';

//as php5.1.2
// you can have multiple callback functions

// Or, using an anonymous function as of PHP 5.3.0
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.class.php';

Reading Note 3 – PHP 5 Advanced OOP and Design Patterns

Basic but you may not know php syntax

1. use variable as variable name

$file1 = "hello";
$file2 = "world";
$file3 = "php";

for($i=1; $i<4; $i++){
   $filename = "file" . $i;
   echo $$filename . "\n";
   //or ${$filename};

2. if set a variable as NULL, then this variable will be noset (!isset)

$a = null;
   echo "you cannot see this";
   echo "set to null means no set";

3. Check if all variable have been defined using isset

   echo "yes, all set";

4. The Difference between empty and isset is that empty is to check if a variable is not set or is assigned a false value. isset is check if a variable is set.

5. What's superglobals? As a general rule, PHP does not support global variables. But there are some variables called superglobals, which are predefined by PHP and can be accessed from any scope. For example, $_GET, $_POST, $_COOKIE, $_SESSION, $_ENV, $_SERVER.

6. String Offerset - use to easy manipulate the any char in a string.

$str = '17';
$str{1} = '2'; //replace the second position of str to be '2', so the str is '12' now
$str[6] = 7; //php4 syntax, still valid in php5, but should use {} instead in php5
echo $str; //so now the str is '12    7'. after 2 there are 4 empty chars.

7. true or false of Array, Object, Resource.
a. If $arr is an empty array, $arr is false, otherwise, it's true
b. If $obj is an object, and $res is a resource, then $obj and $res are always true value

8.each() and reset()
The each function returns the current key/value pair and advances the internal pointer to the next element. Note that The each function returns an array with 4 pairs of items. For example:

$ages = array("John" => 28, "Barbara" => 67);
//reset($ages); //reset if needed
$person = each($ages);
    [1] => 28
    [value] => 28
    [0] => John
    [key] => John

list($name,$age) = each($ages);
echo $name . ": " . $age . "\n";
//You got: Barbara: 67. Because you did not use reset, and indexes 0 and 1 returned by each() are assigned to the list() construct.

$members = array("John", "Barbara");
$person = each($members);
    [1] => John
    [value] => John
    [0] => 0
    [key] => 0

9. The cast oprators
It changes the type of variable.

10. Floating point numbers (also known as "floats", "doubles", or "real numbers") can be specified using any of the following syntaxes:

LNUM [0-9]+
DNUM ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM [+-]?(({LNUM} | {DNUM}) [eE][+-]? {LNUM})

(int) $str is the same as (interger) $str
(bool) $str is the same as (boolean) $str

11. @ is the silence oprator, add @ before a function will silences error message.

12 eval() is similar to include, but instead of compiling and executing code that comes from a file, it accepts the code as a string. (Only do it when you can't do without) For example, in the solr,

$code = file_get_contents('http://localhost:8983/solr/select?q=iPod&wt=php');
//code is string, for exmaple,  'array("k1"=>"v1", "k2"=>"v2")...'
eval("\$result = " . $code . ";"); //this will assign array to $result

13. static variables.
Static variables only run at the first time (and only the first time), so it can be used in a function, where you only trigger something when function is called at the first time.

$count = 5; // "outer" count = 5

function get_count()
    static $count = 0; // "inner" count = 0 only the first run
    return $count++; // "inner" count + 1

echo $count; // "outer" count is still 5 
++$count; // "outer" count is now 6 (but you never echoed it)

echo get_count(); // "inner" count is now + 1 = 1 (0 before the echo)
echo get_count(); // "inner" count is now + 1 = 2 (1 before the echo)
echo get_count(); // "inner" count is now + 1 = 3 (2 before the echo)

Reading Note 2 – PHP 5 Advanced OOP and Design Patterns

Problem of Object Orient in PHP4.

  1. pass an object to a variable, a copy of the object would be created unless you pass it by reference (&)
  2. prevented implementing some additional features on top of the existing object model, such as public/private/protected, unified constructor/destructor name, interfaces, instanceof (instead of is_a() in PHP4), final methods/classes, __clones, class constants, static methods/members, abstract classes/methods, class type hints in function declarations, iterators, __autoload()

New features in PH5

  1. Error handling
  2. foreach with references and pass references into function
  3. all XML extensions have been rewritten to use the superb libxml2 XML toolkit
  4. New MySQLi (MySQL Improved) Extension
  5. SQLite extension
  6. Tidy Extension
  7. Perl Extension
  8. New Memory Manager
  9. drop support for windows 95

Reading Note 1 – PHP 5 Advanced OOP and Design Patterns

Main Different between PHP3 and PHP4

While PHP 3 still continuously parsed the scripts while executing them, PHP 4 came with a new paradigm of “compile first, execute later.” The compilation step does not compile PHP scripts into machine code; it instead compiles them into byte code, which is then executed by the Zend Engine, the new heart of PHP 4.

  1. PHP 4.1.0, introduced superglobals such as $_GET and $_POST. Superglobals can be accessed from within functions without having to use the global keyword. This feature was added in order to allow the register_globals INI option to be turned off.
  2. PHP 4.2.0 With the new superglobals in place, on April 22, 2002, it was released with the register_globals turned off by default.
  3. PHP 4.3.0, the last significant PHP 4 version, was released on December 27, 2002. This version introduced the Command Line Interface (CLI), a revamped file and network I/O layer (called streams), and a bundled GD library.

What’s register_golbals – why it’s bad

register_globals is a feature in PHP which automatically converts input variables like “?foo=bar” in to a PHP variable called $foo. Because many people do not check input variables properly, many applications had security holes, which made it quite easy to circumvent security and authentication code.

Main features of PHP5

  1. Rewrite the Object Oriented part
  2. new SimpleXML extension
  3. SOAP
  4. MySQLi

Work with Litle PHP SDK

In a recent project, we need to process Credit Card on real time. The vendor we use is Litle. Litle provides some SDK libraries including PHP, JAVA, .NET, RUBY, and PYTHON, but lack of documentation. They host the code in Github, and we grab the php SDK from there.

After download the source code, you can run Setup script (under litle-sdk-for-php-master/lib/). During the setup, you can choose Litle URL including different environments. For playing, you may choose sandbox, which has no credentials required and no special access needed. Basically, it will generate litle_SDK_config.ini as shown in the following:

user =USER
password =PASSWORD
currency_merchant_map ['DEFAULT'] =123456
url =
proxy =
version = 8.13
timeout =  65
reportGroup = Default Report Group

And then you can run the testing script named SampleDriver.php (under litle-sdk-for-php-master/test/). If you are using PHP V5.2+, then you should be ok. But if you are running lower version PHP, then you may see the error, as the following,

[24-Jan-2013 15:25:08] PHP Notice:  Undefined index:  currency_merchant_map in /home/test/litle-sdk-for-php-master/lib/Obj2xml.php on line 94
[24-Jan-2013 15:25:09] PHP Fatal error:  Uncaught exception 'Exception' with message 'Unknown SSL protocol error in connection to ' in /home/test/litle-sdk-for-php-master/lib/Communication.php:44

The reason is that in PHP 5.1.6, the pharse_ini_file() function does not recognize the format of ini file generated by Setup script. No sure why, if you know please leave comment below. So if there is a case, then you can change the format of litle_SDK_config.ini as shown in the following:

user =USER
password =PASSWORD
merchant_id =123456
url =
proxy =
version = 8.13
timeout =  65
reportGroup = Default Report Group

And you also need to change the logic in Obj2xml.php, on line 94, do the following change,

//$config['merchantId'] = $config_array['currency_merchant_map']['DEFAULT'];
$config['merchantId'] = $config_array['merchantId'];

Then, you should be all set to test against Litle sandbox.

OK, now let’s move on to Litle Cert environment. First update the url in litle_SDK_config.ini file to be,

;url = 
url =

And then run SampleDriver.php under test folder. You may got another headache, at least it happened to us. It’s SSL Certificate problem, as the show in the following,

PHP Fatal error:  Uncaught exception 'Exception' with message 'SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed' in .....

In fact, this php curl issue, if you Google it, and you may see a lot of people had this issue (I’m glad if you come to this article by searching this in Google :-)). OK, let’s check Communication.php under lib folder,

class Communication{
   function httpRequest($req,$hash_config=NULL){
      $config = Obj2xml::getConfig($hash_config);
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_PROXY, $config['proxy']);
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: text/xml'));
      curl_setopt($ch, CURLOPT_URL, $config['url']);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
      curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, true);
      curl_setopt($ch, CURLOPT_TIMEOUT, $config['timeout']);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
      //you need define CURLOPT_CAINFO, if you set CURLOPT_SSL_VERIFYPEER to be true
      curl_setopt($ch, CURLOPT_CAINFO, "YOUR-CERT-PATH/ca-bundle.crt");
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,2);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_SSLVERSION, 3);
      $output = curl_exec($ch);
      $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      if (! $output){
         throw new Exception (curl_error($ch));
         return $output;


On line 14, we define CURLOPT_CATINFO, which is missing in original Communication.php. What’s CURLOPT_CATINFO? As state in,

The name of a file holding one or more certificates to verify the peer with. This only makes sense when used in combination with CURLOPT_SSL_VERIFYPEER.

And where can we download ca-bundle.crt? Here are two handy scripts to generate ca-bundle.crt,
1. For linux –
2. For windows –

Note that you need to save them with correct extension, ‘pl’ and ‘vbs’ separately, not text file. And then run the script, and it will generate ca-bundle.crt for you. Also you need to use absolute path when you define CURLOPT_CAINFO. For example:

curl_setopt($ch, CURLOPT_CAINFO, "/home/tester/ca-bundle.crt");
curl_setopt($ch, CURLOPT_CAINFO, "C:\CERT\ca-bundle.crt");

Run PHP in command line in Netbeans

PHP is a web programming language, but sometimes you may want to run PHP as script (in the command line,) in the other words not showing the results in browser. You can actually do this in Windows environment with Netbeans. Here is how,

1. Grab an PHP interpreter – The easiest way is to download WAMP server
2. Define PHP interpreter for NetBeans – Go to Tools > Options > PHP, and then set up your PHP interpreter, as shown in the following figure.
3. Set Run Configuration for your project – Right click on your project > Click Properties OR set Properties when you create a new project, and set Run As to be ‘Script (run in command line) as shown in the following figure.
4. Pretty much those are what we need, but remember when you run a script, don’t use “Run Project” button on the toolbar, instead, right click on the Source window, and click ‘run file’, as shown in the following figure.
run file in netbeans

That’s it!

Nginx Log Rotation

One of my site is running on Nginx server, and the logs (access log and error log) is getting large very quick . I don’t want to turn it off, because sometime I need to check them. Without using log rotation, I think it’s not good for performance because write into a large file (says 1G) could be slow (correct me if you don’t agree), and another big issue is that it takes long time to open a large log file. So I wanted to rotate the logs.

I found that in fact, the log rotation was already enabled in my server, which is configured by “/etc/logrotate.d/nginx”. Open that file I see the following content,

/var/log/nginx/*log {
    rotate 10
        /etc/init.d/nginx reopen_logs

The reason my site’s log was not being rotated is because when I set up this site, the log path was not under “/var/log/nginx/.”

It’s easy to fix. Open “/etc/nginx/conf.d/mysite.conf”, and edit the paths of access_log and error_log to be under /var/log/nginx/ will fix the problem.

Note: my server is running ‘CentOS release 6.3’ and the nginx version is 1.2.5, so the path info mentioned in the article may not suitable to your system, but you should be able to do the similar settings.