# 版本控制
簡單理解就是更新系統。(迭代更新)
核心代碼(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: