how to use phing to build php projects

by Hamid Reza Fahimi Madjd @ Jun 25, 2011

Some days ago I found a solution to build php project that called Phing.
Phing is a build framework based on Apapche Ant. If you are familiar with Ant and its role in Java *E projects, you can learn Phing very fast.
Like Ant, there is a (or more) build file named build.xml (default name) to define operations that you like occur on your project.

Now i'm going to describe it by a practical example:

Consider a php project with following structure:

Project
|_src
|__package1
|___class1.php
|___class2.php
|__package2
|__package3
|_static
|_templates
.htaccess
build.xml
config.php
index.php

Scenario:
I want "build.xml" do following operations:

  1. export project from subversion repository and copy it to a temp directory
  2. make an archive file and name it based on latest version number
  3. copy archive file to a remote server over ssh (scp)

I made build.xml file put following code in it:

<?xml version="1.0" encoding="UTF-8"?>
<!-- define project name and default target -->

<project name="my-project" default="dist">

<!-- define some properties (variables) -->
  <property name="path.dive.root" value="/home/hamid/temp" />
  <property name="path.dive" value="${path.dive}/${phing.project.name}" />

<!-- empty related temp directory (delete old one and create new one) -->
  <target name="prepare">
    <echo msg="delete and create ${path.dive} directory" />
    <delete dir="${path.dive}" includeemptydirs="true" verbose="true" failonerror="true" />
    <mkdir dir="${path.dive}" />
  </target>

  <target name="build" depends="prepare">

<!-- export project from reposiroey and copy to temp directory -->
    <svnexport
    svnpath="/usr/bin/svn"
    username="username" password="password"
    force="true" nocache="true"
    repositoryurl="svn://localhost/${phing.project.name}/"
    todir="${path.dive}"/>

<!-- get latest version number and save in svn.lastrevision property -->
    <svnlastrevision
    svnpath="/usr/bin/svn"
    workingcopy="${path.source}"
    repositoryurl="svn://localhost/${phing.project.name}"
    propertyname="svn.lastrevision"/>

<!-- generate archive file name -->
   <property name="archive.filename" value="${phing.project.name}-v${svn.lastrevision}.tar.gz" />
  </target>

  <target name="dist" depends="build">

<!-- archive directory and save it -->
    <tar destfile="${path.dive.root}/${archive.filename}" basedir="${path.dive}" compression="gzip"/>

<!-- copy archive file and copy to sources foler on remote server -->
    <scp username="username" password="password"
    host="host"
    todir="sources/"
    file="${path.dive.root}/${archive.filename}" />
  </target>
</project>

after that go to path that build file is there and type:

$ phing

cause build file name is build.xml, it's not necessary to specify it.
Also if you use PhpStorm, you can add build.xml to Phing Build tool window and deal with that inside the IDE.
Now, I did build process just in 10 Seconds instead of 5 Minutes.

I hope this example encourage you to use Phing.
You can get more detail information from its website.

phing, php comments no comment

slice/paging large contents using php

by Hamid Reza Fahimi Madjd @ Nov 28, 2010

Some days ago i was engaged in wap version of a web based application that had to prepare large content (like articles) for mobile devices.

considering limitation of mobile devices, i decided to slice content to specified bytes (1500 Bytes) and display sliced content instead whole content.

so i wrote a snip code that :

  1. fetch specified bytes
  2. continue to fetching (in both side, left and right) untill get first new line character
define('BYTES_PER_PAGE', 1500);
define('PAGE_NO', ((int)@$_GET['page']) == 0? 1: (int)@$_GET['page']);
$len = mb_strlen($description, 'utf-8');

if($len > BYTES_PER_PAGE) {
  $len = ($len%BYTES_PER_PAGE == 0? (int)$len/BYTES_PER_PAGE: (int)($len/BYTES_PER_PAGE)+1 ) ;
  $start = (PAGE_NO - 1) * BYTES_PER_PAGE;
  $end = PAGE_NO * BYTES_PER_PAGE;

  // go back till get first new line char
  while($start > 0 && ord(mb_substr($description, --$start, 1, 'utf-8')) != 10);

  // go forward till get first new line char
  while($end < mb_strlen($description, 'utf-8') && ord(mb_substr($description, $end++, 1, 'utf-8')) != 10);
  $description = mb_substr($description, $start, $end-$start, 'utf-8');
}

as you see, because of utf8 string, i used  mb_* functions, you can replace it with normal string functions.

php comments no comment

how to log methods call in php ?

by Hamid Reza Fahimi Madjd @ Oct 6, 2010

as you know there are a lot of logging api that you can use theme to follow users activity, errors and etc. but i needed a logging api that log methods call and their passed variable through them.

so i wrote a snip code using debug_backtrace function and ReflectionMethod class to do that, i made 2 tables named activity_log to save called method information and activity_log_param to save parameteres name and its (serialized) value:

class Log {
  protected function log($result, $message = null) {
    $activitySql = 'insert into activity_log(caller, class, method, method_type, result, message, ip, agent) '.
        'values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';

    $pure = next(debug_backtrace(false));
    // create a mysql query object and run the query using bind parameters and return generated autoincrement id
    $newOid = QueryBuilder::create($activitySql)->write(array(
        $pure['file'],
        $pure['class'],
        $pure['function'],
        $pure['type'],
        $result,
        $message,
        getIp(),
        getUserAgent()
      ),true);

    $paramsSql = 'insert into activity_log_param(fk_activity_log_oid, pname, pvalue, serialized) values ';

    $reflectionMethod = new ReflectionMethod($pure['class'] . '::' . $pure['function']);
    $pNames = $reflectionMethod->getParameters();
    $pValues = $pure['args'];
    $tmp = '';

    foreach($pNames as $idx=>$obj) {
      $pValue = null; $serialized = 'no';
      if(!isset($pValues[$idx])) {
        $pValue = null;
      }
      else {
        if(is_object($pValues[$idx])) {
          $pValue = serialize($pValues[$idx]);
          $serialized = 'yes';
        }
        elseif(is_array($pValues[$idx])) {
          $pValue = serialize($pValues[$idx]);
          $serialized = 'yes';
        }
        else {
          $pValue = $pValues[$idx];
        }
      }
      $tmp .= '(' . $newOid . ', '' . $obj->name . '', '' . $pValue . '', '' . $serialized . ''), ';
    }
    if(!empty($tmp)) {
      $paramsSql .= substr($tmp, 0, -2) . ';';
      return QueryBuilder::create($paramsSql)->write();
    }

  }
}

because debug_backtrace() function doesn't return parametere name, i used ReflectionMethod class to get parameters name.

how to use it? inherit your class from Log class and call log() method to log called method information:

CLass MyClass extends Log {
  public function foo($oid, array $sampleArray, Object $sampleObject) {
    parent::log(true, 'done');
  }
}

 

php comments no comment

backup from mysql database's routines

by Hamid Reza Fahimi Madjd @ Apr 11, 2009

Sometimes we need get backup just from mysql database's routines.
command below shows us how we can do that:

mysqldump dbname -uusername -p -Rtd > /path/to/your/dump/file
-u username
-p prompt password
-R stored procedures and functions
-t prevent writing table creation
-d "       "       row information
mysql comments no comment

sql IN logical operation for java

by Hamid Reza Fahimi Madjd @ Apr 20, 2009

Hi,
have you ever needed sql IN for java language ?
OK, in this post I'm going to use new java 5 feature (varargs method) to simulate sql IN:

public static boolean in(int i, int... ints) {
Arrays.sort(ints);
return Arrays.binarySearch(ints, i) >= 0;
}

as you see, our function gets 2 parameters, first one is your desired value and second one is your search list.
now, when you call the method:

public static void main(String[] args) {
System.out.println(in(1, 2, 3, 4, 5, 1));
}

it returns:

true

i hope you find this tip useful;

java comments no comment

last tweet