什么是所谓的模板引擎

<?php
// 程序入口文件 index.php
// 重点
// 什么是“模板引擎” 模板引擎如何工作

// 设置PHP显示所有错误,除notice错误
error_reporting(E_ALL & ~E_NOTICE);

header("Content-Type: text/html; charset=utf-8");


class test
{
    protected function view($name, array $data = array())
    {
        // 模板文件路径
        $sourceFilepath = __DIR__."/{$name}.source.php";

        // 即将编译后的模板路径(实际使用的模板文件路径)
        $compliedPath = __DIR__."/{$name}.complied.php";


        // 模板文件路径文件是否存在
        if (!file_exists($sourceFilepath))
            exit("ERROR: {$sourceFilepath} not exists.");

        // 读取原始文件
        $sourceContent = file_get_contents($sourceFilepath);


        // 预设的 模板规则替换 正则规则
        $replaces = [
            '/{{([a-zA-Z0-9_$\(\)]+)}}/i' => '<?php echo $1; ?>',// 替换 {{xx}}  为 <?php echo xx; ? >
            '/@foreach\((.*)\)/i' => '<?php foreach($1): ?>',// 替换@foreach(xx) 为 <?php foreach(xx): ? >
            '/@endforeach/i' => '<?php endforeach; ?>',// 替换 @endforeach 为 <?php endforeach; ? >
        ];

        // 循环规则,开始替换模板内容
        foreach ($replaces as $regex=>$content)
        {
            $sourceContent = preg_replace($regex, $content, $sourceContent);
        }

        // 写入模板缓存
        file_put_contents($compliedPath, $sourceContent);

        extract($data);
        // 直接include 编译后的模板文件
                ob_start();
        include $compliedPath;
                return ob_get_clean();

    }

    public function index()
    {
        return $this->view('index',[
            'var1' => time(),

            'data' => [
                'k1' => 'v1',
                'k2' => 'v2',
                'k3' => 'v3'
            ]
        ]);
    }
}




$test = new test();
echo $test->index();
<!-- 模板文件 index.source.php -->
这是var1的值:{{$var1}}

<p>
    要循环的数据为
    <pre>
        {{print_r($data)}}
    </pre>
</p>

<p>
    @foreach($data as $index=>$value)
    {{$index}} => {{$value}}<br/>
    @endforeach
</p>

ElasticSearch LBS检索

$data = Http\Request::get('poi/users/_search?', array(
	'query' => array(
		'match_all' => array(),
	),
	'filter' => array(
		'geo_distance' => array(
			'distance' => '10km',#10km以内
			"location" => array('lat' => $lat, 'lon' => $lon),
		),
	),
	'sort' => array(
		array(
			'_geo_distance' => array(
				"location" => array('lat' => $lat, 'lon' => $lon),
				"order" => "asc",#由近到远
				"unit" => 'm',#输出距离单位
				//"distance_type" => "plane",
			),
		),
	),
	'from' => 1,
	'size' => 100,
));

PHP计算两个经纬度点之间距离

// 单位为米
function st_distance($lng1, $lat1, $lng2, $lat2) {
	$radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度
	$radLat2 = deg2rad($lat2);
	$radLng1 = deg2rad($lng1);
	$radLng2 = deg2rad($lng2);
	$a = $radLat1 - $radLat2;
	$b = $radLng1 - $radLng2;
	$s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
	return $s;
}

已升级至php7.0.0-dev

探针地址:https://www.cevin.me/phpinfo.php

编译参数(记住buildconf):

./configure –prefix=/usr/local/php7 –with-config-file-path=/usr/local/php/etc –with-jpeg-dir –with-gd –with-png-dir –with-freetype-dir –with-mhash –with-mcrypt –with-openssl –with-curl –without-pear –with-libxml-dir –with-zlib –enable-bcmath –enable-exif –enable-ftp –with-gettext –enable-mbstring –with-mysql=mysqlnd –with-pdo-mysql=mysqlnd –with-mysqli=mysqlnd –enable-soap –enable-zip –with-iconv-dir –enable-fpm –with-pdo-pgsql=/usr/local/pgsql –with-pgsql=/usr/local/pgsql –enable-sockets –enable-mysqlnd

php7-dev最新版本源码:https://github.com/php/php-src/archive/master.zip

弱弱的说一下:性能提升明显 🙂

也说网页扫描二维码登录跳转

场景:
1.支付宝APP扫码登录、支付
2.微信WEB扫码登录

web前端 jquery:

<img src="qrcode.php?id=xxx" />
<script>
var qrcode_id = xxx;

var e = function() {
    $.get('s.php?qid='+qid, function(data){
        var j = JSON.parse(data) || false;
        if (!j) {
            setTimeout(e,3000);
            return false;
        } else if ('bind' == j.state) {
            alert('手机已扫码');
            setTimeout(e,3000);
            return false;
        } else if ('redirect' == j.state) {
            windnow.location.href = j.redirect_uri;
        }
    });
}
e();
</script>

PHP s.php

<?php

// 开始检查时间
$startTime = time();

$db = new db();

$qid = $_GET['qid'];
$action = $_GET['action'];

// 如果当前二维码已经被别人使用过
if ($qr['bind'] && $qr['bind'] != $current_uid)
    exit( json_encode(['state'=>'fail']) );

// 绑定当前用户(手机扫描时会带上用户设备信息或设备已登陆用户信息)
if (!$qr['bind']) {
    $db->update($qid, ['bind'=>$current_uid]);
    exit( json_encode(['state' => 'bind']) );
}

// 如果当前qr已经被绑定并且是当前登录用户
if ($qr['bind'] == $current_uid && 'login' == $action) {
    // 更新数据库删除code
    // 生成session绑定用户
    exit( json_encode(['state' => 'redirect' , 'redirect_uri' => 'xxxxxxxxxxxxxx']) );
}

exit(json_encode(['state' => 'fail']));

PHP Bt种子转磁力链

include 'BEncode.php';
include 'BDecode.php';

$torrent_content = file_get_contents('filename.torrent');

$desc = BDecode($torrent_content);
$info = $desc['info'];
$hash = strtoupper(sha1( BEncode($info) ));

sprintf('magnet:?xt=urn:btih:%s&dn=%s', $hash, $info['name']);


BEncode.php

class BEncode {
    // Dictionary keys must be sorted. foreach tends to iterate over the order
    // the array was made, so we make a new one in sorted order. 🙂
    function makeSorted($array) {
        // Shouldn't happen!
        if (empty($array))
            return $array;
        $i = 0;
        foreach($array as $key => $dummy)
            $keys[$i++] = stripslashes($key);
        sort($keys);
        for ($i=0; isset($keys[$i]); $i++)
            $return[addslashes($keys[$i])] = $array[addslashes($keys[$i])];
        return $return;
    }

    // Encodes strings, integers and empty dictionaries.
    // $unstrip is set to true when decoding dictionary keys
    function encodeEntry($entry, &$fd, $unstrip = false) {
        if (is_bool($entry)) {
            $fd .= 'de';
            return;
        }
        if (is_int($entry) || is_float($entry)) {
            $fd .= 'i'.$entry.'e';
            return;
        }
        if ($unstrip)
            $myentry = stripslashes($entry);
        else
            $myentry = $entry;
        $length = strlen($myentry);
        $fd .= $length.':'.$myentry;
    }

    // Encodes lists
    function encodeList($array, &$fd) {
        $fd .= 'l';
        // The empty list is defined as array();
        if (empty($array)) {
            $fd .= 'e';
            return;
        }
        for ($i = 0; isset($array[$i]); $i++)
            $this->decideEncode($array[$i], $fd);
        $fd .= 'e';
    }

    // Passes lists and dictionaries accordingly, and has encodeEntry handle
    // the strings and integers.
    function decideEncode($unknown, &$fd) {
        if (is_array($unknown)) {
            if (isset($unknown[0]) || empty($unknown))
                return $this->encodeList($unknown, $fd);
            else
                return $this->encodeDict($unknown, $fd);
        }
        $this->encodeEntry($unknown, $fd);
    }

    // Encodes dictionaries
    function encodeDict($array, &$fd) {
        $fd .= 'd';
        if (is_bool($array)) {
            $fd .= 'e';
            return;
        }
        // NEED TO SORT!
        $newarray = $this->makeSorted($array);
        foreach($newarray as $left => $right) {
            $this->encodeEntry($left, $fd, true);
            $this->decideEncode($right, $fd);
        }
        $fd .= 'e';
    }
}

function BEncode($array) {
    $string = '';
    $encoder = new BEncode;
    $encoder->decideEncode($array, $string);
    return $string;
}

BDecode.php

class BDecode {
    function numberdecode($wholefile, $offset) {
        // Funky handling of negative numbers and zero
        $negative = false;
        if ($wholefile[$offset] == '-') {
            $negative = true;
            $offset++;
        }
        if ($wholefile[$offset] == '0') {
            $offset++;
            if ($negative)
                return array(false);
            if ($wholefile[$offset] == ':' || $wholefile[$offset] == 'e')
                return array(0, ++$offset);
            return array(false);
        }
        $ret[0] = 0;
        for(;;) {
            if ($wholefile[$offset] >= '0' && $wholefile[$offset] <= '9') {
                $ret[0] *= 10;
                //Added 2005.02.21 - VisiGod
           //Changing the type of variable from integer to double to prevent a numeric overflow   
                settype($ret[0],'double');
                //Added 2005.02.21 - VisiGod
                $ret[0] += ord($wholefile[$offset]) - ord('0');
                $offset++;
            }   else if ($wholefile[$offset] == 'e' || $wholefile[$offset] == ':') {
                // Tolerate : or e because this is a multiuse function
                $ret[1] = $offset+1;
                if ($negative) {
                    if ($ret[0] == 0)
                        return array(false);
                    $ret[0] = - $ret[0];
                }
                return $ret;
            } else return array(false);
        }
    }

    function decodeEntry($wholefile, $offset=0) {
        if ($wholefile[$offset] == 'd')
            return $this->decodeDict($wholefile, $offset);
        if ($wholefile[$offset] == 'l')
            return $this->decodelist($wholefile, $offset);
        if ($wholefile[$offset] == 'i')
            return $this->numberdecode($wholefile, ++$offset);
        // String value: decode number, then grab substring

        $info = $this->numberdecode($wholefile, $offset);
        if ($info[0] === false)
            return array(false);
        $ret[0] = substr($wholefile, $info[1], $info[0]);
        $ret[1] = $info[1]+strlen($ret[0]);
        return $ret;
    }

    function decodeList($wholefile, $offset) {
        if ($wholefile[$offset] != 'l')
            return array(false);
        $offset++;
        $ret = array();
        for ($i=0;;$i++) {
            if ($wholefile[$offset] == 'e')
                break;
            $value = $this->decodeEntry($wholefile, $offset);
            if ($value[0] === false)
                return array(false);
            $ret[$i] = $value[0];
            $offset = $value[1];
        }
        // The empty list is an empty array. Seems fine.
        return array(0=>$ret, 1=>++$offset);
    }

    // Tries to construct an array
    function decodeDict($wholefile, $offset=0) {
        if ($wholefile[$offset] == 'l')
            return $this->decodeList($wholefile, $offset);
        if ($wholefile[$offset] != 'd')
            return false;
        $ret=array();
        $offset++;
        for (;;) {  
            if ($wholefile[$offset] == 'e')   {
                $offset++;
                break;
            }
            $left = $this->decodeEntry($wholefile, $offset);
            if (!$left[0])
                return false;
            $offset = $left[1];
            if ($wholefile[$offset] == 'd') {
                // Recurse
                $value = $this->decodedict($wholefile, $offset);
                if (!$value[0])
                    return false;
                $ret[addslashes($left[0])] = $value[0];
                $offset= $value[1];
                continue;
            }
            if ($wholefile[$offset] == 'l') {
                $value = $this->decodeList($wholefile, $offset);
                if (!$value[0] && is_bool($value[0]))
                    return false;
                $ret[addslashes($left[0])] = $value[0];
                $offset = $value[1];
                continue;
            }
            $value = $this->decodeEntry($wholefile, $offset);
            if ($value[0] === false)
                return false;
            $ret[addslashes($left[0])] = $value[0];
            $offset = $value[1];
        }
        return array(0=>(empty($ret)?true:$ret), 1=>$offset);
    }
}

function BDecode($wholefile) {
    $decoder = new BDecode;
    $return = $decoder->decodeEntry($wholefile);
    return $return[0];
}