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中实现循环,并且其它的多条记录字段都是显示在循环中的一条记录中。

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。

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点开始工作。

07-04-2016 0 条评论

php.ini里有个session.gc_maxlifetime来设置过期时间,过期之后就根据session.gc_probability和session.gc_divisor的比例来扫描并删除session。

删除的概率是session.gc_probability=1 除以 session.gc_divisor = 100。
上面两个配置算的概率是1%,意思是每一次php请求,会有1%的概率发生回收,回收不活跃时间达到session.gc_maxlifetime设置时间的session文件。不活跃时间用文件的最后修改时间计算。