# 版本控制
简单理解就是更新系统。(迭代更新)
核心代码(SDK):
```
namespace Admin\Controller;
use Think\Model;
use Vendor\HttpDownload;
use Common\Sdk;
use Vendor\Zip;
class UpdateController extends BaseController
{
public function __construct()
{
parent::__construct();
//$this->server = C('UPDATE_URL');
//$config = M('Websiteconfig')->find();
//$this->key = $config['serverkey'];
//$this->domain = substr($_SERVER['HTTP_HOST'],strpos($_SERVER['HTTP_HOST'],'.')+1);
}
public function index()
{
$res = authUpdate();
$info = $res['data'][0]??'';
$app_id = C('APP_ID');
$version = M('version')->order('id desc')->getField('version');
$post_string = array();
$header = array("Content-Type:multipart/x-www-form-urlencoded");
$url = 'http://auth.yzq88.com/index.php/api/index/getVersion?app_id='.$app_id.'&version='.$version;
$ch = curl_init(); // 启动一个CURL会话
curl_setopt($ch, CURLOPT_URL, $url); // 要访问的地址
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查 // https请求 不验证证书和hosts
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
curl_setopt($ch, CURLOPT_POST, true); // 发送一个常规的Post请求
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string); // Post提交的数据包
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 设置超时限制防止死循环
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取的信息以文件流的形式返回
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //模拟的header头
$result = curl_exec($ch);
$result = json_decode($result, true);
if($result && $result['data']['version'] == $version){
$html = '<div id="uploading">当前已经是最新版本!当前版本号:'.$result['data']['version'].'</div>';
}else{
$html = "<div id='update'><p>更新说明:".$result['data']['remark']."</p><p>更新版本:".$result['data']['version']."</p><p id='upmsg'></p></div><div id='uploading'>检查到新版本 ".$result['data']['version'].",<a href='javascript:;' onclick=\"update('".$result['data']['package']."', '".$result['data']['version']."');\">立即升级</a></div>";
}
if(!$result){
$html = '<div id="uploading">当前已经是最新版本!</div>';
}
$this->assign('html',$html);
$this->assign('nav', array('setting', 'update', ''));//导航
$this->display();
}
public function updating()
{
set_time_limit(0);
// $res = authDownload($v);
$filepath = './Data/';//$res['data']['file'];
$url = $_GET['url'];
$v = $_GET['v'];
$arr=parse_url($url);
$fileName='update.zip';//basename($arr['path']);
$file=file_get_contents($url);
file_put_contents($filepath.$fileName,$file);
if ($filepath) {
if (!class_exists('ZipArchive')){
$this->ajaxReturn(['message'=>'您的服务器不支持php zip扩展,请配置好此扩展再来升级.']);
}
if (!is_writable($_SERVER['DOCUMENT_ROOT'].'/Application')){
$this->ajaxReturn(['message'=>'Application,设置好再升级']);
}
if (!is_writable($_SERVER['DOCUMENT_ROOT'].'/Public')){
$this->ajaxReturn(['message'=>'Public,设置好再升级']);
}
//升级包下载
// $filepath = $filename;
// $filename = 'update.zip';
$locationZipPath= "./Runtime/update/";
//$locationZipPath=iconv('utf-8', 'gbk', $locationZipPath);
if(!is_dir($locationZipPath)){
mkdir($locationZipPath);
}
$this->get_file($filepath,$fileName,$locationZipPath);
$cacheUpdateDirName = './Runtime/update/caches_upgrade/';
if(!is_dir($cacheUpdateDirName)) {
mkdir($cacheUpdateDirName);
}
$zip = new \ZipArchive();
$rs = $zip->open($filepath.$fileName);
if($rs !== TRUE) {
$this->ajaxReturn(array('message' =>'解压失败_2! Error Code:'. $rs.'!'));
}
$zip->extractTo($cacheUpdateDirName);
$zip->close();
$this->recurse_copy($cacheUpdateDirName,getcwd());
//数据库升级
$sqlstatus = true;
if (file_exists($cacheUpdateDirName.'update.sql')) {
$sql = file_get_contents($cacheUpdateDirName.'/update.sql');
$sqldata = explode(";",$sql);
$prefix = C('DB_PREFIX');
$Model = D('Updatelog');
foreach ($sqldata as $item){
if($item){
$sqlstatus = $Model->run($item);
}
}
}
// if (!$sqlstatus) {
// $this->ajaxReturn(array('message' => '数据库升级失败!请手动导入update.sql文件执行数据库升级!'));
// }
//删除升级包
$this->deletedir($locationZipPath);
@unlink(getcwd().'/update.sql');
//@unlink($locationZipPath);
$data['version'] = $v;
$data['save_time'] = date('Y-m-d');
M('version')->add($data);
$this->ajaxReturn(['message'=>'恭喜,升级成功!']);
} else {
exit('2');//参数错误
}
}
private function getRoutefile($url,$recu=0){
if (!$url){
exit('空的url请求'.$recu);
}
if (function_exists('curl_init')){
$ch = curl_init();
$header = array('Accept-Charset: utf-8');
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //优化
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
$temp = curl_exec($ch);
$headers = curl_getinfo($ch);
$haderUrl = '';
if($headers['http_code'] == 302){
$haderUrl=$headers['redirect_url'];
if (!$haderUrl){
$haderUrl=$headers['url'];
}
if (!$haderUrl){
echo 'header有空请求,请查看<br>';
var_export($headers);
exit();
}
$haderUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
return self::getRoutefile($haderUrl,1);
}
$errorno=curl_errno($ch);
curl_close($ch);
if ($errorno) {
if ($errorno==3){
echo '请求地址是:'.$url.',或者'.$haderUrl.'<br>';
}
exit(json_encode(array('message' => 'curl发生错误:错误代码'.$errorno.',如果错误代码是6,您的服务器可能无法连接我们升级服务器'),320));
}else {
return $temp;
}
}else {
$str=file_get_contents($url);
return $str;
}
}
private function recurse_copy($src,$dst) { // 原目录,复制到的目录
$now=time();
$dir = opendir($src);
@mkdir($dst);
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
if ( is_dir($src . '/' . $file) ) {
self::recurse_copy($src . '/' . $file,$dst . '/' . $file);
}
else {
if (file_exists($dst . DIRECTORY_SEPARATOR . $file)){
if (!is_writeable($dst . DIRECTORY_SEPARATOR . $file)){
exit(json_encode(['message' => $dst . DIRECTORY_SEPARATOR . $file.'不可写'],320));
}
@unlink($dst . DIRECTORY_SEPARATOR . $file);
}
if (file_exists($dst . DIRECTORY_SEPARATOR . $file)){
@unlink($dst . DIRECTORY_SEPARATOR . $file);
}
$copyrt=copy($src . DIRECTORY_SEPARATOR . $file,$dst . DIRECTORY_SEPARATOR . $file);
if (!$copyrt){
exit(json_encode(['message' => 'copy '.$dst . DIRECTORY_SEPARATOR . $file.' failed<br>'],320));
}
}
}
}
closedir($dir);
}
// private function deletedir($dirname){
public function deletedir($dirname){
// $result = false;
// if(! is_dir($dirname)){
// echo " $dirname is not a dir!";
// exit(0);
// }
// $handle = opendir($dirname); //打开目录
// while(($file = readdir($handle)) !== false) {
// if($file != '.' && $file != '..'){ //排除"."和"."
// $dir = $dirname.DIRECTORY_SEPARATOR.$file;
// //$dir是目录时递归调用deletedir,是文件则直接删除
// is_dir($dir) ? self::deletedir($dir) : unlink($dir);
// }
// }
$dh=opendir($dirname);
while ($file=readdir($dh)) {
if($file!="." && $file!="..") {
$fullpath=$dirname."/".$file;
if(!is_dir($fullpath)) {
unlink($fullpath);
} else {
$this->deletedir($fullpath);
}
}
}
}
private function get_file($url,$name,$folder = './')
{
set_time_limit((24 * 60) * 60);
// 设置超时时间
$destination_folder = $folder . '/';
// 文件下载保存目录,默认为当前文件目录
if (!is_dir($destination_folder)) {
// 判断目录是否存在
$this->mkdirs($destination_folder);
}
$newfname = $destination_folder.$name;
// 取得文件的名称
$file = fopen($url, 'rb');
// 远程下载文件,二进制模式
if ($file) {
// 如果下载成功
$newf = fopen($newfname, 'wb');
// 远在文件文件
if ($newf) {
// 如果文件保存成功
while (!feof($file)) {
// 判断附件写入是否完整
fwrite($newf, fread($file, 1024 * 8), 1024 * 8);
}
}
}
if ($file) {
fclose($file);
}
if ($newf) {
fclose($newf);
}
return true;
}
private function mkdirs($path, $mode = '0777')
{
if (!is_dir($path)) {
// 判断目录是否存在
self::mkdirs(dirname($path), $mode);
// 循环建立目录
mkdir($path, $mode);
}
return true;
}
}
```
由于需要具有一定的开发水平,我就不写那么保姆级别了,如果不会的话请直接联系我们
QQ:2236094129
wx:![](https://img.kancloud.cn/a1/9e/a19e5bfc4a2785066e6004fea0af8329_1284x2778.JPG)