### 根据字符串生成对应数组方法
$config = array(
'project|page|index' => 'content',
'project|page|nav' => array(
array(
'image' => '1.jpg',
'name' => 'home'
),
array(
'image' => '2.jpg',
'name' => 'about'
)
),
'project|page|open' => true
);
$result = array();
foreach($config as $key=>$val){
$tmp = '';
$keys = explode('|', $key);
for($i=0,$len=count($keys); $i<$len; $i++){
$tmp .= "['".$keys[$i]."']";
}
if(is_array($val)){
eval('$result'.$tmp.'='.var_export($val,true).';');
}elseif(is_string($val)){
eval('$result'.$tmp.'='.$val.';');
}else{
eval('$result'.$tmp.'=$val;');
}
}
print_r($result);
$result = array(
'project' => array(
'page' => array(
'index' => 'content',
'nav' => array(
array(
'image' => '1.jpg',
'name' => 'home'
),
array(
'image' => '2.jpg',
'name' => 'about'
)
),
'open' => true
)
)
);
###求余出现负数处理方法
php int 的范围是 -2147483648 ~ 2147483647,可用常量 PHP_INT_MAX 查看
echo 3701256461%62; // -13
$res = floatval(3701256461);
echo fmod($res,62); // 53
###文件转base64
/** 文件转base64输出
* @param String $file 文件路径
* @return String base64 string
*/
function fileToBase64($file){
$base64_file = '';
if(file_exists($file)){
$mime_type= mime_content_type($file);
$base64_data = base64_encode(file_get_contents($file));
$base64_file = 'data:'.$mime_type.';base64,'.$base64_data;
}
return $base64_file;
}
/** base64转文件输出
* @param String $base64_data base64数据
* @param String $file 要保存的文件路径
* @return boolean
*/
function base64ToFile($base64_data, $file){
if(!$base64_data || !$file){
return false;
}
return file_put_contents($file, base64_decode($base64_data), true);
}
//file to base64
<img src="<?=fileToBase64('1.jpg') ?>" />
//base64 to file
$file = "test.jpg";
$data = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGrWFKrNK9z//2Q==';
if(base64ToFile($data, $file)){
echo '<img src="'.$file.'" />';
}
###获取一个变量的名字
$a = '100';
echo '$a name is:'.get_variable_name($a).' value:'.$a; // $a name is: a value: 100
/**
* @param String $var 要查找的变量
* @param Array $scope 要搜寻的范围
* @param String 变量名称
*/
function get_variable_name(&$var, $scope=null){
$scope = $scope==null? $GLOBALS : $scope; // 如果没有范围则在globals中找寻
// 因有可能有相同值的变量,因此先将当前变量的值保存到一个临时变量中,然后再对原变量赋唯一值,以便查找出变量的名称,找到名字后,将临时变量的值重新赋值到原变量
$tmp = $var;
$var = 'tmp_value_'.mt_rand();
$name = array_search($var, $scope, true); // 根据值查找变量名称
$var = $tmp;
return $name;
}
function test(){
$a = '100';
echo '$a name is:'.get_variable_name($a);
}
test(); // $a name is: undefined
//因为在function中定义的变量globals会找不到
function test2(){
$a = '100';
echo '$a name is:'.get_variable_name($a, get_defined_vars());
}
test2(); // $a name is: a
// 将scope设定为 get_defined_vars() 可以找到
/** 延时输出内容
* @param int $sec 秒数,可以是小数例如 0.3
*/
function cache_flush($sec=2){
ob_flush();
flush();
usleep($sec*1000000);
}
/** 文件加密,使用key与原文异或(XOR)生成密文,解密则再执行一次异或即可
* @param String $source 要加密或解密的文件
* @param String $dest 加密或解密后的文件
* @param String $key 密钥
*/
function file_encrypt($source, $dest, $key){
if(file_exists($source)){
$content = ''; // 处理后的字符串
$keylen = strlen($key); // 密钥长度
$index = 0;
$fp = fopen($source, 'rb');
while(!feof($fp)){
$tmp = fread($fp, 1);
$content .= $tmp ^ substr($key,$index%$keylen,1);
$index++;
}
fclose($fp);
return file_put_contents($dest, $content, true);
}else{
return false;
}
}
/** 删除所有空目录
* @param String $path 目录路径
*/
function rm_empty_dir($path){
if($handle = opendir($path)){
while(($file=readdir($handle))!==false){ // 遍历文件夹
if($file!='.' && $file!='..'){
$curfile = $path.'/'.$file; // 当前目录
if(is_dir($curfile)){ // 目录
rm_empty_dir($curfile); // 如果是目录则继续遍历
if(count(scandir($curfile))==2){ // 目录为空,=2是因为. 和 ..存在
rmdir($curfile); // 删除空目录
}
}
}
}
closedir($handle);
}
}
/* unicode 转 中文
* @param String $str unicode 字符串
* @return String
*/
function unescape($str) {
$str = rawurldecode($str);
preg_match_all("/(?:%u.{4})|&#x.{4};|&#\d+;|.+/U",$str,$r);
$ar = $r[0];
foreach($ar as $k=>$v) {
if(substr($v,0,2) == "%u"){
$ar[$k] = iconv("UCS-2BE","UTF-8",pack("H4",substr($v,-4)));
}elseif(substr($v,0,3) == "&#x"){
$ar[$k] = iconv("UCS-2BE","UTF-8",pack("H4",substr($v,3,-1)));
}elseif(substr($v,0,2) == "&#") {
$ar[$k] = iconv("UCS-2BE","UTF-8",pack("n",substr($v,2,-1)));
}
}
return join("",$ar);
}
<img src="sitestat.php?url=www.domain.com&userid=1" />
// 获取参数
$param = array();
$param['url'] = isset($_GET['url'])? $_GET['url'] : '';
$param['userid'] = isset($_GET['userid'])? $_GET['userid'] : 0;
// 写入log文件
file_put_contents('sitestat.log', json_encode($param)."\r\n", FILE_APPEND);
header('content-type:image/png');
$im = imagecreate(1, 1); // 创建1x1px的空白图像
imagecolorallocatealpha($im, 0, 0, 0, 127); // 透明图像
imagepng($im); // 输出图片
imagedestroy($im);
###mysql的最佳索引攻略
mysql> EXPLAIN SELECT `birday` FROM `user` WHERE `birthday` < "1990/2/2";
-- 结果:
id: 1
select_type: SIMPLE -- 查询类型(简单查询,联合查询,子查询)
table: user -- 显示这一行的数据是关于哪张表的
type: range -- 区间索引(在小于1990/2/2区间的数据),这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL,const代表一次就命中,ALL代表扫描了全表才确定结果。一般来说,得保证查询至少达到range级别,最好能达到ref。
possible_keys: birthday -- 指出MySQL能使用哪个索引在该表中找到行。如果是空的,没有相关的索引。这时要提高性能,可通过检验WHERE子句,看是否引用某些字段,或者检查字段不是适合索引。
key: birthday -- 实际使用到的索引。如果为NULL,则没有使用索引。如果为primary的话,表示使用了主键。
key_len: 4 -- 最长的索引宽度。如果键是NULL,长度就是NULL。在不损失精确性的情况下,长度越短越好
ref: const -- 显示哪个字段或常数与key一起被使用。
rows: 1 -- 这个数表示mysql要遍历多少数据才能找到,在innodb上是不准确的。
Extra: Using where; Using index -- 执行状态说明,这里可以看到的坏的例子是Using temporary和Using
CREATE TABLE `device` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`toid` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'toid',
`createtime` TIMESTAMP NOT NULL DEFAULT 0 COMMENT '创建时间',
`updatetime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `toid` (`toid`)
)
COMMENT='设备表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
CREATE TABLE `device` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`toid` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'toid',
`createtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updatetime` TIMESTAMP NOT NULL COMMENT '最后更新时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `toid` (`toid`)
)
COMMENT='设备表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
###MySQL大表优化方案
字段
尽量使用TINYINT、SMALLINT、MEDIUM_INT作为整数类型而非INT,如果非负则加上UNSIGNED
VARCHAR的长度只分配真正需要的空间
使用枚举或整数代替字符串类型
尽量使用TIMESTAMP而非DATETIME,
单表不要有太多字段,建议在20以内
避免使用NULL字段,很难查询优化且占用额外索引空间
用整型来存IP
索引
索引并不是越多越好,要根据查询有针对性的创建,考虑在WHERE和ORDER BY命令上涉及的列建立索引,可根据EXPLAIN来查看是否用了索引还是全表扫描
应尽量避免在WHERE子句中对字段进行NULL值判断,否则将导致引擎放弃使用索引而进行全表扫描
值分布很稀少的字段不适合建索引,例如"性别"这种只有两三个值的字段
字符字段只建前缀索引
字符字段最好不要做主键
不用外键,由程序保证约束
尽量不用UNIQUE,由程序保证约束
使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引
查询SQL
可通过开启慢查询日志来找出较慢的SQL
不做列运算:SELECT id WHERE age + 1 = 10,任何对列的操作都将导致表扫描,它包括数据库教程函数、计算表达式等等,查询时要尽可能将操作移至等号右边
sql语句尽可能简单:一条sql只能在一个cpu运算;大语句拆小语句,减少锁时间;一条大sql可以堵死整个库
不用SELECT *
OR改写成IN:OR的效率是n级别,IN的效率是log(n)级别,in的个数建议控制在200以内
不用函数和触发器,在应用程序实现
避免%xxx式查询
少用JOIN
使用同类型进行比较,比如用'123'和'123'比,123和123比
尽量避免在WHERE子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描
对于连续数值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
列表数据不要拿全表,要使用LIMIT来分页,每页数量也不要太大
###获取最后一次出错信息
/**
* 获取最后一次出错信息,无论如何也能获取到
* http://www.cnblogs.com/siqi/archive/2012/12/02/2798178.html
* error_get_last set_error_handler 都不会受环境配置的影响
*
*/
error_reporting(0);
ini_set("display_errors", "off");
#php通过mysql取出的数据库的数据都是字符串类型
set_error_handler(function(){
print_r(func_get_args());
});
echo $a ;
print_r(error_get_last());
###一次替换一个问号
$sql = "?,?,?,?";
$data = array('a', 'b', 'c', 'd');
for($i=0;$i<3;$i++){
$sql=preg_replace('/\?/',"'".$data[$i]."'",$sql,1);// 一次只替换一个
}
echo $sql;//'a','b','c'
###字符串转数组
>>> eval('$a='.var_export([1,2,3],true).';')
=> null
>>> $a
=> [
1,
2,
3
]
###执行github上文件
curl -L github.com/oh-my-fish/oh-my-fish/raw/master/bin/install | fish
###判断页面或图片是否经过gzip压缩
function check_gzip($url){
$header = get_headers($url, 1);
if(isset($header['Vary']) && $header['Vary']=='Accept-Encoding'){
return true;
}
return false;
}
header('content-type:image/jpeg');
ob_start('ob_gzhandler'); // 开启gzip,屏蔽则关闭 利用apache mod_deflate module 开启gzip sudo a2enmod deflate
echo file_get_contents('test.jpg');
$url = 'http://www.example.com/';
var_dump(check_gzip($url));
/**
* 判断url是否经过gzip压缩
* @param String $url 来源
* @param Boolean
*/
function check_gzip($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1); // 输出header信息
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 返回的信息不直接输出
curl_setopt($ch, CURLOPT_ENCODING, ''); // 不限制编码类型
$response = curl_exec($ch);
if(!curl_errno($ch)){
$info = curl_getinfo($ch);
// 获取header
$header_size = $info['header_size'];
$header_str = substr($response, 0, $header_size);
$filter = array("\r\n", "\r");
$header_str = str_replace($filter, PHP_EOL, $header_str);
// 检查content-encoding
preg_match('/Content-Encoding: (.*)\s/i', $header_str, $matches);
if(isset($matches[1]) && $matches[1]=='gzip'){
return true;
}
}
return false;
}
###实现0~1随机小数生成
for($i=0; $i<5; $i++){
echo lcg_value().PHP_EOL;
}
function randFloat($min=0, $max=1){
return $min + mt_rand()/mt_getrandmax() * ($max-$min);
}
/**
* 获取指定数字的随机数字组合
* @param Int $var 数字
* @param Int $num 组合这个数字的数量
* @return Array
*/
function getNumGroups($var, $num){
// 数量不正确
if($var<$num){
return array();
}
$total = 0;
$result = array();
for($i=1; $i<$num; $i++){
$tmp = mt_rand(1, $var-($num-$i)-$total);
$total += $tmp;
$result[] = $tmp;
}
$result[] = $var-$total;
return $result;
}
// demo
$result = getNumGroups(100, 3);
print_r($result);
Array
(
[0] => 42
[1] => 25
[2] => 33
)
function getDateFromRange($startdate, $enddate){
$stimestamp = strtotime($startdate);
$etimestamp = strtotime($enddate);
// 计算日期段内有多少天
$days = ($etimestamp-$stimestamp)/86400+1;
// 保存每天日期
$date = array();
for($i=0; $i<$days; $i++){
$date[] = date('Y-m-d', $stimestamp+(86400*$i));
}
return $date;
}
// demo
$date = getDateFromRange('2016-02-25','2016-03-05');
print_r($date);
###字符串解析为数组
$str = "中国,广东省,广州市,天河区,'113.329884,23.154799',1,'2016-01-01 12:00:00','1,2,3,4,5,6'";
$arr = str_getcsv($str, ',', "'");
print_r($arr);
Array
(
[0] => 中国
[1] => 广东省
[2] => 广州市
[3] => 天河区
[4] => 113.329884,23.154799
[5] => 1
[6] => 2016-01-01 12:00:00
[7] => 1,2,3,4,5,6
)
###Access-Control-Allow-Origin实现跨域访问
$ret = array(
'name' => isset($_POST['name'])? $_POST['name'] : '',
'gender' => isset($_POST['gender'])? $_POST['gender'] : ''
);
header('content-type:application:json;charset=utf8');
$origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';
$allow_origin = array(
'http://www.client.com',
'http://www.client2.com'
);
if(in_array($origin, $allow_origin)){
header('Access-Control-Allow-Origin:'.$origin);
header('Access-Control-Allow-Methods:POST');
header('Access-Control-Allow-Headers:x-requested-with,content-type');
}
echo json_encode($ret);
###PDO 查询mysql返回字段整型变为String型解决方法
$pdo = new PDO($dsn, $user, $pass, $param);
使用PDO查询mysql数据库时,执行prepare,execute后,返回的字段数据全都变为字符型
// 在创建连接后,加入
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);提取的时候将数值转换为字符串。
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);启用或禁用预处理语句的模拟。
###数组元素快速去重
// 使用键值互换去重
$arr = array_flip($arr);
$arr = array_flip($arr);
$arr = array_values($arr);
###ip2long 出现负数原因及解决方法
$ip = '192.168.101.100';
$ip_long = sprintf('%u',ip2long($ip));
echo $ip_long.PHP_EOL; // 3232261476
echo long2ip($ip_long); // 192.168.101.100
###查找数组元素提高效率方法
in_array($str, $arr);
// 键值互换
$arr = array_flip($arr);
isset($arr[$str]);
###创建与解析url
如果 enc_type 是 PHP_QUERY_RFC1738,则编码将会以 » RFC 1738 标准和 application/x-www-form-urlencoded 媒体类型进行编码,空格会被编码成加号(+)。
如果 enc_type 是 PHP_QUERY_RFC3986,将根据 » RFC 3986 编码,空格会被百分号编码(%20)。
$data = array('fdipzone','male','programmer','a new programmer');
echo http_build_query($data, 'info_', '#', PHP_QUERY_RFC3986);//info_0=fdipzone#info_1=male#info_2=programmer#info_3=a%20new%20programmer
echo http_build_query($data);//name=fdipzone&gender=male&profession=programmer&explain=a+new+programmer
$url = 'http://fdipzone:123456@www.fdipzone.com:80/test/index.php?id=1#tag';
print_r(parse_url($url))
$str = 'name=fdipzone&gender=male&profession=programer&explain=a new programmer';
parse_str($str);
echo $name.PHP_EOL;
parse_str($str, $arr);
$url = 'http://www.fdipzone.com/test/index.php?name=fdipzone&gender=male&profession=programmer&explain=a new programmer';
$query = parse_url($url, PHP_URL_QUERY);
parse_str($query, $data);
print_r($data);
Array
(
[name] => fdipzone
[gender] => male
[profession] => programmer
[explain] => a new programmer
)
$path = dirname(__FILE__);
$result = array();
traversing($path, $result);
print_r($result);
function traversing($path, &$result){
$curr = glob($path.'/*');
if($curr){
foreach($curr as $f){
if(is_dir($f)){
array_push($result, $f);
traversing($f, $result);
}elseif(strtolower(substr($f, -4))=='.php'){
array_push($result, $f);
}
}
}
}
###explode
$str = '1,2,3,4,5,6,7,8,9';
$arr = explode(',', $str,0);//[1,2,3,4,5,6,7,8,9]
$arr = explode(',', $str, -3);
$ids = null;
$data = explode(',', $ids);//ids=null,使用explode分割,得出的数组是Array ( [0] => )而不是Array()。
if($data){
print_r($data);
}else{
echo 'null';
}
$ids = null;
$data = explode(',', $ids);
if(isset($data[0]) && $data[0]){
foreach($data as $k=>$v){
// do sth
}
}
###浮点数比较方法
$a = 0.1;
$b = 0.9;
$c = 1;
var_dump(($a+$b)==$c);//true
var_dump(($c-$b)==$a);//false
printf("%.20f", $a+$b); // 1.00000000000000000000
printf("%.20f", $c-$b); // 0.09999999999999997780
永远不要相信浮点数已精确到最后一位,也永远不要比较两个浮点数是否相等
var_dump(($c-$b)==$a); // false
var_dump(round(($c-$b),1)==round($a,1)); // true
var_dump(bcsub($c, $b, 1)==$a); // true
/**
* 计算指定日期的一周开始及结束日期
* @param DateTime $date 日期
* @param Int $start 周几作为一周的开始 1-6为周一~周六,0为周日,默认0
* @retrun Array
*/
function getWeekRange($date, $start=0){
// 将日期转时间戳
$dt = new DateTime($date);
$timestamp = $dt->format('U');
// 获取日期是周几
$day = (new DateTime('@'.$timestamp))->format('w');
// 计算开始日期
if($day>=$start){
$startdate_timestamp = mktime(0,0,0,date('m',$timestamp),date('d',$timestamp)-($day-$start),date('Y',$timestamp));
}elseif($day<$start){
$startdate_timestamp = mktime(0,0,0,date('m',$timestamp),date('d',$timestamp)-7+$start-$day,date('Y',$timestamp));
}
// 结束日期=开始日期+6
$enddate_timestamp = mktime(0,0,0,date('m',$startdate_timestamp),date('d',$startdate_timestamp)+6,date('Y',$startdate_timestamp));
$startdate = (new DateTime('@'.$startdate_timestamp))->format('Y-m-d');
$enddate = (new DateTime('@'.$enddate_timestamp))->format('Y-m-d');
return array($startdate, $enddate);
}
$date = '2016-04-27';
for($start=0; $start<=6; $start++){
list($startdate, $enddate) = getWeekRange($date, $start);
echo 'date:'.$date.' week start:'.$start.' range:'.$startdate.', '.$enddate.'<br>';
}
date:2016-04-27 week start:0 range:2016-04-24, 2016-04-30
date:2016-04-27 week start:1 range:2016-04-25, 2016-05-01
date:2016-04-27 week start:2 range:2016-04-26, 2016-05-02
date:2016-04-27 week start:3 range:2016-04-27, 2016-05-03
date:2016-04-27 week start:4 range:2016-04-21, 2016-04-27
date:2016-04-27 week start:5 range:2016-04-22, 2016-04-28
date:2016-04-27 week start:6 range:2016-04-23, 2016-04-29
$str = 'user_order_list';
echo str_replace('_', '/', $str); // user/order/list
/**
* 对字符串执行指定次数替换
* @param Mixed $search 查找目标值
* @param Mixed $replace 替换值
* @param Mixed $subject 执行替换的字符串/数组
* @param Int $limit 允许替换的次数,默认为-1,不限次数
* @return Mixed
*/
function str_replace_limit($search, $replace, $subject, $limit=-1){
if(is_array($search)){
foreach($search as $k=>$v){
$search[$k] = '`'. preg_quote($search[$k], '`'). '`';
}
}else{
$search = '`'. preg_quote($search, '`'). '`';
}
return preg_replace($search, $replace, $subject, $limit);
}
$str = 'user_order_list';
echo str_replace_limit('_', '/', $str, 1); // user/order_list
$arr = array('abbc','bbac','cbba');
$result = str_replace_limit('b', 'B', $arr, 1);
print_r($result); // Array ( [0] => aBbc [1] => Bbac [2] => cBba )
###兼容key没有双引括起来的JSON字符串解析
/** 兼容key没有双引括起来的JSON字符串解析
* @param String $str JSON字符串
* @param boolean $mod true:Array,false:Object
* @return Array/Object
*/
function ext_json_decode($str, $mode=false){
if(preg_match('/\w:/', $str)){
$str = preg_replace('/(\w+):/is', '"$1":', $str);
}
return json_decode($str, $mode);
}
$str = '{"name":"fdipzone"}';
var_dump(ext_json_decode($str, true)); // array(1) { ["name"]=> string(8) "fdipzone" }
$str1 = '{name:"fdipzone"}';
var_dump(ext_json_decode($str1, true)); // array(1) { ["name"]=> string(8) "fdipzone" }
function solidDiamond($n=5, $s='*'){
$str = '';
// 计算总行数
$rows = $n*2-1;
// 循环计算每行的*
for($i=0; $i<$rows; $i++){
if($i<$n){ // 上部
$str .= str_pad('', ($n-$i-1), ' '). str_pad('', $i*2+1, $s)."\r\n";
}else{ // 下部
$str .= str_pad('', ($i-$n+1), ' '). str_pad('', ($rows-$i)*2-1, $s). "\r\n";
}
}
return $str;
}
echo solidDiamond(5);
*
***
*****
*******
*********
*******
*****
***
*
###curl Expect:100-continue
使用curl POST数据时,如果POST的数据大于1024字节,curl并不会直接就发起POST请求。而是会分两步。
1.发送一个请求,header中包含一个Expect:100-continue,询问Server是否愿意接受数据。
2.接受到Server返回的100-continue回应后,才把数据POST到Server。
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Expect:"));
###curl 获取 https 请求方法
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true); // 从证书中检查SSL加密算法是否存在
###获取文件mime类型的方法
$mime_type = mime_content_type('1.jpg');
echo $mime_type; // image/jpeg
$fi = new finfo(FILEINFO_MIME_TYPE);
$mime_type = $fi->file('1.jpg');
echo $mime_type; // image/jpeg
###iconv 中文截断问题的解决方法
iconv遇到不能识别的内容,会从第一个不能识别的字符开始截断,并生成一个E_NOTICE。因此后边的内容被丢弃了。
而在输出字符集后加上//IGNORE则只丢弃不能识别的内容,而不会截断和丢弃后面的内容
$content = iconv('GB2312', 'UTF-8//IGNORE', $content); // $content为采集到的内容
###php 异步调用方法
$.get("doRequest.php", { name: "fdipzone"} );
<img src="doRequest.php?name=fdipzone">
pclose(popen('php /home/fdipzone/doRequest.php &', 'r'));
$ch = curl_init();
$curl_opt = array(
CURLOPT_URL, 'http://www.example.com/doRequest.php'
CURLOPT_RETURNTRANSFER,1,
CURLOPT_TIMEOUT,1
);
curl_setopt_array($ch, $curl_opt);
curl_exec($ch);
curl_close($ch);
###php 发送与接收流文件
function sendStreamFile($url, $file){
if(file_exists($file)){
$opts = array(
'http' => array(
'method' => 'POST',
'header' => 'content-type:application/x-www-form-urlencoded',
'content' => file_get_contents($file)
)
);
$context = stream_context_create($opts);
$response = file_get_contents($url, false, $context);
$ret = json_decode($response, true);
return $ret['success'];
}else{
return false;
}
}
$ret = sendStreamFile('http://localhost/fdipzone/receiveStreamFile.php', 'send.txt');
var_dump($ret);
function receiveStreamFile($receiveFile){
$streamData = isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
if(empty($streamData)){
$streamData = file_get_contents('php://input');
}
if($streamData!=''){
$ret = file_put_contents($receiveFile, $streamData, true);
}else{
$ret = false;
}
return $ret;
}
$receiveFile = 'receive.txt';
$ret = receiveStreamFile($receiveFile);
echo json_encode(array('success'=>(bool)$ret));
###nowdoc
$var = '123';
$content = <<<FDIPZONE
$var time();
FDIPZONE;
echo $content; // 123 time();
class test{
public $a = <<<'FDIPZONE'
$var
FDIPZONE;
}
$obj = new test();
echo $obj->a;
###2038
32位系统下显示2038年1月19日03:14:07以后的日期将会溢出。
>>> date('YmdHis',0x7FFFFFFF)
=> "20380119111407"
>>> date('YmdHis',0x7FFFFFFF+100)
=> "19011214044731"
>>> (new DateTime('@'.(0x7FFFFFFF+100)))->format('YmdHis')
=> "20380119031547"
在32位机器上,可以使用DateTime类来解决这个问题
$date = '2040-01-01 12:00:00';
$dt = new DateTime($date);
echo $dt->format('U'); // 2209032000
echo $dt->format('Y-m-d H:i:s'); // 2040-01-01 12:00:00
// datetime 转 unixtime
$dt = new DateTime('2040-01-01 12:00:00');
echo $dt->format('U'); // 2209032000
// unixtime 转 datetime
$dt = new DateTime('@2209032000');
echo $dt->format('Y-m-d H:i:s'); // 2040-01-01 12:00:00
$dt = new DateTime('@1420029030');
$tz = timezone_open('Europe/London');
$dt->setTimezone($tz);
echo $dt->format('Y-m-d H:i:s').'<br>'; // 2014-12-31 12:30:30
$dt = new DateTime('@1420029030');
$tz = timezone_open('Asia/HONG_KONG');
$dt->setTimezone($tz);
echo $dt->format('Y-m-d H:i:s'); // 2014-12-31 20:30:30
var formdata = new FormData();
formdata.append('name','fdipzone');
formdata.append('gender','male');
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
<!--
function fsubmit(){
var data = new FormData($('#form1')[0]);
$.ajax({
url: 'server.php',
type: 'POST',
data: data,
dataType: 'JSON',
cache: false,
processData: false,
contentType: false
}).done(function(ret){
if(ret['isSuccess']){
var result = '';
result += 'name=' + ret['name'] + '<br>';
result += 'gender=' + ret['gender'] + '<br>';
result += '<img src="' + ret['photo'] + '" width="100">';
$('#result').html(result);
}else{
alert('提交失敗');
}
});
return false;
}
-->
</script>
</head>
<body>
<form name="form1" id="form1">
<p>name:<input type="text" name="name" ></p>
<p>gender:<input type="radio" name="gender" value="1">male <input type="radio" name="gender" value="2">female</p>
<p>photo:<input type="file" name="photo" id="photo"></p>
<p><input type="button" name="b1" value="submit" onclick="fsubmit()"></p>
</form>
<div id="result"></div>
$name = isset($_POST['name'])? $_POST['name'] : '';
$gender = isset($_POST['gender'])? $_POST['gender'] : '';
$filename = time().substr($_FILES['photo']['name'], strrpos($_FILES['photo']['name'],'.'));
$response = array();
if(move_uploaded_file($_FILES['photo']['tmp_name'], $filename)){
$response['isSuccess'] = true;
$response['name'] = $name;
$response['gender'] = $gender;
$response['photo'] = $filename;
}else{
$response['isSuccess'] = false;
}
echo json_encode($response);
map可以做链式操作,forEach不可
let arr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
arr.map(i => i * 32).map(i => i.toString(16)).map(i => i.toUpperCase());
map和forEach语义上和功能上都是不一样的,一个是将数组映射到一个新的数组,一个是对数组进行遍历
forEach和for循环更多是个语法糖吧,写的时候可以省一些代码,感觉比较linq
而且for有很多种用法,比如一般的for+i,for...in...,for...of...
map 和 forEach 的主要区别:map 有返回值(返回修改后的数组),forEach 没有返回值。
###递归
var arr = ['A','B','C','D',"E","F","G"];
function show(arr,num){
debugger
var resultNum = 0;
var iNow = 1;
if(num==1){
return arr.length;
}
function change(arr,iNow){
for(var i=0;i<arr.length;i++){
var result = arr.concat();
result.splice(i,1);
if( iNow == num ){
resultNum += result.length;
}else{
change(result,iNow+1);
}
}
}
change(arr,iNow+1);
return resultNum;
}
console.log(show(arr,5));
###三维数组合并
$arr=[
1=>[
['field_name'=>'a','filed_id'=>1,'status'=>1],
['field_name'=>'a','filed_id'=>1,'status'=>0],
['field_name'=>'a','filed_id'=>1,'status'=>2],
],
2=>[
['field_name'=>'b','filed_id'=>2,'status'=>0],
['field_name'=>'b','filed_id'=>2,'status'=>0],
['field_name'=>'b','filed_id'=>2,'status'=>2],
],
];
$res=[];
foreach($arr as $key=>$val){
$res[$key] = ['field_name'=>$val[0]['field_name'],'filed_id'=>$val[0]['filed_id'],'status0'=>0,'status1'=>0,'status2'=>0];
foreach($val as $k=>$v){
/*if($v['status'] == 0){
$res[$key]['status0']+=1;
}elseif($v['status'] == 1){
$res[$key]['status1']+=1;
}elseif($v['status'] == 2){
$res[$key]['status2']+=1;
}*/
$res[$key]["status{$v['status']}"] += 1;
}
}
print_r($res);
$new_array = [];
foreach( $arr as $arr_key => $arr_val)
{
$allStatus = array_column($arr_val);
$statusCounts = array_count_values($allStatus);
// 最终输出新数组
$new_array[$arr_key] = [
'field_name' => $_val['field_name'],
'field_id' => $_val['field_id'],
'status0' => isset($statusCounts['0']) ? $statusCounts['0'] : 0,
'status1' => isset($statusCounts['1']) ? $statusCounts['1'] : 0,
'status2' => isset($statusCounts['2']) ? $statusCounts['2'] : 0,
];
}
Array
(
[1] => Array
(
[field_name] => a
[filed_id] => 1
[status0] => 1
[status1] => 1
[status2] => 1
)
[2] => Array
(
[field_name] => b
[filed_id] => 2
[status0] => 2
[status1] => 0
[status2] => 1
)
)
insert into worker set name=’tom’;
INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
--但不能这样
INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
insert into tbl_name1(col1,col2) select col3,col4 from tbl_name2;
--如果每一列都有数据
insert into tbl_name1 select col3,col4 from tbl_name2;
如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则执行旧行UPDATE。
--假设a,b为唯一索引,表table没有1,2这样的行是正常插入数据,冲突时,更新c列的值
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3;
--或者是
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=values(c);
--引用其他列更新冲突的行
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
SELECT * FROM `table` ORDER BY RAND() LIMIT 5
SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id
ORDER BY t1.id ASC LIMIT 5;
SELECT * FROM `table`
WHERE id >= (SELECT floor(RAND() * (SELECT MAX(id) FROM `table`)))
ORDER BY id LIMIT 1;
http://willko.iteye.com/blog/340686
在程序里随机n个最大id和最小id的中间数,查询的时候用in获得这几个中间数的记录
select * from table where id in (中间数1, 中间数2,中间数3)
SELECT * FROM Member WHERE Country = "HK" limit ?, 1
###查看文件git 历史
git diff 14b8..b410
git diff 14b8..b410 path/to/file/a path/to/file/b
gitk path/to/file
pip install git-playback
git playback [filename]
git blame filename
git log -p filename
git show history_commit_b history_commit_b_file50