• PHP 获取 DOM 节点的 innerHTML

    dom 没 innerHTML 方法,直接 $dom->saveXML($node) 获取的相当于 outerHTML。所以得小折腾一下。

    $e = $dom->getElementById('sample');
    $content = '';
    foreach ($e->childNodes as $node) {
        $content.= $dom->saveXML($node);
    }

     

    Tags: php dom
  • 一个 php 对象数组转型的神奇结果

    群里说起 php 的数组 key 的类型转换问题,

    比如 $a = array('123'=>'abc'); var_dump($a); 会发现 key 会变成整数。用 $a['123'] 这种方式访问数组的时候,也会先把 key 转换成整数。突然想到能不能构造一个实际 key 为字符串形式的数字的数组,或者整数型属性名的对象(对象内部也是个 hash,也同时支持整数和字符串 key)。试了一些方法没成功。然后看到了这篇东西

    http://www.laruence.com/2010/05/26/1541.html

    就想到了个构造那样的数组和对象的方法。

    $o = new stdClass();
    $o->{'123'} = 1;
    $a = (array) $o;
    var_dump($a);
    var_dump(isset($a['123']));
    var_dump(isset($a[123]));

    $a = array(1,2,3);
    $o = (object) $a;
    var_dump($o);
    var_dump(isset($o->{1}));
    var_dump(isset($o->{'1'}));

    这样就构造出了正常方式没法访问的数组下标和对象属性*(访问对象属性时会把属性名转成字符串)。

    还可以干一件更 BT 的事情,访问对象的私有或保护属性。

    class Test {
        private $a = 1;
        protected $b = 2;
        public $c = 3;
    }
    $o = new Test();
    $a = (array) $o;
    var_dump($a);
    var_dump($a["\0Test\0a"]);
    var_dump($a["\0*\0b"]);

     

     

    Tags: php
  • php 版简单 Trie 树

    用 php 写了一个简单的 Trie 树,可以用来做字符串匹配。

    <?php
    
    $words = array(
    '123','145','43'  
    );
    
    class Trie {
        /**
         *
         * 节点数组。每个节点为二元组,依次为是否叶子节点,子节点.
         * @var array $nodes
         */
        protected $nodes;
        
        /**
         * 
         * @var array $words 关键词数组
         */
        function __construct($words) {
            $this->nodes = array( array(false, array()) ); //初始化,添加根节点
            $p = 1; //下一个要插入的节点号
            foreach ($words as $word) {
                $cur = 0; //当前节点号
                for ($len = strlen($word), $i = 0; $i < $len; $i++) {
                    $c = ord($word[$i]);
                    if (isset($this->nodes[$cur][1][$c])) { //已存在就下移
                        $cur = $this->nodes[$cur][1][$c];
                        continue;
                    }
                    $this->nodes[$p]= array(false, array()); //创建新节点
                    $this->nodes[$cur][1][$c] = $p; //在父节点记录子节点号
                    $cur = $p; //把当前节点设为新插入的
                    $p++; //
                }
                $this->nodes[$cur][0] = true; //一个词结束,标记叶子节点
            }
        }
        
        function match($s) {
            $ret = array();
            $cur = 0; //当前节点,初始为根节点
            $i = 0; //字符串当前偏移
            $p = 0; //字符串回溯位置
            $len = strlen($s);
            while($i < $len) {
                $c = ord($s[$i]);
                if (isset($this->nodes[$cur][1][$c])) { //如果存在
                    $cur = $this->nodes[$cur][1][$c]; //下移当前节点
                    if ($this->nodes[$cur][0]) { //是叶子节点,单词匹配!
                        $ret[$p] = substr($s, $p, $i - $p + 1); //取出匹配位置和匹配的词
                        $p = $i + 1; //设置下一个回溯位置
                        $cur = 0; //重置当前节点为根节点
                    }
                } else { //不匹配
                    $cur = 0; //重置当前节点为根节点
                    $i = $p; //把当前偏移设为回溯位置
                    $p = $i + 1; //设置下一个回溯位置
                }
                $i++; //下一个字符
            }
            return $ret;
        }
    }
    
    $trie = new Trie($words);
    $s = '123456787654321';
    $found = $trie->match($s, $trie);
    print_r($found);
    
    
    结果:
    Array
    (
        [0] => 123
        [11] => 43
    )
    

    不知道有没有 bug 。

     

    Tags: PHP Trie

日历

关于神仙

神仙

世人都晓神仙好啊~~