Archives for 听风看海
js is weird
Published on June 1, 2011
Create dijit declaratively
Published on May 22, 2011
Using programmatically way to create a dijit is flexible and clear. You can use this dijit as an object after creating.
var btn = new dijit.form.Button({label: 'click me'});
Sometime we have to create dijit declaratively. In order to do some initialization works or connect a callback function to the dijit or override a function of dijit you can using the following code.
javascript needed by initialization of dijit
<script type=”dojo/method”></script>
connect a callbacl to dijit
<script type=”dojo/connect” event=”save” args=”someParams”></script>
js code which will be run when the save() function of the dijit is called. This is just like
dojo.connect(yourDijit, 'save', function(){});
override function in dijit
<script type=”dojo/method” event=”onChange” args=”someParams”></script>
Using Sha512 with Zend_Auth
Published on May 17, 2011
Normally we can use setCredentialTreatment(‘MD5(?)’); or setCredentialTreatment(‘SHA1(CONCATE(?, salt))’); to encode the password. But sha1 and MD5 has security flaws and shouldn’t be used for new application. MySQL 5.1 doesn’t support SHA2 (MySQL 5.5 has function about SHA2) we have to encode the user input by ourselves. The way is to write a calss extends Zend_Auth_Adapter_DbTable.
class Adapter extends \Zend_Auth_Adapter_DbTable
{
/**
* _saltColumn
* the column name for salt password
*
* @var string
*/
private $_saltColumn;
/**
* setSaltColumn
*
* @param String $saltColumn
* @return Mweb\Auth\Adapter
*/
public function setSaltColumn($saltColumn)
{
$this->_saltColumn = $saltColumn;
return $this;
}
/**
* getSaltColumn
*
* @return string
*/
public function getSaltColumn()
{
return $this->_saltColumn;
}
/**
* authenticate
*
* @return void
*/
public function authenticate()
{
$saltColumn = $this->getSaltColumn();
if(!is_null($saltColumn)) {
$salt = $this->_zendDb->fetchOne("SELECT {$saltColumn} FROM " .
$this->_tableName . " WHERE {$this->_identityColumn} = ?",
$this->_identity);
$this->setCredential(hash('sha512', $this->_credential . $salt));
return parent::authenticate();
} else {
throw new \Exception("salt column is not set");
}
}
}
get php 5.3.6 with iconv on snow leopard
Published on April 21, 2011
In order to generate Captcha with Zend Framework the php needs to be compiled with the option freetype. But the php shiped by snow leopard is compiled without this option. To solve this problem I have to compile the PHP myself. But there is always problem when PHP is compiled with the option iconv. After two nights I found a way.
1. install macports http://www.macports.org/
2. install php5 and the extensions (GD, MySQL etc)
3. I can’t find iconv extension by macport, so compile iconv.so by yourself
3.1 download php source code from http://php.net/downloads.php
3.2 because php5 and most of extensions are installed through macport, just iconv.so is needed to be complied.
cd phpsource/ext/iconv
phpize
./configure
make
make install
After install iconv.so will be copied in /opt/local/lib/php/extensions/no-debug-non-zts-20090626/
3.3 add iconv.so to php.
touch /opt/local/var/db/php5/iconv.ini
vi /opt/local/var/db/php5/iconv.ini
add “extension=iconv.so” into the iconv.ini
That all!
manually start drop on linux
Published on March 30, 2011
Recently my dropbox on linux didn’t start automatically at login. I spent some time to figure out how to start dropbox manually. In linux it is simple, using dropbox command
>dropbox
then you can can see the options.
Enable dojo for a zend project
Published on March 29, 2011
To enable dojo in your zend framework project is quit easy by using application resource. What you need to do is just add the following code into your application.ini
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts" resources.layout.layout = "layout" resources.dojo.enable = true resources.dojo.djConfig.parseOnLoad = 1 resources.dojo.localPath= "/js/dojo/dojo.js" resources.dojo.registerdojostylesheet = true resources.dojo.requireModule[] = "dojo.io.script" resources.view.encoding = "UTF-8" resources.view.basePath = APPLICATION_PATH "/views/"
Then add following code in the view or layout
echo $this->dojo();
TDD improves your code design
Published on March 19, 2011
What makes Unit Test so difficult
the revolution from global variable to singleton to registry to dependency injection.
“One of the hallmarks of testability is a loose coupling of classes, allowing you to isolate a single class and test it completely”
—- http://code.google.com/p/google-singleton-detector/wiki/WhySingletonsAreControversial
* unit test could prevent writing code with too many dependencies, in other words the TDD is good for the design of object.
What is dependency
If class A uses class B, class A depends on class B.
Like in book PHP in action explained, there are two kind of dependencies in the following code. First dindeDeveloper() create an variable $dbh and then use query() method of this variable.
class EmployeeMapper()
{
public function findDeveloper()
{
global $dbh;
$sql = “SELECT * FROM employee WHERE salary < 3000”;
$rows = $dbh->query($sql);
// ….
}
}
After changing the code we can remove the first dependency
class EmployeeMapper()
{
public function findDeveloper($dbh)
{
$sql = “SELECT * FROM employee WHERE salary < 3000”;
$rows = $dbh->query($sql);
// ….
}
}
Requirement
We want to write a Data Mapper, which is in charge of get/set information of employee from/into database. The interface is like in the following code.
class EmployeeMapper()
{
function findAllDevelopers()
{
}
function findAllManagers()
{
}
}
We need database handler to implement this functions. The interesting thing is how we use the database handler. (Database handler is just one of the typical resources, which is need in all over the application and we need just one instance.)
Global variable
$dsn = ‘mysql:host=localhost;dbname=company’;
$dbh = new PDO($dsn, ‘dbuser’, ‘dbpass’);
class EmployeeMapper()
{
public function findDeveloper()
{
global $dbh;
$sql = “SELECT * FROM employee WHERE salary < 3000”;
$rows = $dbh->query($sql);
// ….
}
public function findManager()
{
global $dbh;
$sql = “SELECT * FROM employee WHERE salary > 3000”;
$rows = $dbh->query($sql);
// ….
}
}
This implementation is simple and straightforward. The disadvantage is if another file a developer changed the $dbh, all other code about database CRUD don’t work anymore. This happens because we could not know where and how the modification of a global variable might happen. Using singleton pattern we can avoid these problem.
Singleton
class DB {
private $_dbh;
private function __construct()
{
}
public static function getInstance()
{
if (is_null($this->_dbh)) {
$dsn = ‘mysql:host=localhost;dbname=company’;
$this->_dbh = new PDO($dsn, ‘dbuser’, ‘dbpass’);
} else {
return $this->_dbh;
}
}
}
class EmployeeMapper()
{
public function findDeveloper()
{
$dbh = DB::getInstance();
$sql = “SELECT * FROM employee WHERE salary < 3000”;
$rows = $dbh->query($sql);
// ….
}
public function findManager()
{
$dbh = DB::getInstance();
$sql = “SELECT * FROM employee WHERE salary > 3000”;
$rows = $dbh->query($sql);
// ….
}
}
Now it is much better. The developer could not change the database resource except changing the DB class. And we can guarantee that just one database handler is used. If later we change the database from MySQL to Postgresql we can just change the DB class. Everything seems fine now. But one of the developer wants to test the EmployeeMapper using SQLite instead of MySQL, what could he do? Change the DB class , run the test then change the DB back? Bad way. Image what happens when he forgets to change the DB class back and checked it into the trunk. Chang the source code for testing is a bad way! It makes also difficulty when one of the customers wants using MySQL at the same time the other customer wants to use Postgresql. The problem here is switching the resource, here is the database resource, which is created by singleton is difficult. We want make it configurable.
We can extend the DB class and let it read some configuration.
public static function getInstance()
{
if (is_null($this->_dbh)) {
$config = parse_ini_file(‘application.ini’);
$dsn = $config[‘dsn’];
$this->_dbh = new PDO($dsn, ‘dbuser’, ‘dbpass’);
} else {
return $this->_dbh;
}
}
But the class of DB is not only in charge of creating database resource but also switching algorithm. This against the “one class do one thing”. When the algorithm becomes more and more complicated the code of DB class is difficult to manager. A unit test to test the algorithm could also difficult. Using registry pattern we can move the code about the switching algorithm out of DB class.
And when we use singleton in this way, the mockup object could not be used to change some behaviours. Because we need a way to inject the mockup object to the class or the methods. To improve it look at the section about DI.
Registry
class MySQLDB {
private $_dbh;
private function __construct()
{
}
public static function getInstance()
{
if (is_null($this->_dbh)) {
$dsn = ‘mysql:host=localhost;dbname=company’;
$this->_dbh = new PDO($dsn, ‘dbuser’, ‘dbpass’);
} else {
return $this->_dbh;
}
}
}
class EmployeeMapper()
{
public function findDeveloper()
{
$dbh = Registry::get(‘db’);
$sql = “SELECT * FROM employee WHERE salary < 3000”;
$rows = $dbh->query($sql);
// ….
}
public function findManager()
{
$dbh = Registry::get(‘db’);
$sql = “SELECT * FROM employee WHERE salary > 3000”;
$rows = $dbh->query($sql);
// ….
}
}
class Bootstrap()
{
public function initDB()
{
$dbh = MySQLDB::getInstance();
Registry::set(‘db’, $dbh);
}
}
for the test we want to use SQLite instead of Mysql, then we implement a new database resource.
class SQLiteDB
{
private $_dbh;
private function __construct()
{
}
public static function getInstance()
{
if (is_null($this->_dbh)) {
$dsn = ‘sqlite:host=localhost;dbname=company’;
$this->_dbh = new PDO($dsn, ‘dbuser’, ‘dbpass’);
} else {
return $this->_dbh;
}
}
}
class BootstrapForTest
{
public function initDB()
{
Registry::set(‘db’, SQLiteDB::getInstance());
}
}
class EmployeeMapperTest extends PHPUnit_Framework_Testcase
{
public function testFindAllDeveloper()
{
//....
}
}
* the implementation of a registry is not written here, you can find a lot of example in the web.
Till now the code is more flexible. But we have still write “Registry::get(‘db’)” everywhere, where we want to use the database resource. In other words the EmployeeMapper has to get the resource what it needs. Dependency Injection is another way to do the same work. By using DI the needed resources are push to EmployMapper by a container. EmployeeMapper has no idea how these resources come.
Dependency Injection
class EmployeeMapper()
{
public function setDbh(PDO $dbh)
{
$this->_dbh = $dbh;
}
public function getDbh()
{
return $this->_dbh;
}
public function findDeveloper()
{
$dbh = $this->getDbh();
$sql = “SELECT * FROM employee WHERE salary < 3000”;
$rows = $dbh->query($sql);
// ….
}
public function findManager()
{
$dbh = $this->getDbh();
$sql = “SELECT * FROM employee WHERE salary > 3000”;
$rows = $dbh->query($sql);
// ….
}
}
The EmployeeMapper now is pure! No any global function or variable. In this class there is just the business logic. The DI container takes care what the resources it needs at run time. The dependency information are usually written in a configuration file i.e. an XML file.
What we can do without a DI container and benefit from DI is like:
class EmployeeMapper()
{
public function __construct(PDO $dbh=null)
{
if (is_null($dbh)) {
$this->setDbh(Registry::get(‘db’));
} else {
$this->setDbh($dbh);
}
}
public function setDbh(PDO $dbh)
{
$this->_dbh = $dbh;
}
public function getDbh()
{
return $this->_dbh;
}
public function findDeveloper()
{
$dbh = $this->getDbh();
$sql = “SELECT * FROM employee WHERE salary < 3000”;
$rows = $dbh->query($sql);
// ….
}
public function findManager()
{
$dbh = $this->getDbh();
$sql = “SELECT * FROM employee WHERE salary > 3000”;
$rows = $dbh->query($sql);
// ….
}
}
With this way, we can change the resource if we want and using the default for usual cases.
What beautiful in this implementation is that the EmployeeMapper doesn’t depend on the implementation it depends on Interface
A better way is using Factory to create EmployMapper object. And let Factory finish the dependency injection.
class EmployeeMapper()
{
public function __construct(PDO $dbh=null)
{
$this->setDbh($dbh);
}
// …..
}
class EmployeeMapperFactory
{
public function create()
{
return new EmployeeMapper(Registry::get(‘db’));
}
}
The topic about DI is big if you want more information look at the following reference links. DI could be looked as a way to create new object instead of using factory or “new”.
*symfony has a DI project http://components.symfony-project.org/dependency-injection/documentation
* best known DI container in Java world is Spring http://www.springsource.org/about
* Guice is another DI container http://code.google.com/p/google-guice/
compress and uncompress on strato host
Published on March 12, 2011
FTP doesn’t support compress and uncompress. Using SFTP instead of FTP. For the user whose package is greater than PowerPlus, you can login to your host with ssh. And you will get a unix shell. With the shell you can do all things the linux can.
Netbeans 折叠代码
Published on March 11, 2011
最近在修改公司老早之前的代码,里面的function大多长达一百多行,看起来超级痛苦。如果可以吧方法里的一些部分折叠起来会看的清楚些。netbeans 默认是可以折叠(folding) function的,如果需要自定义的折叠一部分代码可以在代码里写入下面的标签
//<editor-fold desc=" read report info from database">
... 这里是需要折叠隐藏的代码
//</editor-fold>
如此,就可以把当前不需要特别注意的代码折叠起来了。
