• php的动态代理的又一种实现

    神仙 2006-01-28 15:23
     
                     本来php4里,在对象内部是可以对$this赋值的(或许是bug)。但php5不让这样了,如果对$this赋值会引发一个fatel error:can not re-asign to $this。今天突然想到了一个办法。既然不让对$this赋值,那能不能绕个圈实现呢?
    运行一下下面的代码
    <?php
    class Container {
        public $foo;
        function __construct() {
            $this->foo=new Proxy($this);
        }
    }
    class Proxy {
        private $container;
        function __construct(&amp;$container) {
            $this->container=$container;
        }
        function go() {
            $this->container->foo=10;
        }
    }
    $c=new Container;
    echo "开始\n";
    echo 'gettype($c->foo) = \''.gettype($c->foo)."'\n";
    echo 'get_class($c->foo) = \''.get_class($c->foo)."'\n";
    echo "然后\n";
    $c->foo->go();
    echo 'gettype($c->foo) = \''.gettype($c->foo)."'\n";
    echo '$c->foo = '.$c->foo."\n";
    ?>
    结果是:

    开始
    gettype($c->foo) = 'object'
    get_class($c->foo) = 'Proxy'
    然后
    gettype($c->foo) = 'integer'
    $c->foo = 10

    可以看到,$c->foo已经从一个Proxy对象变成了一个整数,而这一切是在对象内部完成的。这样,我们就可以做一个清爽的动态代理了。

    class Container {
        var $p;
        function __construct() {
            $this->p=new Proxy($this,'p','Target');
        }
    }

    class Target {
        var $v=777;
    }

    class Proxy {
        private $container;
        private $property;
        private $className;
        function __construct(&amp;$container, $property, $class) {
            $this->container=&amp;$container;
            $this->property=$property;
            $this->className=$class;
        }

        function __get($key) {
            $class=$this->className;
            $obj=new $class;
            $property=$this->property;
            $this->container->$property=$obj;
            return $obj->$key;
        }

        function __call($func, $arg) {
            $class=$this->className;
            $obj=new $class;
            $property=$this->property;
            $this->container->$property=$obj;
            return call_user_func_array(array($obj,$func), $arg);
        }
    }

    $c=new Container;
    echo get_class($c->p)."\n";
    echo $c->p->v."\n";
    echo get_class($c->p)."\n";
    echo $c->p->v."\n";
    可以看到,使用代理和使用实际对象没有区别,而且当第二次访问的时候,$c->p已经变成了实际的对象了。


                 
  • 重构

    神仙 2006-01-26 15:32
      Martin说,如果你添加新功能的时候遇到了困难,就重构它。今天算是认识了。做获取数据集的时候,很多东西和获取单个数据的是一样的,想重复利用,但感觉很困难。就把代码重构了一下,把得到sql的部分抽出来,单独弄了个类,然后把两个函数搬到数据库抽象层去,现在就好办了。

  • 程序接口

    神仙 2006-01-25 14:03
     在弄一个ORM。
    取一个数据集的时候大致是这样。
    $dataSet=$manager->getList($filter);
    需要一个过滤条件,相当于select语句的where子句
    考虑了很多形式
    一开始想
    $filter->addFilter('Author::name=="XiaoWang"');
    似乎很直观。但后来写测试的时候发现一个问题。如果用户用字符串值,还要自己去处理转义。
    看了下hibernate的方法,是类似于
    $filter->add(Condition::eq('Author::name',"XiaoWang"));
    感觉很怪。我想没必要去追求完美的面向对象结构,好用就行,就先弄成这样:
    $filter->add('Author::name','==',"XiaoWang");
    反正以后修改涉及的地方也就这一个类和TestCase。

  • 单元测试

    神仙 2006-01-19 14:14
      最近在改自己的php的ORM。尝试用phpunit2自动测试。有了这个确实很舒服。看一个'ok'比人工比较结果方便多了,而且Test Case还可以重复利用。改了一点就运行一下测试,如果ok了就继续。不过phpunit2有时候会莫名其妙什么都不出来,过一会又会好了,不知道室那里的问题。

                 
  • javascript你可能不知道的5

    神仙 2006-01-17 20:17
    javascript中,break, continue可以有一个标签,来方便的跳到几层之外。
    outer:
    for(i=0;i<5;i++){
    for(j=0;j<5;j++){
    if(j==2)
    break outer;//
    document.write(i+', '+j+'; ');
    }
    }
    比较一下不加outer的情况。也试验一下continue。很有用吧
  • javascript你可能不知道的4

    神仙 2006-01-14 13:59
    javascrip中可以用function来定义一个类

    function Base(){
        this.foo=function(){
            return 'base';
        }

    }

    那怎么实现类的继承呢?

    function Derive1(){
        this.foo=function(){
            return 'derive';
        }

    }

    Derive1.prototype=new Base();

    var obj1=new Derive1();

    alert(obj1.foo());



    还有另外一种方法:

    function Derive2(){
        this.parent=Base;
        this.parent();
        this.bar=function(){
            return 'bar';
            }

    }

    var obj2=new Derive2;

    alert(obj2.foo());
    用这种方法还能实现多继承。
    function Base2(){
        this.bar=function(){
            return 'base2';
        }
    }
    function Derive3(){
        this.base1=Base;
        this.base1();
        this.base2=Base2;
        this.Base2();
    }
    var obj3=new Derive3;
    alert(obj3.foo());
    alert(obj3.bar());

  • javascript你可能不知道的3

    神仙 2006-01-10 13:08
    var arr=[1,2,3,4,5];
    delete(arr[2]);
    alert(arr.length);
    alert(arr);
    看看结果,是不是有点意外呢?
    var arr=[1,2,3,4,5];
    arr.length=3;
    alert(arr);
    length还是可写的。这样能方便得截短一个数组。
  • javascript你可能不知道的2

    神仙 2006-01-06 17:32
    另一种创建对象的方法:
    var obj={
    a:10,
    b:20,
    c:function(){
    alert('c');
    }
    };

    alert(obj.a);
    alert(obj.b);
    obj.c();

    这样似乎比
    obj.a=10;
    obj.b=20;
    obj.c=function(){
    alert('c');
    }
    更加清楚点。
    不过,中间的分隔是逗号,不是分号。

  • javascript你可能不知道的1

    神仙 2006-01-04 19:16
    对象还可以当hash表用。 
    var obj;
    obj.a=10;
    obj.b=20;

    alert(obj["a"]);
    alert(obj["b"]);

    对象也可以像数组一样用for in循环来遍历。

    for(e in obj){
    alert(e);
    }

    这样还让javascript有了动态访问对象成员的能力。对函数同样有用
    obj.foo=function(){
    alert('foo');
    }

    obj['foo']();
  • sqlserver啊。。。

    神仙 2005-12-10 22:05
    一直在找sqlserver的好的分页方案,一直都没找到。
    看过php的adodb的实现,今天看到透明的blog上说ror有内置分页功能,就去看了下源代码。
    结果都是一样的方法。考虑了通用性,但效率就不行了。
    又看了hibernate的代码,居然是
    if (offset>0) throw new UnsupportedOperationException("sql server has no offset");
    。。。。。。
    高效和通用看来是不可兼得了。

    有limit就是好啊

日历

关于神仙

神仙

世人都晓神仙好~~~~