文档转换

1.使用phpword 实现word->pdf

require_once("includes/PHPWord/vendor/autoload.php");

$inputfile = "files/temp/offerte_Hankie-Pankie.docx";

$path = realpath(realpath(__DIR__) . '/includes/dompdf');

echo "realpath: " . $path;

\PhpOffice\PhpWord\Settings::setPdfRendererPath($path);
\PhpOffice\PhpWord\Settings::setPdfRendererName(\PhpOffice\PhpWord\Settings::PDF_RENDERER_DOMPDF);

//Load temp file
$phpWord = \PhpOffice\PhpWord\IOFactory::load($inputfile); 

//Save it
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord , 'PDF');
$xmlWriter->save('result.pdf');

2.Html2word

https://packagist.org/packages/cshaptx4869/html2word

3.word->html

https://segmentfault.com/a/1190000019821351?utm_source=tag-newest

4.PDFdo:

http://www.pdfdo.com/doc-to-pdf.aspx

5.cshaptx4869/html2word

https://packagist.org/packages/cshaptx4869/html2word

PHP实现二维数组(或多维数组)转换成一维数组的常见方法总结

本文实例总结了PHP实现二维数组(或多维数组)转换成一维数组的常见方法。分享给大家供大家参考,具体如下:

假设有下面一个二维数组:

$user = array(
  '0' => array('id' => 100, 'username' => 'a1'),
  '1' => array('id' => 101, 'username' => 'a2'),
  '2' => array('id' => 102, 'username' => 'a3'),
  '3' => array('id' => 103, 'username' => 'a4'),
  '4' => array('id' => 104, 'username' => 'a5'),
);

现在要转换成一维数组,有两种情况:

一种是将指定列转换成一维数组,这在另一篇文章有总结:PHP提取多维数组指定一列的方法总结

现在我们重点讲第二种情况,就是把所有的值都转换成一维数组,而且键值相同不会被覆盖,转换后的一维数组是这样的:

$result = array(100, 'a1', 101, 'a2', 102, 'a3', 103, 'a4', 104, 'a5');

主要有下面几个方法。

1 array_reduce函数法

用array_reduce()函数是较为快捷的方法:?

$result = array_reduce($user, function ($result, $value) {
  return array_merge($result, array_values($value));
}, array())

因为array_merge函数会把相同字符串键名的数组覆盖合并,所以必须先用array_value取出值后再合并。

如果第二维是数字键名,如:

$user = array(
  'a' => array(100, 'a1'),
  'b' => array(101, 'a2'),
  'c' => array(102, 'a3'),
  'd' => array(103, 'a4'),
  'e' => array(104, 'a5'),
);

那么直接这样就可以了:

$result = array_reduce($user, 'array_merge', array())

2 array_walk_recursive函数法

用array_walk_recursive()函数就非常灵活,可以把任意维度的数组转换成一维数组。

$result = [];
array_walk_recursive($user, function($value) use (&$result) {
  array_push($result, $value);
});

例如,下面这个多维数组:

$user4 = array(
  'a' => array(100, 'a1'),
  'b' => array(101, 'a2'),
  'c' => array(
    'd' => array(102, 'a3'),
    'e' => array(103, 'a4'),
  ),
);

用这个方法后就变成:

$result = array(100, 'a1', 101, 'a2', 102, 'a3', 103, 'a4');

3 array_map函数法

用array_map和array_reduce函数的方法类似,如下:

$result = [];
array_map(function ($value) use (&$result) {
  $result = array_merge($result, array_values($value));
}, $user);

只是需要多声明一个空的$result数组。

另外,也可以用array_walk的方法,和foreach循环的方法,原理和上面一样。

curl之采集QQ空间留言

主要流程解析

  • 首先,打开浏览器登录QQ空间并访问留言列表
  • 由于QQ空间的链接是https,curl方式请求https链接需要突破https认证,这就需要下载cacert.pem,下面请看cacert.pem的部署步骤
1、将下载的`cacert.pem`文件放至php安装目录下,比如:"D:\wamp\bin\php\php5.5.12";
2、在php.ini文件末尾追加以下配置

curl.cainfo="D:/wamp/bin/php/php5.5.12/cacert.pem"
openssl.cafile="D:/wamp/bin/php/php5.5.12/cacert.pem"
3、重启wamp服务器
4、上面步骤操作完毕,即可用curl方式访问QQ空间数据了

注意事项

  • 1、一定要设置时区为中国时区(避免cookie不同时区而自动过期)
  • 2、在PHP 的命令行模式下执行(避免超时问题)

扩展

通过QQ空间留言的采集,可以扩展下,比如采集空间日志、说说、图片,再比如,可以尝试刷留言(最好定时执行刷留言)。

完整代码示例

<?php

date_default_timezone_set('PRC');
//内存无限制
ini_set('limit_memory', -1);
//代码执行不超时
set_time_limit(0);

//爬取QQ空间留言url
$baseUrl = "https://user.qzone.qq.com/proxy/domain/m.qzone.qq.com/cgi-bin/new/get_msgb?";

////查找留言下一页规律
//第一页
//uin=928692509&hostUin=928692509&start=0&s=0.4852990803750179&format=jsonp&num=10&inCharset=utf-8&outCharset=utf-8&g_tk=1467544760&qzonetoken=e1fa4e2c8b873a4bf33b86e6f4838942ed7a538c10b5b8cb52e2bf4a959d253f90691c5ed8b045ada7&g_tk=1467544760
//第二页
//uin=928692509&hostUin=928692509&start=10&s=0.4852990803750179&format=jsonp&num=10&inCharset=utf-8&outCharset=utf-8&g_tk=1467544760&qzonetoken=e1fa4e2c8b873a4bf33b86e6f4838942ed7a538c10b5b8cb52e2bf4a959d253f90691c5ed8b045ada7&g_tk=1467544760

//爬取QQ空间留言(自己或QQ好友)
$hostUinArr = [
        '1270612806'=>'飞得更高', '928692509'=>'Burning', '2075425089'=>'怒放的生命'
    ];

//遍历采集QQ好友空间留言
foreach($hostUinArr as $hostUin=>$qqName) {
    downloadHostUinMessage($baseUrl, $hostUin, $qqName);
}

//以好友名称为目录,将下载下来的留言单独存放
function downloadHostUinMessage($baseUrl, $hostUin, $qqName){
    $qqName = iconv('UTF-8', 'GBK', $qqName);
    $dir = './qqMessage/'.$qqName;
    
    if(!is_dir($dir)) {
        mkdir($dir, 0777, true);
    }
    
    $totalPages = 1;
    
    for($i=0; $i<$totalPages; $i++){
        $start = $i*10;
        $params = "uin=928692509&hostUin={$hostUin}&start={$start}&s=0.4852990803750179&format=jsonp&num=10&inCharset=utf-8&outCharset=utf-8&g_tk=1467544760&qzonetoken=e1fa4e2c8b873a4bf33b86e6f4838942ed7a538c10b5b8cb52e2bf4a959d253f90691c5ed8b045ada7&g_tk=1467544760";
        
        $url = $baseUrl . $params;
        $iContent = qqCommentCurl($url);
        
        $iContent = str_replace('_Callback(', '', $iContent);
        $iContent = trim(substr($iContent, 0, -2));
        //计算总页数,保证留言采集完
        if($totalPages == 1) {
            $iContentObj = json_decode($iContent);
            if(isset($iContentObj->code) && $iContentObj->code == 0) {
                $dataObj = $iContentObj->data;
                $totalPages = ceil($dataObj->total/10);
            } else {
                //结束
                return false;
            }
        }
        
        file_put_contents($dir.'/'.$hostUin.'_'.$i.'.txt', $iContent);
    }
}

/**
 * @author RenZhicai
 * QQ空间留言请求curl
 * @param type $url
 * @return type
 */
function qqCommentCurl($url='')
{
    $ch = curl_init();
    //需要获取的 URL 地址,也可以在curl_init() 初始化会话的时候。
    curl_setopt($ch, CURLOPT_URL, $url);
    //TRUE 将curl_exec()获取的信息以字符串返回,而不是直接输出。
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    if(preg_match('/http:\/\//', $url)) {
        //FALSE 禁止 cURL 验证对等证书(peer's certificate)。要验证的交换证书可以在 CURLOPT_CAINFO 选项中设置,或在 CURLOPT_CAPATH中设置证书目录。
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //这个是重点。
    }
    
    //启用时会将头文件的信息作为数据流输出。
    curl_setopt($ch, CURLOPT_HEADER, 0); 
    //TRUE 时将会根据服务器返回 HTTP 头中的 "Location: " 重定向。(注意:这是递归的,"Location: " 发送几次就重定向几次,除非设置了 CURLOPT_MAXREDIRS,限制最大重定向次数。)。
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 这样能够让cURL支持页面链接跳转

    //header头信息
    $headerArr = [
        "accept-language: zh-CN,zh;q=0.8",
        "user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"
    ];
    //设置 HTTP 头字段的数组。格式: array('Content-type: text/plain', 'Content-length: 100')
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArr);
    
    curl_setopt($ch, CURLOPT_AUTOREFERER, true);
    
    //设置新的cookie,忽略之前会话时存的cookie
    curl_setopt($ch, CURLOPT_COOKIESESSION, TRUE);
    //包含 cookie 数据的文件名
    curl_setopt($ch, CURLOPT_COOKIEFILE, 'daoyancookiefile');
    //连接结束后,比如,调用 curl_close 后,保存 cookie 信息的文件。
    curl_setopt($ch, CURLOPT_COOKIEJAR, 'daoyancookiefile');

    //登录后的cookie信息  
    $cookieStr = "cookie: pgv_pvi=9803880448; tvfe_boss_uuid=7aa8e6046d68c6a2; RK=qBcndcbOTD; eas_sid=K1s5q0V8H8N5B4c1j9e2L0D8W3; pgv_pvid=8596381360; o_cookie=928692509; __Q_w_s_hat_seed=1; __Q_w_s__QZN_TodoMsgCnt=1; ptcz=dab5485d33e04f8612e84673ce0609bdcae13f792156f92dccf5a9784988a16a; uin=o0928692509; skey=@CgmH4oeQ8; pt2gguin=o0928692509; p_uin=o0928692509; pt4_token=Lub2nMWbTLfbx0TYxH*uyDBOU4tEBXvKvv0JNQRQuGo_; p_skey=MxE5cMJA2xHQ8BXgpbVqSL3hgeoEfcq-quN1kvcUrcQ_; pgv_info=ssid=s7150557986; Loading=Yes; qz_screen=1366x768; qqmusic_uin=; qqmusic_key=; qqmusic_fromtag=; qzmusicplayer=qzone_player_928692509_1509368391144; QZ_FE_WEBP_SUPPORT=1; cpu_performance_v8=6";
    //设定 HTTP 请求中"Cookie: "部分的内容。多个 cookie 用分号分隔,分号后带一个空格(例如, "fruit=apple; colour=red")。
    curl_setopt($ch, CURLOPT_COOKIE, $cookieStr);

    $output = curl_exec($ch);
    if($output === false){
                //记录curl请求失败的详情
        $errorInfo = "cURL Error: ".curl_error($ch);
        file_put_contents('curl_error_'.date('YmdHis').'.txt', $errorInfo);
    }
    
    curl_close($ch);

    return $output;
}

采集效果一览

PHP date_format

面向对象风格 <?php
$date = new DateTime('2000-01-01');
echo $date->format('Y-m-d H:i:s');
?>

过程化风格 <?php
$date = date_create('2000-01-01');
echo date_format($date, 'Y-m-d H:i:s');
?>

以上例程会输出:

2000-01-01 00:00:00

利用Swoole实现PHP+websocket直播,即使通讯代码,及linux下swoole安装基本配置

php安装swoole

1. 下载swoole安装

wget http://pecl.php.net/get/swoole-1.9.1.tgz
tar -zxvf swoole-1.9.1.tgz
cd swoole-1.9.1
phpize
./configure
make
make install

2. 在php.ini添加swoole.so

extension=swoole.so

php -m查看是否安装成功

环境依赖

  • 仅支持Linux,FreeBSD,MacOS,3类操作系统
  • Linux内核版本2.3.32以上
  • PHP5.3.10以上版本
  • gcc4.4以上版本或者clang
  • cmake2.4+,编译为libswoole.so作为C/C++库时需要使用cmake 

PHP版本依赖

  • swoole仅支持PHP5.3.10或更高版本,建议使用PHP5.4+
  • swoole不依赖php的stream、sockets、pcntl、posix、sysvmsg等扩展。PHP只需安装最基本的扩展即可 

PHP直播代码

1.start.php 使用时需要开启,服务器输入(php start.php)

<?php
//php在线直播示例代码
//使用PHPCLI模式运行
//命令:php start.php

//设置路径
define('_ROOT_', dirname(__FILE__));
require_once _ROOT_.'/function.php';
//监听地址和端口
$server = new swoole_websocket_server("0.0.0.0(这里就是四个0,不要改)", 8888);
//服务端接收连接事件
$server->on('open', function (swoole_websocket_server $server, $request) {
    if(!file_exists(_ROOT_.'/client/'.$request->fd.'.client')){
        @file_put_contents(_ROOT_.'/client/'.$request->fd.'.client',$request->fd);
    }
});
//服务端接收信息事件
$server->on('message', function (swoole_websocket_server $server, $frame) {
    foreach(notice(_ROOT_.'/client/') as $v){
            $server->push($v,$frame->data);
    }
});
//服务端接收关闭事件
$server->on('close', function ($ser, $fd) {
    @unlink(_ROOT_.'/client/'.$fd.'.client');
});
//服务开启
$server->start();

2.index.html 直播页面,访问该页面观看直播

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>在线直播界面</title>
</head>
<body>
<img id="receiver" style='width:640px;height:480px'/>
<script type="text/javascript" charset="utf-8">
    var ws = new WebSocket("ws://改成自己服务器ip:8888");
    var image = document.getElementById('receiver');
    ws.onopen = function(){

    }
    ws.onmessage = function(data)
    {
        image.src=data.data;
    }
</script>
</body>
</html>

3.rec.html主播录制页面,访问该页面进行直播录制

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>主播录制界面</title>
</head>
<body>
<video id="video" autoplay="" style='width:640px;height:480px'></video>
<canvas id="output" style="display:none"></canvas>
<script type="text/javascript" charset="utf-8">
    var ws = new WebSocket("ws://自己服务器ip:8888");
    var back = document.getElementById('output');
    var backcontext = back.getContext('2d');
    var video = document.getElementById("video");
    var success = function(stream){
        video.src = window.URL.createObjectURL(stream);
    }
    ws.onopen = function(){
        draw();
    }
    var draw = function(){
        try{
            backcontext.drawImage(video,0,0, back.width, back.height);
        }catch(e){
            if (e.name == "NS_ERROR_NOT_AVAILABLE") {
                return setTimeout(draw, 100);
            } else {
                throw e;
            }
        }
        if(video.src){
            ws.send(back.toDataURL("image/jpeg", 0.5));
        }
        setTimeout(draw, 100);
    }
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
    navigator.mozGetUserMedia || navigator.msGetUserMedia;
    navigator.getUserMedia({video:true, audio:false}, success, console.log);
</script>
</body>
</html>

4.function.php 统计数据页面

<?php
//统计在线人数
function clearDir($dir)
{
    $n = 0;
    if ($dh = opendir($dir))
    {
        while (($file = readdir($dh)) !== false)
        {
            if ($file == '.' or $file == '..')
            {
                continue;
            }
            if (is_file($dir . $file)) {
                $n++;
            }
        }
    }
    closedir($dh);
    return $n;
}

//通知在线的人
function notice($dir){
    if ($dh = opendir($dir))
    {
        while (($file = readdir($dh)) !== false)
        {
            if ($file == '.' or $file == '..')
            {
                continue;
            }
            if (is_file($dir . $file)) {
                $array[]=file_get_contents($dir.$file);
            }
        }
    }
    closedir($dh);
    return $array;
}

5.在同级目录下建立client文件,存放信息

PHP 即使通讯

1.socket.php 一样,使用时需要开启

<?php
    //创建websocket服务器对象,监听0.0.0.0:9502端口
    $ws = new swoole_websocket_server("0.0.0.0", 9502);

    //监听WebSocket连接打开事件
    $ws->on('open', function ($ws, $request) {
        $fd[] = $request->fd;
        $GLOBALS['fd'][] = $fd;
        //$ws->push($request->fd, "hello, welcome\n");
    });

    //监听WebSocket消息事件
    $ws->on('message', function ($ws, $frame) {
        $msg =  'from'.$frame->fd.":{$frame->data}\n";
    //var_dump($GLOBALS['fd']);
    //exit;
        foreach($GLOBALS['fd'] as $aa){
            foreach($aa as $i){
                $ws->push($i,$msg);
            }
        }
       // $ws->push($frame->fd, "server: {$frame->data}");
        // $ws->push($frame->fd, "server: {$frame->data}");
    });

    //监听WebSocket连接关闭事件
    $ws->on('close', function ($ws, $fd) {
        echo "client-{$fd} is closed\n";
    });

    $ws->start();

2.socket.html聊天页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="msg"></div>
<input type="text" id="text">
<input type="submit" value="发送数据" onclick="song()">
</body>
<script>
    var msg = document.getElementById("msg");
    var wsServer = 'ws://60.205.208.176:9502';
    //调用websocket对象建立连接:
    //参数:ws/wss(加密)://ip:port (字符串)
    var websocket = new WebSocket(wsServer);
    //onopen监听连接打开
    websocket.onopen = function (evt) {
        //websocket.readyState 属性:
        /*
        CONNECTING    0    The connection is not yet open.
        OPEN    1    The connection is open and ready to communicate.
        CLOSING    2    The connection is in the process of closing.
        CLOSED    3    The connection is closed or couldn't be opened.
        */
        msg.innerHTML = websocket.readyState;
    };

    function song(){
        var text = document.getElementById('text').value;
        document.getElementById('text').value = '';
        //向服务器发送数据
        websocket.send(text);
    }
      //监听连接关闭
//    websocket.onclose = function (evt) {
//        console.log("Disconnected");
//    };

    //onmessage 监听服务器数据推送
    websocket.onmessage = function (evt) {
        msg.innerHTML += evt.data +'<br>';
//        console.log('Retrieved data from server: ' + evt.data);
    };
//监听连接错误信息
//    websocket.onerror = function (evt, e) {
//        console.log('Error occured: ' + evt.data);
//    };

</script>
</html>

摄像头视频直播

LiveCamera是一款基于HTML5+WebSocket+PHP的视频直播系统,通过网页(HTML5)调用摄像头,通过websocket传输给PHP后端(workerman), 再由后端广播给所有在线播放网页,观看者可以通过这个播放页面实时观看摄像头拍摄的内容。此应用支持部分手机浏览器调用摄像头直播摄像头视频流。 
注意:目前不支持部署在windows系统

Demo:https://www.workerman.net/workerman-chat

实现百度网盘下载功能,必备!

很多小站应该有需要让用户下载一些东西,比如报名表什么的,前两天看过一个教程,就有利用百度网盘实现自己网站下载的方法,今天就分享出来给大家

<?php
 /*将本代码保存为bd.php 即可
利用 file_get_contents和preg_match_all、str_replace三个函数实现!
将百度网盘的$shareid 和 $uk 加入即可
例如:http://pan.baidu.com/share/link?shareid=489412&uk=101682133
自己服务器上就 localhost/bd.php?shareid=489412&uk=101682133 就可以自己下载了
*/
$shareid=$_GET['shareid'];
$uk=$_GET['uk'];
 if(isset($shareid) && isset($uk))
 {
$str = file_get_contents ("http://pan.baidu.com/share/link?shareid={$shareid}&uk={$uk}");
preg_match_all('|"dlink\\\":\\\"([^"]+)\\\",\\\"|imsU', $str, $baiduid);
$down=str_replace("\\","",$baiduid[1][1]);
 }
header("Location: ".$down);
 ?>

代码不是很多,但是个人觉得还是非常实用的.而且流量之类的用的都是百度的,也节省自己的空间不是?哈哈。

PHP写在线视频直播技术详解

本文转自:https://www.cnblogs.com/zx-admin/p/5697447.html

废话一句,如果你要做高性能服务器服务,请去读底层的东西 http tcp/ip socket 了解基础协议,你对如何建造高性能服务器会有一个深度的了解

目前楼主专注php开发,最直接的方法就是使用lnmp去直接做,搜索以下资料,发现还是行得通的,先把基础架构列出来

前端页面 php  

弹幕flash+js 数据来源是redis集群  

及时聊天 redis集群 +js长连接

礼物系统 

在线调用ffmpeg对流媒体进行转码

服务器流媒体 nginx-rtmp-module  的支持

基于HTTP的FLV/MP4 VOD点播
HLS (HTTP Live Streaming) M3U8的支持
基于http的操作(发布、播放、录制)
可以很好的协同现有的流媒体服务器以及播放器一起工作
在线调用ffmpeg对流媒体进行转码
H264/AAC音视频编码格式的支持

服务器端的并发和负载是很大的问题,在兼顾服务器数量+宽带的,后面在详解

视频加速 cdn

支持的pc 安卓 ios需要优化 因为 nginx-rtmp也是支持HLS 

视频源支持 obs 目前这个是pc开源的比较好的

安卓或者ios目前没有发现比较好的开源视频源推送的,欢迎推荐

背景和资料

目前流行的流媒体服务器

http://www.oschina.net/project/tag/111/streaming

进行综合对比,发现就PHP作为开发语言来说,nginx肯定是比较方便,因为大部分需要的东西都可以直接配置而且配置也不是很麻烦

又花了很多时间去搜索性能对比,发现nginx-rtmp的性能还是不错的,而且后期做负载和水平扩展,都是很方便的

开发文档

https://github.com/arut/nginx-rtmp-module/wiki/Directives

http://blog.csdn.net/defonds/article/details/9274479/

http://blog.csdn.net/cccallen/article/details/8440191/

所以最后决定是nginx-rtmp作为流媒体服务器,数据库上5.6+因为5.6+的版本把主从的日志复制变成了多线程复制,性能更好,配置更方便

http://www.ttlsa.com/mysql/summary-of-the-new-features-of-mysql5_6/

建议上5.7 QPS 更强,最新版,因为是全新项目,编译 的时候可以把 memory存储引擎加上,在测试服在测试比较方便

 5.7版本新特性说明

http://www.oschina.net/translate/whats-new-in-mysql-5-7-generally-available?cmp&p=4

作为需要高并发的网站,建议最好上php7,因为官方鸟哥早就说了,性能增加30%左右,如果你需要超高并发,请上golang,就并发来说,php的资源消耗是很大的

php的并发扩展来说,多进程,虽然也有多线程,但是7以上的版本的扩展不知道是否已经更新,这个也是个问题,如果你了解go语言就会发现go在并发方面做得很好

协程比多线程的资源消耗更小,而且nginx也是支持go的,但是性能怎么样,目前没有测试过 

http://blog.csdn.net/win_lin/article/details/41379799

内存数据库目前大部分都是redis集群,我也是选的这个

整体下来作为一个php来说,这样的开发成本是最低的

 目前基于php7的框架目前没有,所示自己开发一个小的耦合性低,方便可以扩展的标准mvc框架,模仿CI,目前3.X系列没有说明支持php7

据说CI 4 .x版本会支持

http://codeigniter.org.cn/forums/thread-22318-1-1.html

网站开发测试

 测试服搭建

vmware

服务器 centos 6.5 和 centos 7.2

php7.1 mysql 5.7 nginx 1.9

组件基本都是最新版


user nginx;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;


events {
worker_connections 10240;
}

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;


rtmp {
server {
listen 1935;

application mytv {  //千万不能使用myapp作为名字 ,不知道为什么就是始终无法播放 访问路径是rtmp://ip/mytv/ 可以使用vlc播放器播放,作为测试
live on;
}


application hls {
live on;
hls on;
hls_path /usr/local/nginx/hls;  //这个地址最好和
hls_fragment 5s; 
}
}
}

http {
include mime.types;
default_type application/octet-stream;


sendfile on;

access_log on; 

access_log /usr/local/nginx/html/rtmp_access.log;


server {
listen 8081;
server_name localhost 192.168.1.70 127.0.0.1;


location /hls {

types {
application/vnd.apple.mpegurl m3u8;            请注意是加上on_public url/x.php 在这个php文件做权限和id对应播放房间的判断,是根据传入的id进行生产id.m3u8文件的
video/mp2t ts;                                 访问url是http://ip/id.m3u8
}
root /usr/local/nginx/hls;

}

}

server {

listen 8080;
location /stat {

rtmp_stat all;

rtmp_stat_stylesheet stat.xsl;

}

location /stat.xsl {

root /usr/local/nginx/html/; #在nginx-rtmp-module源码根目录   查看当前服务器推流情况的xsl统计

}

}

server {

listen 8082;
location / {

root /usr/local/nginx/html/;

}
}

server {

listen 80;
location / {

root /usr/local/nginx/html/;

}
}
}


user nginx;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;


events {
worker_connections 10240;
}

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;


rtmp {
server {
listen 1935;

application mytv {  //千万不能使用myapp作为名字 ,不知道为什么就是始终无法播放 访问路径是rtmp://ip/mytv/ 可以使用vlc播放器播放,作为测试
live on;
}


application hls {
live on;
hls on;
hls_path /usr/local/nginx/hls;  //这个地址最好和
hls_fragment 5s; 
}
}
}

http {
include mime.types;
default_type application/octet-stream;


sendfile on;

access_log on; 

access_log /usr/local/nginx/html/rtmp_access.log;


server {
listen 8081;
server_name localhost 192.168.1.70 127.0.0.1;


location /hls {

types {
application/vnd.apple.mpegurl m3u8;            请注意是加上on_public url/x.php 在这个php文件做权限和id对应播放房间的判断,是根据传入的id进行生产id.m3u8文件的
video/mp2t ts;                                 访问url是http://ip/id.m3u8
}
root /usr/local/nginx/hls;

}

}

server {

listen 8080;
location /stat {

rtmp_stat all;

rtmp_stat_stylesheet stat.xsl;

}

location /stat.xsl {

root /usr/local/nginx/html/; #在nginx-rtmp-module源码根目录   查看当前服务器推流情况的xsl统计

}

}

server {

listen 8082;
location / {

root /usr/local/nginx/html/;

}
}

server {

listen 80;
location / {

root /usr/local/nginx/html/;

}
}
}

  网页测试播放器hls可以直接使用h5直接播放

rtmp可以使用 ckplayer的flash进行播放,安卓手机端目前没有测试,因为手机uc默认是没有flash,但是使用hls就可以,因为ios默认就是支持的

obs 推流地址 :rtmp://ip/mytv/ 播放也是这个 

这个配置文件会再次更新,仅供参考

./configure \
--prefix=/usr/local/nginx \
--add-module=/usr/local/src/nginx-rtmp-module-master \
--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_ssl_module \
--with-http_flv_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/tmp/nginx/client/ \
--http-proxy-temp-path=/var/tmp/nginx/proxy/ \
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/

这个编译其实已经把hls包含进去了
复制代码

 2016年8月16日16:46:20  今天下午测试,使用腾讯云作为服务器端的,rtmp测试效果延迟6-10s,本地串流到服务器,hls还没有测试

还有一个问题就是腾讯云的安全组,你需要把你的机器加入开放所有端口,默认只开放80端口,可以直接IP访问

复制代码
user  nginx;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  10240;
}

   rtmp_auto_push on;
   rtmp_auto_push_reconnect 1s;


rtmp {
    server {
      listen 1935;

      application mytv {
           live on;
      }

         
   application hls {
            live on;
            hls on;
            hls_path /usr/local/nginx/hls;
            hls_fragment 5s; 
        }
   }
}

http {
    include       mime.types;
    default_type  application/octet-stream;


    sendfile        on;

    access_log on;   
          
    access_log /usr/local/nginx/html/rtmp_access.log;


    server {
        listen       8081;
        server_name  localhost 192.168.1.170 127.0.0.1;


        location /hls {
            
            types {
               # application/vnd.apple.mpegurl m3u8;
            application/x-mpegurl m3u8;
                video/mp2t ts;
            }
            alias /usr/local/nginx/hls;
            
        }
    

    }



    server {

       listen      8080;
       location /stat {

       rtmp_stat all;

       rtmp_stat_stylesheet stat.xsl;

       }

 

       location /stat.xsl {

           root /usr/local/nginx/html/;  #在nginx-rtmp-module源码根目录

       }

   }





 server {

       listen      80;
       server_name  localhost 192.168.1.170 127.0.0.1;
       location / {

         root /usr/local/nginx/html/;
         index index.php;
       }

         location ~ \.php$ {
            root           /usr/local/nginx/html/;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            #fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
         fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }


   }
}

 播放地址 http://192.168.1.170:8081/hls/.m3u8

实际开发就会根据用户ID.m3u8 来播放,所以需要一些nginx的知识,推流地址  rtmp://192.168.1.170/hls/  在加密的串流码 里面带上用户ID,是否是大主播,等等的标识,来分流服务器,pull push cdn等

所以nginx和nginx-rtmp的详细知识很重要QQ群 247823727 博客文件如果不能下载请进群下载 

yii2的Console定时任务创建

Yii2的定时任务可以有两种写法,原理都是通过服务器的定时任务去调用

1.通过调用指定的URL访问 就相当于在浏览器中访问

2.通过console调用

下面我们就来说说Console 是如何实现定时任务的

一、首先在创建Controlle 并继承 yii\console\Controller;

<?php

namespace console\controllers;

use yii\console\Controller;

class TestController extends Controller {

public function actionIndex()

{

echo "hello world";

}

}

在yii根目录下,命令行执行

yii test/index

如果是class AaaBbbController function ActionAaaBbb

yii aaa-bbb/aaa-bbb

linux下,运行crontab -e

30 21 * * * /usr/local/php/bin/php /your_project_path/yii test/test

二、用命令行cmd测试是否成功

(一定要看好路径去执行 yii 这个文件 一定要写绝对路径)

/你的文件夹路径/yii 你的文件夹路径/console/test(控制器)/index(方法)

或者进入的你的项目目录下,例如 D:\wamp\www\smartSPACE>yii crontab/copy-db,你需要配置你的php环境变量

下例为 在console文件夹下执行控制器和方法

三、设置定时任务

linux下,运行crontab -e

30 21 * * * /usr/local/php/bin/php /your_project_path/yii test/test

*/1 * * * * /usr/local/php/bin/php /home/wwwroot/smartSPACE/yii crontab/copydb

这里根据自己需求填写

上面的例子表示每晚的21:30执行上面的定时程序

下面是定时任务设置的一些基本介绍

基本格式 :

  • * * * * command

分 时 日 月 周 命令

第1列表示分钟1~59 每分钟用*或者 */1表示

第2列表示小时1~23(0表示0点)

第3列表示日期1~31

第4列表示月份1~12

第5列标识号星期0~6(0表示星期天)

第6列要运行的命令

crontab文件的一些例子:

30 21 * * * /usr/local/etc/rc.d/lighttpd restart #上面的例子表示每晚的21:30重启apache。

45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart #上面的例子表示每月1、10、22日的4 : 45重启apache。

10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart #上面的例子表示每周六、周日的1 : 10重启apache。

0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart #上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启apache。

0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart #上面的例子表示每星期六的11 : 00 pm重启apache。

0 */1 * * * /usr/local/etc/rc.d/lighttpd restart #每一小时重启apache

例子:

*/1 * * * * /usr/local/php/bin/php /home/wwwroot/smartSPACE/yii crontab/copy-db>>/home/wwwroot/smartSPACE/commands/test.txt

注释:
一分钟重复    */1 * * * *
php目录      /usr/local/php/bin/php
项目目录      /home/wwwroot/smartSPACE/
运行的方法   yii crontab/copy-db
结果值写入那个文件  /home/wwwroot/smartSPACE/commands/test.txt

linux 上跟windows类似

/usr/local/php/bin/php /home/wwwroot/smartSPACE/yii crontab/copy-db

/usr/local/php/bin/php你的linux下的php环境位置 /home/wwwroot/smartSPACE/yii crontab/copy-db你的项目目录

给个php代码例子

<?php 

/**
 * @ 定时任务
 * @
 * @
 */

namespace app\commands;

use yii\console\Controller;
// use MongoDB\BSON\ObjectID;

class CrontabController  extends Controller
{
    /**
     * 定时清理mongodb数据
     */
    public function actionClearMongo()
    {
        $query = new \yii\mongodb\Query();
        $time_end = strtotime(date('2018-06-20'));
        $time_begin = strtotime("2018-05-30");
        $collection = \Yii::$app->mongodb->getCollection('publish_message');
        $i = 1;
        while ($time_begin < $time_end){
            $date = date("Y-m-d", $time_begin);
            $start_time = strtotime($date." 00:00:00");
            $end_time = strtotime($date." 23:30:00");
            //清除每天23:30前的数据
            $where = [
                "between","payload.timestamp", $start_time, $end_time
            ];
            $time_begin +=24*3600;
//         var_dump(new \MongoDB\BSON\UTCDateTime($end_time.'000'));die;
            $data = $query->from('publish_message')->where($where)->orderBy('created asc')->all();
//             $primaryVal = new \yii\mongodb\MongoId('000000000000000000000001');
//             dump($primaryVal);die;
//             $collection = \Yii::$app->mongodb->getCollection('publish_message');

//             var_dump((string) new \yii\MongoDB\BSON\ObjectId('000000000000000000000001'));
//             $data = $collection->find([]);

            foreach ($data as $v){
//                 var_dump($v);
                $oid = (string)$v['_id'];
                echo $i.'-'.$oid.'
    ';
                $collection->remove(['_id' => $v['_id']]);
                $i++;
            }
        }
        die;
    }

    /**
     * 定时任务获取mondb内故障消息
     * create dahai
     * time 2018/07/18
     */
    public function actionCopyDb(){
        $query = new \yii\mongodb\Query();

        //先获取上一次的结束时间
        $last_result = $query->select(['end_time'])->from('timed_task')->orderBy('_id desc')->limit(1)->one();
        $last_time = $last_result['end_time'];
        $start_time = $last_time;
        $end_time = time();

        $collection = \Yii::$app->mongodb->getCollection('timed_task');
        $collection->insert(['end_time' => $end_time]);


        $query->andWhere([
            "between","payload.timestamp", $start_time, $end_time
        ]);
        $query->andWhere(['in', 'payload.desired.arrays.0.status.event', [1,2,3,4,5,6,7]]);
        $result = $query->select(['created', 'payload'])->from('publish_message')->orderBy('created asc')->all();
        if ($result){
            //故障类型,设备别称,开关别称,故障时间
            foreach ($result as $k => $l)
            {
                //对应相关用户通知故障消息
                $deviceid = $l['payload']['deviceid'];
                $Equipment= \app\models\Equipment::find()->select('id')->where(['serial_number'=>$deviceid])->one();
                $EquipmentUser =\app\models\EquipmentUser::find()->select('user_id')->where(['equipment_id'=>$Equipment->id])->asArray()->all();
                $user_ids = array_column($EquipmentUser,'user_id');
                $created = $l['payload']['timestamp'] > 0 ? date('Y-m-d H:i', $l['payload']['timestamp']) : '---';
                $event_desc = \app\services\VStatusLog::$event[$l['payload']['desired']['arrays'][0]['status']['event']];
                //查询别名
                $eAlias = \app\models\Alias::findOne(['type'=>1,'extend_id'=>$l['payload']['deviceid'],'user_id'=>$this->uid]); //设备别名
                $sAlias = \app\models\Alias::findOne(['type'=>2,'extend_id'=>$l['payload']['desired']['arrays'][0]['device']['id'],'user_id'=>$this->uid]);//开关别名
                $alias1 = $eAlias?$eAlias['alias']:$l['payload']['deviceid'];
                $alias2 = $sAlias?$eAlias['alias']:'开关'.$l['payload']['desired']['arrays'][0]['device']['index'];
                while ($user_id = array_shift($user_ids)){
                    $FaultMessage = new \app\models\FaultMessage();
                    $FaultMessage->user_id = $user_id;
                    $FaultMessage->message_id = ($l['_id'])->__toString();
                    $FaultMessage->created = $created;
                    $FaultMessage->event = $l['payload']['desired']['arrays'][0]['status']['event'];
                    $FaultMessage->event_desc = $event_desc;
                    $FaultMessage->equipment_alias = $alias1;
                    $FaultMessage->switch_alias = $alias2;
                    $FaultMessage->create_time = time();
                    $FaultMessage->save();
                }
            }
         }else{
            echo "没有".date("Y-m-d H:i:s")."\n";
            return "没有东西";
        }
        echo "有".date("Y-m-d H:i:s")."\n";
        return "有东西";
    }

}

yii2中,关于你加载了一些数据库或者扩展依赖,你需要在添加config-console.php添加你在web.php相同的配置即可

例如我这个报错:yii\di\ServiceLocator->get(‘mongodb’) yii\mongodb\Query->all()就是因为这个导致
————————————————
原文链接:https://blog.csdn.net/qq_27229113/article/details/81103227

Yii2 配置yii2-redis扩展

Yii2-redis 不用 composer 的安装
由于 composer 是国外的源,所以用下面的方式很难成功
php composer.phar require –prefer-dist yiisoft/yii2-redis

改成手动安装redis
1、下载 yii2-redis 的文件
https://github.com/yiisoft/yii2-redis/archive/master.zip
改文件夹名为 yii2-redis,放到 vendor\yiisoft 目录下

2、编辑文件vendor\yiisoft\extensions.php:
‘yiisoft/yii2-redis’ =>
  array (
    ’name’ => ‘yiisoft/yii2-redis’,
    ’version’ => ‘2.0.14.0’,
    ’alias’ =>
      array (
        ’@yii/redis’ => $vendorDir . ‘/yiisoft/yii2-redis/src’,
      ),
  ),

3、编辑文件vendor\composer\autoload_psr4.php,加入:
‘yii\\redis\\’ => array($vendorDir . ‘/yiisoft/yii2-redis/src’),

4、编辑文件 main.php
return [
  //….
  ’components’ => [
    ’redis’ => [
      ’class’ => ‘yii\redis\Connection’,
      ’hostname’ => ‘localhost’,
      ’port’ => 6379,
      ’database’ => 0,
    ],
  ]
];