php过滤敏感字符

$res = array('123','456','678');
$str = "123你好";
$res = array_combine($res,array_fill(0,count($res),'*'));
$to_str = strtr($str,$res);
return $to_str;

php+apache 上传大文件

1.编辑httpd.conf文件

修改 LimitRequestBody 655000000

2.编辑php.ini文件

file_uploads on;
upload_max_filesize 1000m #上传文件最大m

post_max_size 1000m #post数据最大m
max_execution_time 600 #每个PHP页面运行的最大时间值(秒),默认30秒
max_input_time 600 #每个PHP页面接收数据所需的最大时间,默认60秒
memory_limit 128m #每个PHP页面所吃掉的最大内存,默认8M

fastcgi_finish_request 一个另类的异步函数

最近看thinkphp5.1 源码的时候无意中发现了一个没有见过的函数fastcgi_finish_request 。

上网查了下,是一个基于fastcgi模式下的一个函数。是为了解决阻塞操作的函数。

例子:

<?php
echo '请求成功!';
fastcgi_finish_request(); //在这里就完成了,以下操作客户端不会运行
// 1. 初始化
for($i=0;$i<10;$i++){
        $ch = curl_init();
        // 2. 设置选项,包括URL
        curl_setopt($ch,CURLOPT_URL,"http://baidu.com");
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch,CURLOPT_HEADER,0);
        // 3. 执行并获取HTML文档内容
        $output = curl_exec($ch);
        if($output === FALSE ){
                echo "CURL Error:".curl_error($ch);
        }else{
                file_put_contents('log.txt','ok-'.$i, FILE_APPEND | LOCK_EX);
        }
        // 4. 释放curl句柄
        curl_close($ch);
}

运行下:

cat log.txt

php无限级分类引用模式

今天去面试,面试官问我,不用递归如何无限分类,然后面试官跟我说引用可以,接着我去网上搜了下。代码如下:

<?php
$array = array(
    array('id' => 1, 'pid' => 0, 'name' => '安徽省'),
    array('id' => 2, 'pid' => 0, 'name' => '浙江省'),
    array('id' => 3, 'pid' => 1, 'name' => '合肥市'),
    array('id' => 4, 'pid' => 3, 'name' => '长丰县'),
    array('id' => 5, 'pid' => 1, 'name' => '安庆市'),
    array('id' => 6, 'pid' => 4, 'name' => 'ddd'),
);

function generateTree($array)
{
    $items = array();
    foreach ($array as $value) {
        $items[$value['id']] = $value;
    }
    $tree = array();
    foreach ($items as $key => $value) {
        if (isset($items[$value['pid']])) {
            $items[$value['pid']]['childen'][] = &$items[$key];
        } else {
            $tree[] = &$items[$key];
        }
    }
    return $tree;

}

$tree = generateTree($array);
print_r($tree);

这段代码我已经测试过了,没问题的。

PHP反射类ReflectionClass 简单使用

详细接口请看:https://www.cnblogs.com/youyoui/p/7300340.html

例子:

这里有个需求,根据传过来的type,来判断是使用手机发送验证码还是邮箱发送验证码。

如果是以前的话,是这样做的:

首先新建一个email类:

<?php
class Email
{
  public function send(string $email)
  {
    var_dump("发送邮箱:".$email);
  }
}

phone类:

<?php
class Phone
{
  public function send(string $phone=null)
  {
    var_dump("发送电话:".$phone);
  }
}

index.php文件

<?php

function loadFun($className)
{
  require_once($className.'.php');
}

spl_autoload_register('loadFun');//自动加载函数

$type = "phone";

if($type=="phone")
{
  $phone = new Phone();
  $phone->send("11111");
}else{
  $email = new Email();
  $email->send("11111@qq.com");
}

这是旧的方法。

反射机制,把index改一下:

<?php

function loadFun($className)
{
  require_once($className.'.php');
}

spl_autoload_register('loadFun');

$type = "Phone";

$class = new ReflectionClass($type);
$name = $class->newInstance();
$name->send("13123");

只需要把type传递进来就可以实现了,不用再写这么多if语句去判断了。

php 神奇的trait

今天发现某些框架 直接use 一个类,就可以实现单例模式。我发现他们都是用了trait这个特性。

接着我自己写了一个 trait试了下

trait Single
{
    protected static $instance = null;

    private function __construct()
    {

    }

    public static function getInstance()
    {
        if(is_null(self::$instance)){
            self::$instance = new self();
        }
        return self::$instance;
    }
}

接着我找了之前的单例发送手机类

class SmsCode
{
    use Single;

    public function send()
    {
        var_dump("发送手机号码哦!");
    }
}

直接就可以应用了。

SmsCode::getInstance()->send()

php 简单使用 C语言编写一个 根据域名获取ip的函数

php版本 php-7.3.2

我们首先进入php安装包里面

cd ext/ 进入此目录

这时你会看见一个 ext_skel.php的文件

然后 ./ext_skel.php –ext say_hello (say_hello 可以随便取)

我们首先写一个示例先 这个示例是 写一个函数 输出 hello

我们cd进入 say_hello 这个目录

vim say_hello.c 可以看到很多乱七八糟的鬼东西 我们先不要管

我们在 这个 函数下面 定义一个 set_hello函数

PHP_FUNCTION(set_hello)
 {
         char *res;
         res = strpprintf(0,"hello world!");
         RETURN_STR(res); //把hello world 返回出去!
 }

接着我们找到 zend_function_entry 这里

把生成的 say_hello_test1 和 say_hello_test2 注释掉或del掉

然后 写上 PHP_FE(set_hello,NULL)

保存退出

接着 运行

/php/bin/phpize (这是我的目录 请根据自己的目录)

./configure –with-php-config=php/bin/php-config
(这是我的目录 请根据自己的目录)

make && make install

接着我们修改 php.ini 文件 添加 extension=say_hello.so

保存 我们写一个 test.php 测试一下

<?php
echo set_hello();

/php/bin/php test.php 运行

ok 完成。

接着我们回到正题

一些繁琐的步骤我就不写了

首先

./ext_skel.php –ext hello

接着 vim hello.c

我们在头部引入

#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>

接着新建一个函数

PHP_FUNCTION(yeye)
{
        struct hostent *h;
        zend_string *return_str;
        char *host;
        char strIp[32];
   // zend_parse_parameters 是获取传递过来的 测试 s 是字符串类型 &host就是传递过来的参数
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!",&host) == FAILURE){
                RETURN_NULL();
        }

        char ch = '/';
        char *ret;

        ret = strrchr(host, ch);
        if(ret)
        {
                ret = ret+1;
        }else
        {
                ret = host;
        }
        //gethostbyname 返回hostent结构体类型指针 这里判断是否成功 里面的参数可以上网查询
        if((h=gethostbyname(ret))!=NULL){
                //inet_ntop 将网络传输的二进制数值转化为成点分十进制的ip地址 不懂上网查询
                inet_ntop(h->h_addrtype,h->h_addr,strIp,sizeof(strIp));
                return_str = strpprintf(0,strIp);
                RETURN_STR(return_str);
        }else
        {
                RETURN_FALSE;
        }
}

修改 zend_function_entry

static const zend_function_entry hello_functions[] = {
        PHP_FE(yeye,NULL)
        PHP_FE_END
};

保存 然后根据前面的步骤编译就可以了

最后要把 extension=hello.so 加进 php.ini文件

好了我们测试下吧

<?php
if(!isset($_GET['url'])){
        exit("url不能为空!");
};
var_dump(yeye($_GET['url']));

保存 重启php-fpm 运行

成功的失败

失败的时候

参考教程:
https://blog.csdn.net/u011957758/article/details/72513935

php jwt代替session 无状态登录

因为我是在tp框架中运行的

首页下载tp框架 此版本为5.1版本

composer create-project topthink/think tp55

然后 下载 jwt php封装库

cd tp55

composer require firebase/php-jwt


然后在lib目录下新建Jwt.php 类

内容为

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/5/30
 * Time: 9:09
 */

namespace app\lib;

class Jwt
{
    public static function setJwt($data)
    {
        $key = md5("123456");
        $time = time(); //当前时间
        $token = [
            'iss' => 'https://www.huxierong.xyz', //签发者 可选
            'aud' => 'https://www.huxierong.xyz', //接收该JWT的一方,可选
            'iat' => $time, //签发时间
            'nbf' => $time, //(Not Before):某个时间点后才能访问,比如设置time+30,表示当前时间30秒后才能使用
            'exp' => $time + 432000, //过期时间,这里设置5天
            'data' => $data
        ];
        return \Firebase\JWT\JWT::encode($token, $key);
    }

    public static function getJwt($jwt)
    {
        try {
            $key = md5("123456");
            $res = \Firebase\JWT\JWT::decode($jwt, $key, ['HS256']);
            $arr = json_decode(json_encode($res), true);//转为数组
            return $arr;
        } catch (\Firebase\JWT\SignatureInvalidException $e) {  //签名不正确
            echo 'token签名校验不通过!';
        } catch (\Firebase\JWT\BeforeValidException $e) {  // 签名在某个时间点之后才能用
            echo 'token暂时未启用!';
        } catch (\Firebase\JWT\ExpiredException $e) {  // token过期
            echo 'token已过期!';
        } catch (\UnexpectedValueException $e)
        {
            echo "token非法!";
        }catch (\Exception $e)
        {
            echo "其他错误!";
        }
    }
}

在Index.php 控制器中新建两个方法

<?php
namespace app\index\controller;

use app\lib\Jwt;
use think\facade\Request;

class Index
{
    public function createJwt()
    {
        echo Jwt::setJwt(['user_id'=>1]);
    }

    public function getJwt()
    {
        $auth = Request::header('auth');
        dump(Jwt::getJwt($auth));
    }
}

在route.php里 添加2个路由

<?php
use \think\facade\Route;
Route::get("createJwt","index/Index/createJwt"); //创建jwt
Route::get("getJwt","index/Index/getJwt"); //获取jwt

在tp55这个根目录下运行

php think run -H 0.0.0.0 –port 3333

首先运行 createJwt

http://127.0.0.1:3333/createJwt

如果没有意外的话 就会打印出一串base64代码

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvd3d3Lmh1eGllcm9uZy54eXoiLCJhdWQiOiJodHRwczpcL1wvd3d3Lmh1eGllcm9uZy54eXoiLCJpYXQiOjE1NTkxNzkxNDYsIm5iZiI6MTU1OTE3OTE0NiwiZXhwIjoxNTU5NjExMTQ2LCJkYXRhIjp7InVzZXJfaWQiOjF9fQ.4MvOLasxrM-S7FghmYxvw_sl6Xu78b2xaaSnLFMjl4w

然后使用 postman 把这一串base64 扔进header auth里面

运行

就显示刚才加密的数据啦。

thinkphp5.1 微信支付实现 jsapi支付 和app支付

我们先下载 微信的sdk 改一下后目录

我定义了一个 抽象类 payment.php 为了以后接入其他支付

最主要的是WxPay.PHP

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/5/13
 * Time: 9:23
 */
namespace payment\weixin\pay;
use payment\payment;
use payment\weixin\lib\WxPayApi;
use payment\weixin\lib\WxPayNotify;
use payment\weixin\lib\WxPayUnifiedOrder;
use think\Exception;
class WxPay extends payment
{
    /**
     * 支付
     * @param $arr
     * @return array|mixed
     */
    public static function pay($arr)
    {
        try{
            $config = new WxConfig();
            //②、统一下单
            $input = new WxPayUnifiedOrder();
            //判断是公众号 还是 app
            if($arr['trade_type']=="JSAPI")
            {
                $tools = new JsApiPay();
                $openId = $tools->GetOpenid();
                $input->SetOpenid($openId);
            }
            $input->SetBody($arr['body']); //设置商品或支付单简要描述
            //订单自定义参数,回调携带返回
            if(array_key_exists('attach',$arr))
            {
                $input->SetAttach($arr['attach']);
            }
            //自定义 商户订单号
            $input->SetOut_trade_no($arr['trade_no']);
            //金额
            $input->SetTotal_fee($arr['total_fee']);
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));
            $input->SetNotify_url($arr['notify_url']);
            $input->SetTrade_type($arr['trade_type']);
            $order = WxPayApi::unifiedOrder($config, $input);

            if($arr['trade_type']=="JSAPI")
            {
                $orders = $tools->GetJsApiParameters($order);
                return ['status'=>1,'message'=>'OK','data'=>$orders];
            }
            return ['status'=>1,'message'=>'OK','data'=>$order];

        }catch (\Exception $e)
        {
            return ['status'=>0,'message'=>$e->getMessage(),'data'=>''];
        }

    }

    public static function notify($arr)
    {
        $notify = new WxPayNotify();
        $config = new WxConfig();
	    $res = $notify->Handle($config);

        if($res)
        {
            $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
            $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            $status = 1;
            $msg = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }else
        {
            $data = [];
            $status = 0;
            $msg = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>';
        }
        return ['status'=>$status,'msg'=>$msg,'data'=>$data];
    }

}

Index.php引用

<?php
namespace app\admin\controller;

use payment\weixin\pay\WxPay;
use think\Controller;

class Index extends Controller
{
public function index()
{
/*
* app支付
*/
// $arr = [];
// $arr['attach'] = [];
// $arr['trade_type'] = "APP";
// $arr['body'] = "body";
// $arr['trade_no'] = date("YmdHis").substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
// $arr['total_fee'] = 1;
// $arr['notify_url'] = "https://xxxx/wxNotify";
// $res = WxPay::pay($arr);
// $res['data'] = json_encode($res['data']);
// return json($res);

/*
* js公众号
*/
// $arr = [];
// $arr['attach'] = [];
// $arr['trade_type'] = "JSAPI";
// $arr['body'] = "";
// $arr['trade_no'] = date("YmdHis").substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
// $arr['total_fee'] = 1;
// $arr['notify_url'] = "https://xxxx/wxNotify";
// $res = WxPay::pay($arr);

}

/*
* 回调
*/
public function wxNotify()
{
$res = WxPay::notify([]);
if($res['status']==1)
{
echo $res['msg'];
}else
{
echo $res['msg'];
}
exit();
}


}

全部代码