日期:2014-05-17  浏览次数:20760 次

ThinkPHP的一些类与方法

Thinkphp 代码

获取客户端IP地址

?

获取客户端IP地址

$type表示返回类型 0 返回IP地址 1 返回IPV4地址数字

function get_client_ip($type = 0) {

? ? $type ? ? ? = ?$type ? 1 : 0;

? ? static $ip ?= ? NULL;

? ? if ($ip !== NULL) return $ip[$type];

? ? if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {

? ? ? ? $arr ? ?= ? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

? ? ? ? $pos ? ?= ? array_search('unknown',$arr);

? ? ? ? if(false !== $pos) unset($arr[$pos]);

? ? ? ? $ip ? ? = ? trim($arr[0]);

? ? }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {

? ? ? ? $ip ? ? = ? $_SERVER['HTTP_CLIENT_IP'];

? ? }elseif (isset($_SERVER['REMOTE_ADDR'])) {

? ? ? ? $ip ? ? = ? $_SERVER['REMOTE_ADDR'];

? ? }

? ? // IP地址合法验证

? ? $long = ip2long($ip);

? ? $ip ? = $long ? array($ip, $long) : array('0.0.0.0', 0);

? ? return $ip[$type];

}

?

?

文件字节大小格式化

?

字节格式化 把字节数格式为 B K M G T 描述的大小

function byte_format($size, $dec=2){

? ? $a = array("B", "KB", "MB", "GB", "TB", "PB");

? ? $pos = 0;

? ? while ($size >= 1024) {

? ? ? ? ?$size /= 1024;

? ? ? ? ? ?$pos++;

? ? }

? ? return round($size,$dec)." ".$a[$pos];

}

或者

function get_size($s,$u='B',$p=1){ ?

? ? $us = array('B'=>'K','K'=>'M','M'=>'G','G'=>'T'); ?

? ? return (($u!=='B')&&(!isset($us[$u]))||($s<1024))?(number_format($s,$p)." $u"):(get_size($s/1024,$us[$u],$p)); ?

} ?

?

?

显示彩虹字符串

用于显示彩虹字符串,支持UTF8和中文,效果如下:

function color_txt($str){

? ? $len ? ? ? ?= mb_strlen($str);

? ? $colorTxt ? = '';

? ? for($i=0; $i<$len; $i++) {

? ? ? ? $colorTxt .= ?'<span style="color:'.rand_color().'">'.mb_substr($str,$i,1,'utf-8').'</span>';

? ? }

? ? return $colorTxt;

}

function rand_color(){

? ? return '#'.sprintf("%02X",mt_rand(0,255)).sprintf("%02X",mt_rand(0,255)).sprintf("%02X",mt_rand(0,255));

}

?

?

让PHP更快的提供文件下载

一般来说, 我们可以通过直接让URL指向一个位于Document Root下面的文件, 来引导用户下载文件.

?

  但是, 这样做, 就没办法做一些统计, 权限检查, 等等的工作. 于是, 很多时候, 我们采用让PHP来做转发, 为用户提供文件下载.

<?php

  $file = "/tmp/dummy.tar.gz";

  header("Content-type: application/octet-stream");

  header('Content-Disposition: attachment; filename="' . basename($file) . '"');

  header("Content-Length: ". filesize($file));

  readfile($file);

?

但是这个有一个问题, 就是如果文件是中文名的话, 有的用户可能下载后的文件名是乱码.

?

  于是, 我们做一下修改(参考: :

<?php

  $file = "/tmp/中文名.tar.gz";

  $filename = basename($file);

  header("Content-type: application/octet-stream");

  //处理中文文件名

  $ua = $_SERVER["HTTP_USER_AGENT"];

  $encoded_filename = urlencode($filename);

  $encoded_filename = str_replace("+", "%20", $encoded_filename);

  if (preg_match("/MSIE/", $ua)) {

  header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');

  } else if (preg_match("/Firefox/", $ua)) {

  header("Content-Disposition: attachment; filename*=\"utf8''" . $filename . '"');

  } else {

  header('Content-Disposition: attachment; filename="' . $filename . '"');

  }

  header('Content-Disposition: attachment; filename="' . $filename . '"');

  header("Content-Length: ". filesize($file));

  readfile($file);

?

恩, 现在看起来好多了, 不过还有一个问题, 那就是readfile, 虽然PHP的readfile尝试实现的尽量高效, 不占用PHP本身的内存, 但是实际上它还是需要采用MMAP(如果支持), 或者是一个固定的buffer去循环读取文件, 直接输出.

?

  输出的时候, 如果是Apache + PHP mod, 那么还需要发送到Apache的输出缓冲区. 最后才发送给用户. 而对于Nginx + fpm如果他们分开部署的话, 那还会带来额外的网络IO.

?

  那么, 能不能不经过PHP这层, 直接让Webserver直接把文件发送给用户呢?

?