php 数组实现简单队列

<?php
class Que {
  //队列最大值
  protected $m = 10;
  //头指针
  protected $h = 0;
  //尾脂针
  protected $t = 0;
  //是否安全
  protected $isSave = false;

  function __construct($isSave = false)
  {
      $this->isSave = $isSave;
      $this->arr = array_fill(0, $this->m, null);
  }

  /**
   * $n >= -100
   * 满返回-999
   * 不满返回入队列后队列元素的数目
   * 
   */

  function in($n){
      if($this->isSave){
        static::lock('in');
      }

      if($n < -100){
        throw new \Exception("数据异常", 1);
      }
      
      if( !$this->canIn() ){
        return -999;
      }


      $this->t = $this->newInOffset();
      $this->arr[$this->t] = $n;

      return $this->getLength();
  }

  /**
   * 空返回-999
   * 非空返回出队列的值
   */
  function out(){
    if($this->isSave){
      static::lock('out');
    }

    if(!$this->canOut()){
        return -999;
    }
    
    $n = $this->arr[$this->h];
    unset($this->arr[$this->h]);
    $this->arr[$this->h] = null;
    $this->h = $this->newOutOffest();
    return $n;
  }

  /**
   *获取数组长度
   */
  function getLength(){
    if($this->isEmpty()) return 0;
    if($this->t < $this->h){
      $l = $this->m - $this->h + $this->t;
    }else{
      $l = $this->t - $this->h;
    }
    return $l + 1;
  }

  /**
   * 判断数组是否为空数组
   */
  function isEmpty(){
    return $this->h == $this->t && is_null($this->arr[$this->h]);
  }

  /**
   *获取入队后的尾指诊偏移量
   */
  function newInOffset(){
      if( $this->isEmpty() ){//是否是空队列
          return $this->t;
      }

      return ($this->t + 1) % $this->m;
  }

  /**
   *判断出队后头指诊的偏移量
   */
  function newOutOffest(){
    if(!$this->isEmpty() && $this->h == $this->t){
        return $this->h;
    }

    return ($this->h + 1) % $this->m;
  }

  /**
   *能否入队
   */
  function canIn(){
    return is_null($this->arr[$this->newInOffset()]);
  }

  /**
   *能否出队
   */
  function canOut(){
    return !is_null($this->arr[$this->h]);
  }

  /**
   *获取队列内容
   */
  function getQueList(){
    return $this->arr;
  }

  /**
   *加锁
   */
  public static function lock($name, $ex = 60)
  {
      if ($res = Redis::setnx($name, '1', 'NX')) {
          Redis::expire($name, $ex);

          register_shutdown_function(function () use ($name) {
              Que::unlock($name);
          });
      } else {
          throw new \Exception('执行中,请稍等');
      }
  }

  /**
   * 解锁
   */
  public static function unlock($name)
  {
      Redis::del($name);
  }
}

/**
$q = new Que;
for($i = 0; $i < 20; $i++){
    $r = $q->in($i);
    var_dump($r);
    if($i % 3 == 0){
      var_dump("out : ".$q->out());
    }
}

for($i = 0; $i < 20; $i++){
  var_dump("out : ".$q->out());
}
**/


发表在 php, php函数集, php小程序, 基础 | 留下评论

dyld: Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib 解决方案

dyld: Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib
解决方案

ln -s /usr/local/opt/readline/lib/libreadline.dylib /usr/local/opt/readline/lib/libreadline.7.dylib

发表在 MAC | 留下评论

docker 设置时区

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

发表在 docker | 留下评论

简单易用分布式锁

class PublicFunc{
    public static function lock($name, $ex = 60)
    {
        if ($res = Redis::setnx($name, '1')) {
            Redis::expire($name, $ex);

            register_shutdown_function(function () use ($name) {
                PublicFunc::unlock($name);
            });
        } else {
            throw new \Exception('执行中,请稍等');
        }
    }

    public static function unlock($name)
    {
        Redis::del($name);
    }
}
发表在 php, php 优化, php函数集 | 留下评论

nginx 504 Gateway Time-out

方向代理增加超时时间
location ~ /api {
proxy_pass http://127.0.0.1:8081;
proxy_read_timeout 3600;//反向代理读取超时时间,默认60秒
}

发表在 nginx | 留下评论

根据生日计算年龄



    public static function getAgeFromBirthDay($birthday)
    {
        $bday = new \DateTime($birthday); // 你的出生日

        $today = new \Datetime(date('Y-m-d'));

        $diff = $today->diff($bday);
        return $diff->y;
    }
发表在 php, php函数集, 基础 | 留下评论

跨域访问设置方式

header('Access-Control-Allow-Origin: *');//允许跨域域名
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, OPTIONS, DELETE');//允许跨域方式
header('Access-Control-Allow-Headers: *');//允许header
header('Access-Control-Expose-Headers: *');//某些header无法传递,须要指明header白名单(content-type 就在此列)
发表在 js, 前端, 设计模式, 运维 | 留下评论

js ISO-8859-1 转中文

fetch 获取的 header 内容如果是中文(多子节),则会转译成 ISO-8859-1 编码格式,需要转编码转换

var str = “ç\u0088±æ\u0088\u0091ä¸\u00ADå\u009B½”;
var utfstring =decodeURI(escape(str))//先编码再解码
//或者 utfstring =decodeURIComponent(escape(str)) 

decodeURIComponent 和 decodeURIComponent 区别具体看这里。encodeURI 自身无法产生能适用于HTTP GET 或 POST 请求的URI,例如对于 XMLHTTPRequests, 因为 “&”, “+”, 和 “=” 不会被编码,然而在 GET 和 POST 请求中它们是特殊字符。然而encodeURIComponent这个方法会对这些字符编码
参考

发表在 js, 前端 | 留下评论

fetch 下载流文件

前后端分离的项目,前端大部分使用fetch调用接口,遇到下载的时候,服务器接口一般直接返回流文件(链接本身就是一个文件)

const getExport = async (url) => {
    let options = _headerOptions('GET')
    let response = await fetch(config.apiHost+url,options)

    response.blob().then((blob) => {
        const a = window.document.createElement('a');
        const downUrl = window.URL.createObjectURL(blob);// 获取 blob 本地文件连接 (blob 为纯二进制对象,不能够直接保存到磁盘上)
        const filename = response.headers.get('Content-Disposition').split('filename=')[1].split('.');
        a.href = downUrl;
        a.download = `${decodeURI(escape(filename[0]))}.${filename[1]}`;
        a.click();
        window.URL.revokeObjectURL(downUrl);
    });

    return [];
}
发表在 js, 前端 | 留下评论

curl命令上传文件

curl 'http://xxxxxx' -F "theFile=/Users/xxxx/Downloads/1.jpg;filename=xxxx"

后台接收到的信息

var_dump($_FILE);
/*
array(1) {
  ["theFile"]=>
  array(6) {
    ["name"]=>
    string(7) "xxxx"
    ["tempName"]=>
    string(14) "/tmp/phpnk5HXI"
    ["tempResource"]=>
    array(0) {
    }
    ["type"]=>
    string(0) ""
    ["size"]=>
    int(36)
    ["error"]=>
    int(0)
  }
}
*/
发表在 Shell | 留下评论