03-07-2017 0 条评论

我们在编码的时候,通过php解析标准xml数据,可能一行代码就可以搞定

$array = json_decode(json_encode((array)simplexml_load_string($xml)),1);

然而在使用非标准xml的时候,就不能解析了,这时候我们可以使用xmlParser来解析,
xmlParser:

<?php
/**
 * xmlParser
 *
 * @author     shashank Patel
 */

class xmlParser
{
    public $ssBlankShow = true;

    /**
    * @todo convert xml to array
    * @param string $contents
    * @param string $get_attributes
    * @param string $priority
    * @access public
    * @return mixed
    */
    public function xml2array($contents, $get_attributes=1, $priority = 'tag')
    {
        if(!$contents)
            return array();

        if(!function_exists('xml_parser_create'))
        {
            return array();
        }

        $parser = xml_parser_create('');
        xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parse_into_struct($parser, trim($contents), $xml_values);
        xml_parser_free($parser);

        if(!$xml_values)
            return;

        $xml_array = array();
        $parents = array();
        $opened_tags = array();
        $arr = array();

        $current = &$xml_array;

        $repeated_tag_index = array();

        foreach($xml_values as $data)
        {
            unset($attributes,$value);

            extract($data);

            $result = array();

            $attributes_data = array();

            if(isset($value))
            {
                if($priority == 'tag')
                    $result = $value;
                else
                    $result['value'] = $value;
            }

            if(isset($attributes) and $get_attributes)
            {
                foreach($attributes as $attr => $val)
                {
                    if($priority == 'tag')
                        $attributes_data[$attr] = $val;
                    else
                        $result['attr'][$attr] = $val;
                }
            }

            if($type == "open")
            {
                $parent[$level-1] = &$current;
                if(!is_array($current) or (!in_array($tag, array_keys($current))))
                {
                    $current[$tag] = $result;

                    if($attributes_data)
                        $current[$tag. '_attr'] = $attributes_data;

                    $repeated_tag_index[$tag.'_'.$level] = 1;

                    $current = &$current[$tag];

                }
                else
                {
                    if(isset($current[$tag][0]))
                    {
                        $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;

                        $repeated_tag_index[$tag.'_'.$level]++;
                    }
                    else
                    {
                        $current[$tag] = array($current[$tag],$result);

                        $repeated_tag_index[$tag.'_'.$level] = 2;

                        if(isset($current[$tag.'_attr']))
                        {
                            $current[$tag]['0_attr'] = $current[$tag.'_attr'];

                            unset($current[$tag.'_attr']);
                        }

                    }
                    $last_item_index = $repeated_tag_index[$tag.'_'.$level]-1;
                    $current = &$current[$tag][$last_item_index];
                }

            }
            elseif($type == "complete")
            {
                if(!isset($current[$tag]))
                {
                    $current[$tag] = $result;
                    $repeated_tag_index[$tag.'_'.$level] = 1;
                    if($priority == 'tag' and $attributes_data)
                        $current[$tag. '_attr'] = $attributes_data;

                }
                else
                {
                    if(isset($current[$tag][0]) and is_array($current[$tag]))
                    {
                        $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;

                        if($priority == 'tag' and $get_attributes and $attributes_data)
                        {
                            $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                        }

                        $repeated_tag_index[$tag.'_'.$level]++;

                    }
                    else
                    {

                        $current[$tag] = array($current[$tag],$result);

                        $repeated_tag_index[$tag.'_'.$level] = 1;

                        if($priority == 'tag' and $get_attributes)
                        {
                            if(isset($current[$tag.'_attr']))
                            {
                                $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                                unset($current[$tag.'_attr']);
                            }

                            if($attributes_data)
                            {
                                $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                            }
                        }
                        $repeated_tag_index[$tag.'_'.$level]++;
                    }
                }

            }
            elseif($type == 'close')
            {
                $current = &$parent[$level-1];
            }
        }

        return($xml_array);
    }

    /**
    * @todo convert array to xml
    * @param mixed $array
    * @param string $level
    * @param string $KeyForBlank
    * @access public    
    * @return mixed
    */
    public function array_to_xml($array, $level=1, $KeyForBlank = 'row')
    {
        $xml = '';

        if ($level==1)
        {
            $xml .= '<?xml version="1.0" encoding="UTF-8"?>'.
                "<musicbox><response>";
        }
        else if($level==11)
        {
            $xml .= '<?xml version="1.0" encoding="UTF-8"?>'."\n".
                "<xml>";
        }
        foreach ($array as $key=>$value)
        {

            $key = strtolower($key);
            $eleKey = $key;

            if (is_array($value))
            {
                if(sizeof($value)) {
                    if ( preg_match('/^\d+$/', $eleKey) ) $eleKey = $KeyForBlank;
                    $xml .= str_repeat("",$level)."<$eleKey>";
                    $level++;
                    $xml .= $this->array_to_xml($value, $level, $KeyForBlank);
                    $level--;
                    $xml .= str_repeat("",$level)."</$eleKey>";
                }
                else
                {  
                    if($eleKey == 'genre' || $this->ssBlankShow == true)
                        $xml .= str_repeat("",$level)."<$eleKey></$eleKey>";
                    else
                        $xml .= str_repeat("",$level)."<$eleKey />";
                }
            }
            else
            {
                if (trim($value)!='')
                {
                    if ( preg_match('/^\d+$/', $eleKey) ) $eleKey = $KeyForBlank;
                    if (htmlspecialchars($value)!=$value || $this->otherchar($value))
                    {
                        $xml .= str_repeat("",$level).
                                "<$eleKey>$value</$eleKey>";
                    }
                    else
                    {
                        $xml .= str_repeat("",$level).
                            "<$eleKey>$value</$eleKey>";
                    }
                }
                else
                {
                    if($eleKey == 'genre' || $this->ssBlankShow == true)
                        $xml .= str_repeat("",$level)."<$eleKey></$eleKey>";
                    else
                        $xml .= str_repeat("",$level)."<$eleKey />";
                }
            }
        }
        if ($level==1)
        {
            $xml .= "</response></musicbox>";
        }
        else if($level==11)
        {
            $xml .= "</xml>";
        }
        return $xml;
    }
    /**
    * @todo remove other char ('/\:/')
    * @param string $str
    * @access public    
    * @return mixed
    */


    public function otherchar($str)
    {
        return preg_match('/\:/', $str);
    }

}
使用方法:
$oXmlParser = new xmlParser();
$asArray = $oXmlParser->xml2array($resultXml);

$resultXml是xml的数据。
这时候返回的可能是多维数组,再通过foreach把最终的结果输出。

10-02-2017 0 条评论

在开发中,常遇到mysql查询一对多时,会显示成多条记录组成,这样在PHP环境中,去读取数据的时候,就会很麻烦,不能按照循环记录去读取。
使用下面方法可以解决这个问题,就可以使用循环去读取数据,其它的多条记录,显示在字段中,并且默认以逗号隔开。

数据表结构

A 表

id pid text

1 2 123
2 3 456

B 表

id aid con

1 2 111
2 2 222

SELECT a.id,a.text,group_concat(b.con) as con FROM a RIGHT JOIN b ON a.id=b.aid WHERE a.id=2 GROUP BY b.aid;
mysql> SELECT a.id,a.text,group_concat(b.con) as con FROM a RIGHT JOIN b ON a.id=b.aid WHERE a.id=2 GROUP BY b.aid;
+----+------+---------+
| id | text | con |
+----+------+---------+
| 2 | 456 | 111,222 |
+----+------+---------+
1 row in set

这样我们就可以PHP中实现循环,并且其它的多条记录字段都是显示在循环中的一条记录中。

14-09-2016 0 条评论

1. ./configure –prefix=/usr/local/nginx –add-module=/app/ngx_http_consistent_hash-master
安装第三方模块一致性哈希

2. make && make install

netstat -antp
可以看到是哪个进程及服务占用端口。

pkill – p http 强制杀死所有http服务

nginx 信号量

1.通过命令显示nginx服务

ps aux|grep nginx

2.杀死相应的进程(INT)

kill -INT 26733

3.优雅的关闭进程,即等请求结束后再关闭(QUIT)

kill -QUIT 26733

4.平滑的重启nginx(HUP)(无需重启nginx,就可以加载修改过的配置文件,此时也是优雅的关闭进程)

kill -HUP 26733

(备注:通过nginx提供的命令也可以执行操作,./sbin/nginx -s reload)

5.重读日志(USR1)

linux系统下一个文件对应着一个inode节点,因为nginx监听着当前的access.log节点,所以不管是重命名或者什么操作,日志都是写这个文件上。
可以通过如下命令,更改inode节点,重读日志,通过这个信号,我们可以把nginx下面的日志,按照每天的时间来存储。

kill -USR1 26733
(备注:通过nginx提供的命令也可以执行操作,./sbin/nginx -s reopen)

6. 当升级nginx软件时(USR2)配合(WINCH),可以平滑的升级,优雅关闭旧的进程,启用新版本的nginx进程。

tips:有些人觉得每次命令都要输个进程号很麻烦,有一种方法可以获取相应的PID。
cat logs/nginx.pid 可以显示相应的进程ID,所以可以使用命令:kill -INT ‘cat logs/nginx.pid’。

7. 通过命令可以查看配置文件正确

./sbin/nginx -t

8. nginx配置段
全局区
worker_processes 1 说明有1个子进程,这个值太大无益处,因为要争夺CPU,一般设置为CPU数*核数(如一个CPU,其中为4核),只需设置为4。

Event
一般是配置nginx进程与连接的特性。(如一个worker同时允许多少个连接)。
worker_connections 1024 一个子进程最大允许连1024个连接。
http
可以在server里面配置虚拟主机,可配IP、域名、端口。

9. 日志管理
nginx的server段有一条信息
#access_log logs/host.access.log main;
说明格式的日志是main格式,当然你也可以自定义格式。
main格式:
log_format main ‘$remote_addr – $remote_user[$time_local]”$request””
‘$status $body_bytes_sent “$http_referer”‘
‘$http_user_agent'”$http_x_forwarded_for”;
其中主要说下$http_x_forwarded_for这个选项,主要是用户在使用代理时,会把最后一层代理的IP加在头部信息中。

按照年月目录存诸当月每天的日志记录,需要使用到shell脚本以及crontab -e设置定时(定时计划)
sh:
#!/bin/bash
LOGPATH=/usr/local/nginx/logs/abc.com.access.log
BASEPATH=/data/$(date -d yesterday +%Y%m)
mkdir -p $BASEPATH
BAK = $BASEPATH/$(date -d yesterday +%d%H%M).abc.access.log
mv $LOGPATH $BAK
touch $LOGPATH
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`

10.Location
精准匹配
如果不写root html 这行,则会继承nginx的目录,如:/usr/local/nginx/html
location = /index.htm{
root /var/www/html/;
index index.htm index.html;
}
location = /{
root /var/www/html/;
index index.htm index.html;
}
location /index.htm{
root html;
index index.htm index.html;
}
通过上面的这三个location,我可以分析出,当浏览器输入一个地址的时候,如:localhost,那么默认就会走第二个location,因为第二个是走index.htm,又因为是走根目录,所以会再次转发,所以再一次走到第一个精准匹配,反之如果把第二个的换成index index.html index.htm;,则会走第三个,因为第一个精准匹配不到,只有第三个不是精准匹配,所以匹配成功。

Location总结流程:当一个URI发出来的时候,首先会去找精准匹配,如果有匹配到,则会返回;如果没有,那么就会走普通匹配,看是否命中多个,记忆最长的匹配结果,暂时不返回出去,继续去寻找正则匹配,如果有匹配正则,则会直接返回,如果没有的话,就会返回刚才记忆最长的普通匹配。

11.Rewrite
如可以禁用某个IP不允许访问
location = /{
if($remote_addr=192.16/8.1.100){
return 403;
}
//正则匹配
if($http_user_agent ~ msie){
rewrite ^.*$ /msie.html;
break; //这里如果不break,会循环重定向。
}
//通过变量自定义404
if(!-e $document_root$fastcgi_script_name){
rewrite ^.*$ /404.html;
break;
}
//set设置变量用法
可以用来达到多条件判断时作标记用,达到apache下的rewrite_condition的效果。
如下:判断IE并重写,且不用break;这里纯是学习set的用法。
if($http_user_agent ~* msie){
set $isie 1;
}
if($fastcgi_script_name == ie.html){
set $isie 0;
}
if($isie 1){
rewrite ^.*$ ie.html
}
root /var/www/html/;
index index.htm index.html;
}
注意:用url重写时,正则里如果有{},正则就要用双引号包起来。

12.Nginx与PHP整合
因为PHP与nginx是独立运行的,它不同于apache是把php当成一个模块在运行,所以nginx是通过fastcgi通讯,将所有的php请求转发到php-fpm进程。
配置如下:
location ~ \.php{
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/html/$fastcgi_script_name;
include fastcgi_param;
}
在linux下,如果使用mysql连接服务器的时候,如果是有localhost会采用socket连接,所以php.ini必须要配置,如:
修改php.ini的下面选项。
mysql.default_socket = /var/lib/mysql/mysql.sock
当然除此之外面不想修改的话,那么就使用127.0.0.1连接,采用的就是tcp协议连接。
13.gzip压缩
原理:
浏览器–请求–>声明可以接受gzip压缩或deflate压缩或sdch压缩等。
从http协议角度看,声明acceopt-encoding:gzip deflat sdch头部压缩的算法。
sdch是google推出的一种压缩方式。
gzip配置的常用参数
gzip on|off; #是否开启gzip
gzip_buffers 32 4k| 16 8k #缓冲(压缩在内存中缓冲几块?每块多大?)
gzip_comp_level[1-9] #推荐6 压缩级别(级别越高,压的越小,越浪费CPU计算资源)
gzip_disable #正则匹配 UA 什么样的uri不进行gzip
gzip_min_length 200 #开始压缩的最小长度(再小就不要压缩了,意义不大)
gzip_http_version 1.0|1.1 #开始压缩的http协议(可以不设置,目前都是1.1协议)
gzip_proxied #设置请求者代理服务器,该如何缓存内容。
gzip_types text/plain application/xml #对哪些类型的文件用压缩,如:text,html,css,xml,js
gzip_vary on|off #是否传输gzip压缩标志
注意:图片/mp3,这样的二进制文件,不必压缩。
因为压缩率比较小,比如100->80字节,而且压缩也是耗费CPU资源的。
特别小的文件,也没有必要压缩,因为压缩本身也是有字节的。
14.缓存设置(expires)
格式:
location ~ \.(jpg|jpeg|gif|png|css|js)${
root html
expires 1d;
}
其中日期格式为:expires 1s(秒),30m(分),2h(小时),1d(天)。
注意:服务器的日期格式一定要准确,否则可能造成缓存失效。
其实304状态也是一种好的缓存手段。
原理:服务器响应文件内容时,同时响应etag标签(内容的签名,内容一样,他也变),和last_modified_since标签。
下次浏览器去请求时,先发送头信息,如果检查出文件没有发生改变(修改时间及etag),如果没有,直接返回头信息,所以size是0,浏览 器知道没有文件没有改变,直接调用本地缓存。
15.nginx反向代理服务器+负载均衡
反向代理:
location ~ \.php${
proxy_pass http://192.168.1.2:8080;
}
这里把所有的php请求,转到192.168.1.2服务器,也就是反向代理。

负载均衡
location ~ \.(jpg|jpeg|gif|png)${
proxy_pass http://imgserver;
}
upstream imgserver{
server 192.168.1.200:81 weight=1 max_fails=2 fail_timeout=3;
server 192.168.1.200:82 weight=1 max_fails=2 fail_timeout=3;
}
server{
listen 81;
server_name localhost;
root html;
}
server{
listen 82;
server_name localhost;
root html;
}

16.nginx连接memcached
nginx首先连接memcache,如果有则输出数据,如果没有则连接到php,再去mysql找数据,再用memcache SET数据。
location / {
set $memcached_key “$uri”;
memcached_pass 127.0.0.1:11211;
error_page 404 /callback.php
}
首先连接memcache,添加一个key,这时key就是uri参数。
如果要给memcached,做集群就使用一致性哈希。
upstream mcserver{
consistent_hash $request_uri;//使用一致性哈希
server 192.168.1.250:11211;
server 192.168.1.250:11212;
server 192.168.1.250:11213;
}
location / {
set $memcached_key $request_uri;
memcached_pass mcserver;
error_page 404 /callback.php
}

memcache 也需要设置一致性哈希。
1.首先php需要添加多台memcache服务器。
2.修改php.ini,支持一致性哈希
memcache.hash_strategy=consistent
Upstream做负载均衡时,要用IP或者远程主机名,不要使用localhost。

17.安装统计模块,便于观察nginx状态
编译nginx的时候带上 –with-http_stub_status_module

location /status {
stub_status on;
access_log off;
allow 192.168.1.100;//允许这个IP访问
deny all;//其它禁止访问
}

18.nginx高并发优化

主要思路通过优化socket和文件
1.socket
系统层面:
最大连接数somaxconn
查看连接数 more /proc/sys/net/core/somaxconn
设置echo 50000 > /proc/sys/net/core/somaxconn
加快tcp连接的回收 recycle
cat /proc/sys/net/ipv4/tcp_tw_recycle 默认是0,不快速回收。需要改为1
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
空的tcp是否允许回收利用reuse
cat /proc/sys/net/ipv4/tcp_tw_reuse 默认是0,不回收利用。需要改为1
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
洪水攻击 不做洪水抵御
more /proc/sys/net/ipv4/tcp_syncookies 为1就是抵御,需要改为0
echo 0 > /proc/sys/net/ipv4/tcp_syncookies
nginx:
子进程允许打开的连接(worker_connections)
http连接快速关闭(keep_alivetime=0)
2.文件
系统层面:
ulimit -n 设置一个比较大的值
ulimit -n 50000
nginx:
子进程允许打开的文件 worker_limit_nofile
worker_limit_nofile 10000
19.服务器集群搭建
php-fpm启动,监听多个端口。
start.sh
#!/bin/sh
/usr/local/php/sbin/php-fpm -y /usr/local/php/etc/php-fpm.conf
/usr/local/php/sbin/php-fpm -y /usr/local/php/etc/php-fpm9001.conf
/usr/local/php/sbin/php-fpm -y /usr/local/php/etc/php-fpm9002.conf
/usr/local/php/sbin/php-fpm -y /usr/local/php/etc/php-fpm9003.conf
/usr/local/php/sbin/php-fpm -y /usr/local/php/etc/php-fpm9004.conf

02-08-2016 0 条评论

因为发现很多人不会源码安装lnmp环境,刚好准备搭建环境,所以把基本步骤写出来,以后大家照着敲就可以。
本次搭建使用的都是最新的nginx1.11.3和php7(号称比5.6有2倍的性能提升),以及mysql5.7.13(号称有着一倍的性能提升)。
首先我们来安装mysql5.7.13
因为使用的是ubuntu12.04所以使用deb安装,见地址,先下载下来。

wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-server_5.7.14-1ubuntu12.04_amd64.deb-bundle.tar

然后解压:

tar xvf mysql-server_5.7.14-1ubuntu12.04_amd64.deb-bundle.tar

会得到如下文件:

 1.mysql-common_5.7.14-1ubuntu14.04_amd64.deb
2.libmysqlclient20_5.7.14-1ubuntu14.04_amd64.deb
3.libmysqlclient-dev_5.7.14-1ubuntu14.04_amd64.deb
4.libmysqld-dev_5.7.14-1ubuntu14.04_amd64.deb
5.mysql-community-client_5.7.14-1ubuntu14.04_amd64.deb
6.mysql-client_5.7.14-1ubuntu14.04_amd64.deb
7.mysql-community-server_5.7.14-1ubuntu14.04_amd64.deb

依次安装执行:

sudo dpkg -i mysql-common_5.7.14-1ubuntu12.04_amd64.deb libmysqlclient20_5.7.14-1ubuntu12.04_amd64.deb libmysqlclient-dev_5.7.14-1ubuntu12.04_amd64.deb libmysqld-dev_5.7.14-1ubuntu12.04_amd64.deb mysql-client_5.7.14-1ubuntu12.04_amd64.deb mysql-community-server_5.7.14-1ubuntu12.04_amd64.deb

其间会提输入root密码。
添加mysql用户组和用户。
groupadd mysql
useradd -r -g mysql mysql
默认安装的文件在:
配置文件:/etc/mysql/my.cnf
datadir:/var/lib/mysql 需要赋予mysql权限 chown -R mysql:mysql ./
mysqld /usr/sbin/mysqld
如果安装完成之后没有看到data文件夹,可以操作下面的步骤。
/usr/sbin/mysqld –user=mysql –datadir=/var/lib/mysql/data/mysql –initial –initialize-insecure
现在可以启动mysql服务了。
/etc/init.d/mysql start
nginx安装
wget https://nginx.org/download/nginx-1.11.3.tar.gz
tar zxvf nginx-1.11.3.tar.gz
cd nginx-1.11.3
groupadd nginx
useradd -r -g nginx nginx

./configure --prefix=/usr/local/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_gzip_static_module \
--with-pcre \

通常安装nginx需要使用zip和pcre一个是用来数据传输压缩及使用正则表达式(rwrite)
make && make install
PHP安装
wget http://cn2.php.net/distributions/php-7.0.9.tar.gz
tar zxvf php-7.0.9.tar.gz
cd php-7.0.9

./configure --prefix=/usr/local/php7 \
--with-config-file-path=/usr/local/php7/etc \
--with-mcrypt=/usr/include \
--with-gd \
--with-iconv \
--with-zlib \
--enable-xml \
--enable-bcmath \
--enable-shmop \
--enable-sysvsem \
--enable-inline-optimization \
--enable-mbregex \
--enable-fpm \
--enable-mbstring \
--enable-ftp \
--enable-gd-native-ttf \
--with-openssl \
--enable-pcntl \
--enable-sockets \
--with-xmlrpc \
--enable-zip \
--enable-soap \
--without-pear \
--with-gettext \
--enable-session \
--with-curl \
--with-jpeg-dir \
--with-freetype-dir \
--enable-sockets \
--enable-opcache \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd

因为php7版本不支持mysql,所以这里不需要安装。
当然对于一个新的ubuntu系统,不能顺利的完成检测。
所以这时候就要根据系统的提示安装相应的软件,如:libxml2、jpg、png、curl等。
可以使用ubuntu系统自带的apt-get install。
make && make install
nginx与php-fpm通讯
一般安装完成php就有php-fpm,不过相应的配置文件可能要重新命名。
即php7/etc/php-fpm.conf.default
cp php-fpm.conf.default php-fpm.conf
因为fpm.conf默认使用的是nobody用户名及用户组,系统中是不存在的,所以需要新建。
groupadd nobody
useradd -r -g nobody nobody
现在切换到nginx,使它能与php-fpm通讯。
打开下面的注释。

 location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

至此,lnmp环境就已经装好了,现在你的程序开始启航了。

28-07-2016 0 条评论

因为之前的一个系统在使用PHPEXCEL导入的时候,出现了系统崩溃的问题,后面经过一步步的分析,在load()里面中断,系统无法响应。
解决这个问题其实很简单。
一般影响这个问题的原因,是你的excel里面的内容有出现特殊的字符。
解决方法:

try {
     $inputFileType = PHPExcel_IOFactory::identify($uploadfile);
     $objReader = PHPExcel_IOFactory::createReader($inputFileType);
     $objReader->setReadDataOnly(true);//只需要添加这个方法
     $objPHPExcel = $objReader->load($uploadfile);
    } catch(Exception $e) {
         die('Error loading file "'.pathinfo($uploadfile,PATHINFO_BASENAME).'": '.$e->getMessage());
    }

其意思就是读取相应的单元格的数据,忽略任何格式的信息。
我们来看下官方的代码。

    /**
     * Read data only?
     * Identifies whether the Reader should only read data values for cells, and ignore any formatting             information;
     * or whether it should read both data and formatting
     * @var boolean
     */
    protected $_readDataOnly = FALSE;

默认使用的是false。

20-06-2016 0 条评论

有时因为项目的需求,一个项目要布署多套系统,所以即使有版本控制往往也需要手动更新代码,造成项目维护性差。
下面通过shell脚本,可以通过svn up定时自动更新代码

#! /bin/sh
filelist=`ls /var/www/html/ |grep '^new_o2o_'`
for file in $filelist
do
   while read line
   do
   svn up ./$file/$line
   done < svn_update.txt
done

其中svn_update.txt 存储更新的文件路径,每行一个文件。
设置crontab -e 设置脚本运行时间。

14-06-2016 0 条评论

1.php错误日志保存
基本的方法是使用error_log进行保存,可以存放在一个目录下。
如:

error_log(
    date_default_timezone_set('asia/chongqing');

格式是:错误的日志,发生错误的级别,显示错误错的代码
如:
date().$a.’\r\n’,3,$b;

date(‘Y年m月d日—G小时i分钟s秒’).$变量名–将错误的日志赋值给这个变量.’\r\n’,3,’d:\dir—指的是存放的目录’;
)
2.php异常处理
请记住一点:PHP默认的异常处理是一个类,是系统默认的类,即:Exception。
1.基本语法

    try{
        //可能出现错误或是异常的代码
    }
    //catch 捕获  Exception 是异常类(是php定义好的一个类)
    catch(Exception e){
        //对异常处理
        //1.自己处理
        //2.自己不处理,将其抛出
    }

例子:

    try{
        a('addd');
        echo '12155';
    }catch(EXception $a){
    echo '失败了'.$a->getMessage();
    //可以继续抛出,这时将会启动PHP默认的异常处理器来处理。
    //你可以自定义一个顶级异常处理,见下文有介绍。
    }
    function a($name){
        if($name=='peng'){
            echo '这是正确的peng';
        }else{
            throw new Exception ('出错了');
        }
    }

//这种处理的方式,可以有效的控制错误,所以在开发中大量的使用。
注意事项:
1.当捕获到一个异常后,try{}里面后续代码将不会被执行,需要注意的是前面的代码可以执行,
那这到底是个什么样的意思呢?
如上的例子中,echo ‘12155’是不会被执行的,反之如果这样修改:

    try{
        echo '12155';
        a('addd');
        //这里的12155是会被执行的。
    }

2.定义一个顶级异常处理器

    function my_exception($e){
        echo '我是顶级异常处理器'.$e->getMessage();
    }

//修改默认的顶级异常处理函数(器)

set_exception_handler("my_exception");

3.如果一个异常发生,但是你没有catch捕获,则提示Uncatched Exception。
4.当catch一个异常,你可以处理,也可以不处理,不处就可以。

throw new Exception('信息');

5.使用多个catch代码块可以捕获不同种类的异常。

    try{
        //代码码...需要进行检测代码的异常
    }catch(PDOException $e){

    }catch(Exception $e){

    }

    try{
    $i=8/0;
    }catch(Exception $e){
    echo 'ok';
    echo $e->getMessage();
    }

这个例子并不会执行’ok’,原因是$i=8/0,并没有抛出异常。
所以可以看出,能不能捕获(catch)到异常,要取决于有没有真的抛出异常。

14-06-2016 0 条评论

我们知道在php里面,session默认保存的路径都是在/tmp/session或/var/lib/php5,这样就造成了这个目录里面的文件数太多,引发了PHP性能问题,所以我们可以设置多级目录,当然也可以把session放在mysql或者redis,这里我们只说分级目录,后续会讲mysql及redis方案。
首先,修改 php.ini的 session.save_path 选项修改如下:

session.save_path = “2;/tmp/session“  //这里设置2级就可以
session.hash_function = 1 //默认是为0(md5),这里设置为1(sha1)
session.hash_bits_per_character = 5 //指定在SID字符串中的每个字符内保存多少bit  4: 0-9, a-f ;5: 0-9, a-v; 6: 0-9, a-z, A-Z, “-“, “,”

找到PHP安装目录下的ext/session/mod_files.sh 通过脚本就可以生成目录。

#! /bin/sh
 
if test "$2" = ""; then
echo "usage: $0 basedir depth"
exit 1
fi
 
if test "$2" = "0"; then
exit 0
fi
 
hash_chars="0 1 2 3 4 5 6 7 8 9 a b c d e f"
if test "$3" -a "$3" -ge "5"; then
hash_chars="$hash_chars g h i j k l m n o p q r s t u v"
if test "$3" -eq "6"; then
hash_chars="$hash_chars w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z - ,"
fi
fi
 
for i in $hash_chars; do
newpath="$1/$i"
mkdir $newpath || exit 1
sh $0 $newpath `expr $2 - 1` $3
done

#cd /home
#./mod_files.sh /var/lib/php5 2 5 //参数表示 存放路径, 几级目录,每个目录生成多少个目录。
其中一点,需要注意其存储目录(/tmp/session或/var/lib/php5),要有相应的执行权限,可以给777。
因为通过使用session多级目录,php是不会释放资源的,所以需要我们自己写脚本定时清理。
rm_session_auto_mksession.sh

#! /bin/sh
rm -rf /var/lib/php5/*
/home/sh/session_mod_file.sh /var/lib/php5 2 5
chmod -R 777 /var/lib/php5

通过这个脚本和上面的脚本配合crontab -e就可以定时清理SESSION文件。
0 3 * * * /home/sh/rm_session_auto_mksession.sh,每天凌晨3点开始工作。

01-05-2016 0 条评论

我们在使用域名泛解析的时候,往往vhost里面并没有一条相关的记录,如:

ServerAlias *.abc.com

但是却同样可以使用泛解析,当域名已经配置相应的vhost那么则会优先去找相匹配的虚拟主机。
反之如果没有,则会获取default.conf中的第一条记录作为解析。
这时将忽略以下信息:

ServerAdmin webmaster@localhost
ServerName www.abc.com

直接去寻找相应的路径信息:

DocumentRoot /var/www/html/website

当然,你也可以禁止域名泛解析,就是在第一记录上增加:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        ServerName www.abc.com
        DocumentRoot /var/www/html/
        <location />
        Order deny,allow
        Deny from all
        </location>
</VirtualHost>
13-04-2016 0 条评论

像任何其他的操作系统一样,GNU/Linux 已经实现的内存管理不仅有效,而且更好。但是,如果有任何进程正在蚕食你的内存,而你想要清除它的话,Linux 提供了一个刷新或清除RAM缓存方法。
如何在 Linux 中清除缓存(Cache)?

每个 Linux 系统有三种选项来清除缓存而不需要中断任何进程或服务。

(LCTT 译注:Cache,译作“缓存”,指 CPU 和内存之间高速缓存。Buffer,译作“缓冲区”,指在写入磁盘前的存储再内存中的内容。在本文中,Buffer 和 Cache 有时候会通指。)

  1. 仅清除页面缓存(PageCache)

# sync; echo 1 > /proc/sys/vm/drop_caches

 

2. 清除目录项和inode

# sync; echo 2 > /proc/sys/vm/drop_caches

3.清除页面缓存,目录项和inode

# sync; echo 3 > /proc/sys/vm/drop_caches

上述命令的说明:

sync 将刷新文件系统缓冲区(buffer),命令通过“;”分隔,顺序执行,shell在执行序列中的下一个命令之前会等待命令的终止。正如内核文档中提到的,写入到drop_cache将清空缓存而不会杀死任何应用程序/服务,echo命令做写入文件的工作。

如果你必须清除磁盘高速缓存,第一个命令在企业和生产环境中是最安全,

"...echo 1&gt; ..."

只会清除页面缓存。 在生产环境中不建议使用上面的第三个选项

"...echo 3 &gt; ..."

,除非你明确自己在做什么,因为它会清除缓存页,目录项和inodes。

在Linux上释放也许被内核所使用的缓冲区(Buffer)和缓存(Cache)是否是个好主意?

当你设置许多设定想要检查效果时,如果它实际上是专门针对 I/O 范围的基准测试,那么你可能需要清除缓冲区和缓存。你可以如上所示删除缓存,无需重新启动系统(即无需停机)。

Linux被设计成它在寻找磁盘之前到磁盘缓存寻找的方式。如果它发现该资源在缓存中,则该请求不会发送到磁盘。如果我们清理缓存,磁盘缓存就起不到作用了,系统会到磁盘上寻找资源。

此外,当清除缓存后它也将减慢系统运行速度,系统会将每一个被请求的资源再次加载到磁盘缓存中。

现在,我们将创建一个 shell 脚本,通过一个 cron 调度任务在每天下午2点自动清除RAM缓存。如下创建一个 shell 脚本 clearcache.sh 并在其中添加以下行:

#!/bin/bash
# 注意,我们这里使用了 "echo 3",但是不推荐使用在产品环境中,应该使用 "echo 1"
echo "echo 3 > /proc/sys/vm/drop_caches"

给clearcache.sh文件设置执行权限

# chmod 755 clearcache.sh

现在,当你需要清除内存缓存时只需要调用脚本。

现在设置一个每天下午2点的定时任务来清除RAM缓存,打开crontab进行编辑。

# crontab -e

添加以下行,保存并退出。

0 3 * * * /path/to/clearcache.sh

有关如何创建一个定时任务,更多细节你可以查看文章 11 个定时调度任务的例子

在生产环境的服务器上自动清除RAM是否是一个好主意?

不!它不是。想想一个情况,当你已经预定脚本在每天下午2点来清除内存缓存。那么其时该脚本会执行并刷新你的内存缓存。在某一天由于某些原因,可能您的网站的在线用户会超过预期地从你的服务器请求资源。

而在这时,按计划调度的脚本运行了,并清除了缓存中的一切。当所有的用户都从磁盘读取数据时,这将导致服务器崩溃并损坏数据库。因此,清除缓存仅在必要时并且在你的预料之中,否则你就是个呆瓜系统管理员。

如何清除Linux的交换空间?

如果你想清除掉的空间,你可以运行下面的命令:

# swapoff -a && swapon -a

此外,了解有关风险后,您可以将上面的命令添加到cron中。

现在,我们将上面两种命令结合成一个命令,写成正确的脚本来同时清除RAM缓存和交换空间。

# echo 3 > /proc/sys/vm/drop_caches && swapoff -a && swapon -a && printf '\n%s\n' 'Ram-cache and Swap Cleared'

su -c 'echo 3 > /proc/sys/vm/drop_caches' && swapoff -a && swapon -a && printf '\n%s\n' 'Ram-cache and Swap Cleared'

在测试上面的命令之前,我们在执行脚本前后运行“free -m” 来检查缓存。

free -h 检查内存使用情况

free -h 检查内存使用情况