5ucms论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 7348|回复: 0
打印 上一主题 下一主题

[开发教程] 微擎系统之数据库及其表的安装分析教程

[复制链接]

670

主题

785

帖子

8273

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
8273
跳转到指定楼层
楼主
发表于 2017-5-30 07:58:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
当进入到“参数配置”后,微擎微信公众号系统的下一步安装就是根据填写好的数据库选项以及管理选项进行创建数据库并创建数据库表,执行创建数据库和数据库表的创建安装是在“参数配置”这一步点击“继续”后就开始创建。

  也就是说当在“参数配置”这一步点击“继续”,实际上是提交了“参数配置”这个网页的一个表单,在这个表单里面有以下非常重要的三个知识点:

  这个表单使用的传递方法method是:post

  表单使用一个隐藏域:
  1. <input type="hidden" name="do" id="do" />
复制代码


  当点击“继续”进行提交时把上面的隐藏域的name值do的值设置为
  1. countinue:if(check(this)){jQuery('#do').val('continue')
复制代码


当在“参数配置”里面点击“继续”将执行install.php里面的如下程序:

  1)此时,$action的值仍为db即:

  1.   $action = $_COOKIE['action'];
  2.   $action = in_array($action, $actions) ? $action : 'license';
复制代码



  在“参数配置”这一步里面使用的是get方式,即$ispost值为false,而现在提交的表单方法为post,所以,$ispost值为true:$ispost = strtolower($_SERVER['REQUEST_METHOD']) == 'post';

  这是非常重要的,因为,下面就是使用这个判断来提交表单创建数据库和数据库表。

  2)条件if($action == 'db')已经成立,此时,就要执行这里面的代码。

  在这个条件里面条件if($ispost)已经成立了,这在“参数配置”里面是不成立的,而此时是成立的。

  但是,条件if($_POST['do'] != 'continue')不成立,所以,这里面的代码不执行,这里只所以做这样一个判断就是为了防止“安装数据库”和“参数配置”这两步出问题,而导致可能系统安装出问题,如果提交的$do的值不等于continue,则立马回到“监测环境”这一步,防止安装数据库时发生错误。

  处理判断版本信息:
  1. $family = $_POST['family'] == 'x' ? 'x' : 'v';
复制代码



  获取提交过来的安装微擎系统时填写的数据库信息和后台登录信息:

  1.         $db = $_POST['db'];
  2.         $user = $_POST['user'];
复制代码


  因为,在安装时使用的是以数组形式获取填写的表单值,如下所示:

  1.   <input class="form-control" type="text" name="db[prefix]" value="ims_">
  2.   <input class="form-control" type="text" name="db[server]" value="bbs.5ucms.com">
  3.   <input class="form-control" type="text" name="db[username]" value="root">
复制代码


  也就是db是一个数组名称,里面是一个键名,value里面是这个键的一个值,类似
  1. $db=array('prefix'=>'ims_','server'=>'bbs.5ucms.com','username'=>'root')
复制代码


  如果在实际使用中可以不用设置键,只使用一个db[]这样就表示一个索引数组了,这是非常有用的。

  所以,上面的
  1. $db = $_POST['db'] = array('prefix'=>'ims_','server'=>'bbs.5ucms.com','username'=>'root')
复制代码

3)创建数据库:

  当获取到安装微擎微信公众号管理系统后,就根据填写的数据库信息进行创建数据库和表。因为,微擎使用了pdo数据库抽象层,所以,先来一个try。

  a)要创建数据库首先要连接数据库,连接数据库需要哪些参数?所以,接下来就要获取连接数据库时的参数:

  获取服务器ip或服务器域名:
  1. $pieces = explode(':', $db['server']);
复制代码



  因为,填写的服务器有可能使用非默认的端口3306,所以,处理一下要使用的另外的端口,也就是在填写表单时是否填写了非默认的端口的处理。

  这样如果在“参数配置”界面表单里面如果填写了端口,则通过上面的处理后得到的将是一个包含端口和服务器ip或域名两个元素的数组$pieces。

  服务器ip或域名:
  1. $db['server'] = $pieces[0];
复制代码



  端口:
  1. $db['port'] = !empty($pieces[1]) ? $pieces[1] : '3306';
复制代码



  连接数据库:
  1. $link = new PDO("mysql:host={$db['server']};port={$db['port']}", $db['username'], $db['password']);
复制代码



  设置编码:
  1. $link->exec("SET character_set_connection=utf8, character_set_results=utf8, character_set_client=binary");
复制代码



  设置sql执行时的模式:
  1. $link->exec("SET sql_mode=''");
复制代码



  这种模式可以很好的容错,但是,也有一定的环处,既然,官方都使用这个我们就不解释了。

  b)判断是否连接成功,这里通过一个if条件语句来处理下面的代码:

  如果连接失败则返回错误代码:

  1.             if ($link->errorCode() != '00000') {
  2.                 $errorInfo = $link->errorInfo();
  3.                 $error = $errorInfo[2];
  4.             }
复制代码



  当连接成功后返回错误处理函数errorCode()将返回一个五个零值,这样我们可以判断如果返回的值不是00000,则说明数据库连接出错。

  通过函数errorInfo()获取错误信息,通过这个函数得到的是一个包括三个元素的数组,其中第三个元素是错误提示内容,所以,上面的代码要获取$errorInfo[2]的值,即错误提示信息。

  c)开始创建数据库:

   在创建数据库前先判断一下连接好的服务器里面有没有已经存在的要创建的数据库:
  1. $link->query("SHOW DATABASES LIKE '{$db['name']}';")
复制代码



   获取一条结果:
  1. $fetch = $statement->fetch();
复制代码



  如果$fetch的值为空说明服务器里面并不存在要创建的数据库$db['name'],则进入创建。

  但是,在创建数据库前还要判断一下数据库版本,因为不同的数据库版本创建数据库时使用的sql语句略有不同,这个分界点是数据库版4.1:

  1.     if (empty($fetch)){
  2.         if (substr($link->getAttribute(PDO::ATTR_SERVER_VERSION), 0, 3) > '4.1') {
  3.             $link->query("CREATE DATABASE IF NOT EXISTS `{$db['name']}` DEFAULT CHARACTER SET utf8");
  4.         } else {
  5.             $link->query("CREATE DATABASE IF NOT EXISTS `{$db['name']}`");
  6.         }   
  7.     }
复制代码



  这样就创建了一个数据库,但是,这样就结束了吗?其实,还要判断一下创建的数据库是否成功创建,方法很简单就是查询一下数据库看看刚刚创建的数据库存不存在服务器里面。

  1.                   $statement = $link->query("SHOW DATABASES LIKE '{$db['name']}';");
  2.                 $fetch = $statement->fetch();
  3.                 if (empty($fetch)) {
  4.                     $error .= "数据库不存在且创建数据库失败. <br />";
  5.                 }
复制代码



  若获取到的查询的结果$fetch的值为空,说明没有创建好数据库,然后,提示错误信息。

  否则,如果返回的错误代码不是00000,再次报错:

  1.                  if ($link->errorCode() != '00000') {
  2.                     $errorInfo = $link->errorInfo();
  3.                     $error .= $errorInfo[2];
  4.                 }
复制代码


  注意上面也是这样的代码报错,但是,这里是在已经连接好数据库服务器后,报错处理,而上则是连接数据库时报错处理,这两者是不一样的。

  e)若上面的try里面的代码执行有问题,则抛出一个异常错误:

  1.                catch (PDOException $e) {
  2.             $error = $e->getMessage();
  3.             if (strpos($error, 'Access denied for user') !== false) {
  4.                 $error = '您的数据库访问用户名或是密码错误. <br />';
  5.             } else {
  6.                 $error = iconv('gbk', 'utf8', $error);
  7.             }
  8.         }
复制代码


4)判断数据库是否为空:

  1.         if(empty($error)) {
  2.             $link->exec("USE {$db['name']}");
  3.             $statement = $link->query("SHOW TABLES LIKE '{$db['prefix']}%';");
  4.             if ($statement->fetch()) {
  5.                 $error = '您的数据库不为空,请重新建立数据库或是清空该数据库或更改表前缀!';
  6.             }
  7.         }
复制代码



  安装微擎就是要创建一个空的数据库,这样才可以在后面把数据库表插入到数据库里面,所以,在创建完数据库以后,再次判断一下创建的数据库是否为空,难道这是多此一举,绝对不是程序就是这样逻辑严密容不得半点马虎,哪怕是一个小小的标点符号。

  5)安装数据:上面数据库已经创建好了,接下来就是把要生成文件(例如数据库配置文件、锁文件等)、和需要的文件从微擎官方下载下来,因为,安装方式有两种,一种是本地安装,一种是离线安装,所以,下面的代码还要对这两种方式进行处理。

  获取配置文件并进行相应的替换:

  1.             $config = local_config();
  2.             $cookiepre = local_salt(4) . '_';
  3.             $authkey = local_salt(8);
  4.             $config = str_replace(array(
  5.                 '{db-server}', '{db-username}', '{db-password}', '{db-port}', '{db-name}', '{db-tablepre}', '{cookiepre}', '{authkey}', '{attachdir}'
  6.             ), array(
  7.                 $db['server'], $db['username'], $db['password'], $db['port'], $db['name'], $db['prefix'], $cookiepre, $authkey, 'attachment'
  8.             ), $config);
复制代码



  也就是把刚下载下来的配置数据替换成我们在“参数配置”里面填写的数据库信息。

  引入程序版本文件:
  1. $verfile = IA_ROOT . '/framework/version.inc.php';
复制代码



  引入数据库表以及表中的数据文件:
  1. $dbfile = IA_ROOT . '/data/db.php';
复制代码



  这个db.php文件只有在本地安装也就是离线安装才有,而在线安装没有这个文件,因为,是从远程服务器安装数据库表的及其数据的。

6)如果是在线安装,即条件if($_POST['type'] == 'remote') 成立,则执行下面的代码:

  获取在线安装数据:
  1. $ins = remote_install();
复制代码


  通过这个函数就把微擎程序从微擎官方远程服务器上面下载下来保存到$ins里面了。

  在在线安装前处理连接不到服务器、链接微擎更新服务器失败和未能下载程序包三种错误:

  连接本地服务器获取程序版本号等信息:


  设置下载过来的微擎程序包临时文件名:
  1. $tmpfile = IA_ROOT . '/we7source.tmp';
复制代码



  把程序保存到临时文件$tmpfile里面:
  1. file_put_contents($tmpfile, $archive);
复制代码


  创建一个data目录:
  1. local_mkdirs(IA_ROOT . '/data');
复制代码



  获取$ins['schemas']内容并保存到db.php里面:
  1. file_put_contents(IA_ROOT . '/data/db.php', base64_decode($ins['schemas']));
复制代码


  读取文件$tmpfile的内容存放到$path目录(这个$path目录会根据我们安装的程序的位置不同而不同,例如,安装根目录则$path表示根目录):

  1.                 $fp = fopen($tmpfile, 'r');
  2.                 if ($fp) {
  3.                     $buffer = '';
  4.                     while (!feof($fp)) {
  5.                         $buffer .= fgets($fp, 4096);
  6.                         if($buffer[strlen($buffer) - 1] == "\n") {
  7.                             $pieces = explode(':', $buffer);
  8.                             $path = base64_decode($pieces[0]);
  9.                             $dat = base64_decode($pieces[1]);
  10.                             $fname = IA_ROOT . $path;
  11.                             local_mkdirs(dirname($fname));
  12.                             file_put_contents($fname, $dat);
  13.                             $buffer = '';
  14.                         }
  15.                     }
  16.                     fclose($fp);
  17.                 }
  18.                 unlink($tmpfile);
复制代码



  最后,不要忘记删除临时文件$tmpfile。

  此到,在线安装微擎系统结束。

6)离线安装:上面是在线远程安装,但是,如果您选择的是离线安装(其实,不用我们选择程序会根据您安装时的文件进行判断,自动帮我们选择哪种方式进行安装)。

    a)创建表并插入初始化数据:

  生成版本号:


如果根目录里面有文件index.php、web、版本号文件$verfile和/data/db.php文件,则表示要进行离线安装,即条件if(file_exists(IA_ROOT . '/index.php') && is_dir(IA_ROOT . '/web') && file_exists($verfile) &&file_exists($dbfile))成立。

  引入要用到的数据库表文件:
  1. $dat = require $dbfile;
复制代码



  判断一下$dat是不是空或是不是一个数组,则不进行安装数据库表,返回到上一步:

  1.                 if(empty($dat) || !is_array($dat)) {
  2.                     die('<script type="text/javascript">alert("安装包不正确, 数据安装脚本缺失.");history.back();</script>');
  3.                 }
复制代码


  遍历创建数据库表并把表中的初始数据插入到表中:

  1.                 foreach($dat['schemas'] as $schema) {
  2.                     $sql = local_create_sql($schema);
  3.                     local_run($sql);
  4.                 }
  5.                 foreach($dat['datas'] as $data) {
  6.                     local_run($data);
  7.                 }
  8.             } else {
  9.                 die('<script type="text/javascript">alert("你正在使用本地安装, 但未下载完整安装包, 请从微擎官网下载完整安装包后重试.");history.back();</script>');
  10.             }
复制代码


  这里面使用的函数local_create_sql和local_run在phpos微信网都已经详细分析了,这里不再分析。

    b)插入用户名密码:

    因为,后台的用户名和密码相对上面的表以及表中的数据来说比较敏感,所以,微擎官方单独处理(邱嵩松注,使用了sha1加密,好一些,因为MD5被破解的太多了):

  1.             $salt = local_salt(8);
  2.             $password = sha1("{$user['password']}-{$salt}-{$authkey}");
  3.             $link->exec("INSERT INTO {$db['prefix']}users (username, password, salt, joindate) VALUES('{$user['username']}', '{$password}', '{$salt}', '" . time() . "')");

复制代码

  从这里也可以知道我们在后台登录的密码是通过sha1函数进行加密处理的。

  c)生成配置文件:
  1.               local_mkdirs(IA_ROOT . '/data');
  2.             file_put_contents(IA_ROOT . '/data/config.php', $config);
复制代码



  通过函数touch()生成一个锁文件install.lock,这样再次按装程序时就根据这个文件进行判断程序是否已经安装了,如果没有这个文件说明程序还没有安装,否则,已经安装。
  1.             touch(IA_ROOT . '/data/install.lock');
  2.             setcookie('action', 'finish');
复制代码


  重新定位到当前路径并退出程序:

  1.             header('location: ?refresh');
  2.             exit();
复制代码



  到此,在线安装和离线安装微擎处理代码就结束了,当这一点结束后,就跳转到“完成”最后这一步了,即if($action == 'finish') 条件里面执行后继的操作,将在另外一个文件进行讲解。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|5ucms.com

GMT+8, 2024-6-16 18:33 , Processed in 0.046875 second(s), 34 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表