• 2018-05-31

    PHP 获取周一,上个月的正确做法

    Views: 28958 | 3 Comments

    如果你理所当然地认为在 PHP 中获取周一,上周一,上个月,下个月这些时间能简单地用 strtotime() 函数来获取的话,那你就大错特错了!

    $now = strtotime('2018-01-31');
    echo date('Y-m-d', strtotime('+1 month', $now)) . "\n";
    

    输出的结果是:

    2018-03-03
    

    并不是期望的返回2月份的某一天,而返回了错误的3月份。为什么呢?这和 strtotime() 的实现原理有关:

    • 将月份加1,就变成了 2018-02-31
    • 因为2月没有31号,所以修正,从 2018-02-28 再往前加3天

    类似的,星期相关的代码也有问题。

    $now = strtotime('2018-05-20'); // 这一天是周日
    echo date('Y-m-d', strtotime('this monday', $now)) . "\n";
    echo date('Y-m-d', strtotime('+0 monday', $now)) . "\n";
    

    输出的结果是:

    2018-05-21
    2018-05-21
    

    +0 monday 和 +1 monday 的结果是一样的,并不能将这种格式理解为本周一和下周一(见评论),特别容易出错的是,你可能会错误地认为 +1 monday 是下周一,但事实不是。要得到下周N,或者下下周N,需要先求出本周一。本周一的求法如下:

    $now = strtotime('2018-05-20');
    $time = $now - 86400 * (date('N', $now) - 1);
    echo date('Y-m-d', $time) . "\n"; // 2018-05-14
    

    然后再用本周一加减N个7天,得出前后的周一,之后再根据周一求周N。还有,"+n monday" 和 "-n monday" 的结果和期望不同,其处理逻辑不一致。结合评论,+n xxx 是从当天(含)开始找,-n xxx 是从前一天开始找, +-0 按 +1 处理。

    一句话总结:PHP strtotime() 求上周,下周,上个月,下个月等,不能简单处理,需要特殊处理,都需要先求出本周一或者本周一号,再手动处理,而且星期的处理应该在求出本周一之后用时间戳整数运算。

    Posted by ideawu at 2018-05-31 19:09:33
  • 2017-05-17

    轻量级 COMET 服务器 icomet 支持 EventSource(SSE)

    Views: 27668 | No Comments

    最初的 COMET 技术,指的是 HTTP 长轮询,不过,随着时间的推进,许多能实现浏览器即时推送的技术都可被称为 COMET 技术。由我开发的基于 libevent 库的轻量级 COMET 服务器开源项目 icomet,支持主流的浏览器推送技术,并且支持移动端。

    最近,在网友的贡献下,icomet 支持了 HTML 5 的 Server-Sent Events(SSE, EventSource) 技术。这项技术也是 W3C 标准之一,详情可见:http://www.w3.org/TR/eventsource/

    在支持 HTML 5 的浏览器中使用 SSE,代码会非常简洁,示例如下:

    var source = new EventSource("http://127.0.0.1:8100/sse?cname=12&seq=1");
    source.onmessage = function(e) {
        document.body.innerHTML += e.data;
    };
    

    e.data 就是服务器推送的数据。icomet 项目源码中带有 demo/web/sse.html 脚本,你直接拖到浏览器里即可看运行效果。

    源码和示例下载:https://github.com/ideawu/icomet

    Posted by ideawu at 2017-05-17 14:21:01 Tags:
  • 2016-08-19

    集成于 iphp 框架的 PHP 并发模型和工具

    Views: 28173 | 2 Comments

    由于 PHP 具有"所思即所写"的强大优势, 使其在 Web 之外, 也被广泛用于后台脚本编写. 而且, 当你已经用 PHP 来开发 Web 应用时, 你显然不愿意再引入 Java 或者 Python 等语言, 再说, 这些语言相对 PHP 的强大优势, 显示太弱了.

    不过, 用 PHP 来编写后台脚本, 也有一些劣势, 那便是 PHP 缺少并发模型. 例如, 当你用 HTTP 请求第三方服务, 而第三方每一个请求要处理 10 秒时, 这就需要你并发地发起请求. curl_multi 当然能处理, 但不通用, 而且对代码逻辑的改变太大, 需要从串行化改为批量化, 对思维干扰太大.

    为此, PHP 提供了一套 Master-Workers 并发模型, 帮助你实现 PHP 的并发处理.

    Continue reading »

    Posted by ideawu at 2016-08-19 14:29:36
  • 2016-06-23

    单启动多个mysql实例mysqld_multi配置

    Views: 13860 | No Comments

    1. 创建 mysqld_multi.conf 配置

    [mysqld_multi]
    mysqld=/usr/bin/mysqld_safe  
    mysqladmin=/usr/bin/mysqladmin 
    user=AAA
    password=BBB
    
    
    [mysqld3306]
    port=3306
    datadir=/var/lib/mysql3306
    socket=/var/lib/mysql3306/mysql.sock
    pid-file=/var/lib/mysql3306/mysqld.pid
    log-error=/var/log/mysqld_3306.log
    user=mysql
    symbolic-links=0
    character-set-server = utf8
    skip-name-resolve
    
    server-id=123
    log-bin=mysql-bin
    log-slave-updates
    binlog-ignore-db=mysql
    binlog-ignore-db=test
    binlog-ignore-db=information_schema
    binlog-ignore-db=performance_schema
    replicate-ignore-db=mysql
    replicate-ignore-db=test
    replicate-ignore-db=information_schema
    replicate-ignore-db=performance_schema
    master-connect-retry=10
    max_connections=1000
    
    sort_buffer_size = 300M
    join_buffer_size = 300M
    key_buffer_size  = 300M
    innodb_buffer_pool_size = 4000M
    query_cache_size=200M
    

    注意, 要配置 user 和 password, 一会将要创建一个帐号用于 mysqld_multi.
    Continue reading »

    Posted by ideawu at 2016-06-23 16:27:32
  • 2016-06-23

    PHP过滤掉Emoji表情字符

    Views: 23887 | 1 Comment

    这段代码在 stackoverflow 上搜到, 据说是 Smarty 用的.

    function smarty_modifier_emojistrip($string)
    {       
        return preg_replace('/\xEE[\x80-\xBF][\x80-\xBF]|\xEF[\x81-\x83][\x80-\xBF]/', '', $string);
    }
    
    Posted by ideawu at 15:53:56
  • 2016-06-17

    一个简单的聊天或者私信系统设计

    Views: 17755 | 1 Comment

    不少网站都会内置聊天或者私信系统, 为了方便更多人, 现将一个最简单的聊天系统的接口设计放在这里, 这是一个基于 HTTP 的聊天系统设计.

    首先是视图设计:

    # view:
    
    msg/unread
    	(全局)未读消息列表
    chat
    	一对一聊天窗口
    chat/history
    	我的聊天记录(按人组织)列表
    

    接着是数据接口设计:

    # ajax:
    
    msg/unread/get
    	获取(全局)未读消息列表
    	@last_msg_id: 获取比此消息更晚的未读消息, 不包含该条消息.
    chat/get
    	获取一对一聊天记录
    	@user_id: (msg_id, user_id 必须传一个)聊天者
    	@msg_id: (msg_id, user_id 必须传一个)根据此消息, 可得到聊天者, 并可在显示聊天记录时定位到对应的消息
    chat/get_new
    	@user_id: 聊天者
    	@last_msg_id: 获取比此消息更晚的消息, 不包含该条消息.
    chat/send
    	发送消息
    chat/history/get
    	我的聊天记录(按人组织)列表
    

    其中, 带有 last_msg_id 参数的接口, 可用于轮询获取新消息, 以便在缺少推送机制(PUSH)时提供一种替代方案. 大多数情况下, 10秒一次的刷新频率能达到"实时聊天"的效果.

    当有推送机制时, 如采用 iComet, 推送机制只推送通知(notify), 实际的消息内容仍然通过带 last_msg_id 的接口获取. 也就是说, 把固定刷新频率, 改为受通知时刷新(PUSH + PULL 结合).

    另外, 消息的持久化可以使用 MySQL 数据库, 但更推荐 SSDB NoSQL 数据库, 可以 SSDB 能存储超过十亿条的聊天历史记录并能快速查询.

    基于 SSDB + iComet 的聊天系统 demo: https://github.com/ideawu/icomet-demos

    Posted by ideawu at 2016-06-17 17:51:27
|<<<123456789>>>| 1/28 Pages, 163 Results.